1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use crate::{FromInner, Inner, IntoInner};
use uv::uv_udp_send_t;

callbacks! {
    pub UdpSendCB(req: UdpSendReq, status: crate::Result<u32>);
}

/// Additional data stored on the request
pub(crate) struct UdpSendDataFields<'a> {
    bufs_ptr: *mut uv::uv_buf_t,
    bufs_len: usize,
    bufs_capacity: usize,
    udp_send_cb: UdpSendCB<'a>,
}

/// Callback for uv_udp_send
pub(crate) extern "C" fn uv_udp_send_cb(req: *mut uv_udp_send_t, status: std::os::raw::c_int) {
    let dataptr = crate::Req::get_data(uv_handle!(req));
    if !dataptr.is_null() {
        unsafe {
            if let super::UdpSendData(d) = &mut *dataptr {
                let status = if status < 0 {
                    Err(crate::Error::from_inner(status as uv::uv_errno_t))
                } else {
                    Ok(status as _)
                };
                d.udp_send_cb.call(req.into_inner(), status);
            }
        }
    }

    // free memory
    let mut req = UdpSendReq::from_inner(req);
    req.destroy();
}

/// UDP Send request type
#[derive(Clone, Copy)]
pub struct UdpSendReq {
    req: *mut uv_udp_send_t,

    /// This is only guaranteed to be set if the UdpSendReq was created by new(). If it was created
    /// any other way (such as by From<*mut uv_udp_send_t>), it will not be set.
    pub(crate) bufs_ptr: *const uv::uv_buf_t,
}

impl UdpSendReq {
    /// Create a new udp send request
    pub fn new<CB: Into<UdpSendCB<'static>>>(
        bufs: &[impl crate::BufTrait],
        cb: CB,
    ) -> crate::Result<UdpSendReq> {
        let layout = std::alloc::Layout::new::<uv_udp_send_t>();
        let req = unsafe { std::alloc::alloc(layout) as *mut uv_udp_send_t };
        if req.is_null() {
            return Err(crate::Error::ENOMEM);
        }

        let (bufs_ptr, bufs_len, bufs_capacity) = bufs.into_inner();
        let udp_send_cb = cb.into();
        crate::Req::initialize_data(
            uv_handle!(req),
            super::UdpSendData(UdpSendDataFields {
                bufs_ptr,
                bufs_len,
                bufs_capacity,
                udp_send_cb,
            }),
        );

        Ok(UdpSendReq { req, bufs_ptr })
    }

    /// UDP handle where this send request is taking place.
    pub fn handle(&self) -> crate::UdpHandle {
        unsafe { (*self.req).handle }.into_inner()
    }

    pub fn destroy(&mut self) {
        let dataptr = crate::Req::get_data(uv_handle!(self.req));
        if !dataptr.is_null() {
            if let super::UdpSendData(d) = unsafe { &mut *dataptr } {
                if !d.bufs_ptr.is_null() {
                    // This will destroy the Vec<uv_buf_t>, but will not actually deallocate the
                    // uv_buf_t's themselves. That's up to the user to do.
                    unsafe {
                        std::mem::drop(Vec::from_raw_parts(d.bufs_ptr, d.bufs_len, d.bufs_capacity))
                    };
                }
            }
        }

        crate::Req::free_data(uv_handle!(self.req));

        let layout = std::alloc::Layout::new::<uv_udp_send_t>();
        unsafe { std::alloc::dealloc(self.req as _, layout) }
    }
}

impl FromInner<*mut uv_udp_send_t> for UdpSendReq {
    fn from_inner(req: *mut uv_udp_send_t) -> UdpSendReq {
        UdpSendReq {
            req,
            bufs_ptr: std::ptr::null(),
        }
    }
}

impl Inner<*mut uv_udp_send_t> for UdpSendReq {
    fn inner(&self) -> *mut uv_udp_send_t {
        self.req
    }
}

impl Inner<*mut uv::uv_req_t> for UdpSendReq {
    fn inner(&self) -> *mut uv::uv_req_t {
        uv_handle!(self.req)
    }
}

impl From<UdpSendReq> for crate::Req {
    fn from(udp_send: UdpSendReq) -> crate::Req {
        crate::Req::from_inner(Inner::<*mut uv::uv_req_t>::inner(&udp_send))
    }
}

impl crate::ToReq for UdpSendReq {
    fn to_req(&self) -> crate::Req {
        crate::Req::from_inner(Inner::<*mut uv::uv_req_t>::inner(self))
    }
}

impl crate::ReqTrait for UdpSendReq {}