#
std/sys/net/connection/
socket.rs

    1#[cfg(test)]
    2mod tests;
    3
    4use crate::ffi::{c_int, c_void};
    5use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut};
    6use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6};
    7use crate::sys::common::small_c_string::run_with_cstr;
    8use crate::sys_common::{AsInner, FromInner};
    9use crate::time::Duration;
    10use crate::{cmp, fmt, mem, ptr};
    11
    12cfg_if::cfg_if! {
    13    if #[cfg(target_os = "hermit")] {
    14        mod hermit;
    15        pub use hermit::*;
    16    } else if #[cfg(target_os = "solid_asp3")] {
    17        mod solid;
    18        pub use solid::*;
    19    } else if #[cfg(target_family = "unix")] {
    20        mod unix;
    21        pub use unix::*;
    22    } else if #[cfg(all(target_os = "wasi", target_env = "p2"))] {
    23        mod wasip2;
    24        pub use wasip2::*;
    25    } else if #[cfg(target_os = "windows")] {
    26        mod windows;
    27        pub use windows::*;
    28    }
    29}
    30
    31use netc as c;
    32
    33cfg_if::cfg_if! {
    34    if #[cfg(any(
    35        target_os = "dragonfly",
    36        target_os = "freebsd",
    37        target_os = "openbsd",
    38        target_os = "netbsd",
    39        target_os = "illumos",
    40        target_os = "solaris",
    41        target_os = "haiku",
    42        target_os = "l4re",
    43        target_os = "nto",
    44        target_os = "nuttx",
    45        target_vendor = "apple",
    46    ))] {
    47        use c::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
    48        use c::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
    49    } else {
    50        use c::IPV6_ADD_MEMBERSHIP;
    51        use c::IPV6_DROP_MEMBERSHIP;
    52    }
    53}
    54
    55cfg_if::cfg_if! {
    56    if #[cfg(any(
    57        target_os = "linux", target_os = "android",
    58        target_os = "hurd",
    59        target_os = "dragonfly", target_os = "freebsd",
    60        target_os = "openbsd", target_os = "netbsd",
    61        target_os = "solaris", target_os = "illumos",
    62        target_os = "haiku", target_os = "nto",
    63        target_os = "cygwin"))] {
    64        use libc::MSG_NOSIGNAL;
    65    } else {
    66        const MSG_NOSIGNAL: c_int = 0x0;
    67    }
    68}
    69
    70cfg_if::cfg_if! {
    71    if #[cfg(any(
    72        target_os = "dragonfly", target_os = "freebsd",
    73        target_os = "openbsd", target_os = "netbsd",
    74        target_os = "solaris", target_os = "illumos",
    75        target_os = "nto"))] {
    76        use crate::ffi::c_uchar;
    77        type IpV4MultiCastType = c_uchar;
    78    } else {
    79        type IpV4MultiCastType = c_int;
    80    }
    81}
    82
    83////////////////////////////////////////////////////////////////////////////////
    84// address conversions
    85////////////////////////////////////////////////////////////////////////////////
    86
    87fn ip_v4_addr_to_c(addr: &Ipv4Addr) -> c::in_addr {
    88    // `s_addr` is stored as BE on all machines and the array is in BE order.
    89    // So the native endian conversion method is used so that it's never swapped.
    90    c::in_addr { s_addr: u32::from_ne_bytes(addr.octets()) }
    91}
    92
    93fn ip_v6_addr_to_c(addr: &Ipv6Addr) -> c::in6_addr {
    94    c::in6_addr { s6_addr: addr.octets() }
    95}
    96
    97fn ip_v4_addr_from_c(addr: c::in_addr) -> Ipv4Addr {
    98    Ipv4Addr::from(addr.s_addr.to_ne_bytes())
    99}
    100
    101fn ip_v6_addr_from_c(addr: c::in6_addr) -> Ipv6Addr {
    102    Ipv6Addr::from(addr.s6_addr)
    103}
    104
    105fn socket_addr_v4_to_c(addr: &SocketAddrV4) -> c::sockaddr_in {
    106    c::sockaddr_in {
    107        sin_family: c::AF_INET as c::sa_family_t,
    108        sin_port: addr.port().to_be(),
    109        sin_addr: ip_v4_addr_to_c(addr.ip()),
    110        ..unsafe { mem::zeroed() }
    111    }
    112}
    113
    114fn socket_addr_v6_to_c(addr: &SocketAddrV6) -> c::sockaddr_in6 {
    115    c::sockaddr_in6 {
    116        sin6_family: c::AF_INET6 as c::sa_family_t,
    117        sin6_port: addr.port().to_be(),
    118        sin6_addr: ip_v6_addr_to_c(addr.ip()),
    119        sin6_flowinfo: addr.flowinfo(),
    120        sin6_scope_id: addr.scope_id(),
    121        ..unsafe { mem::zeroed() }
    122    }
    123}
    124
    125fn socket_addr_v4_from_c(addr: c::sockaddr_in) -> SocketAddrV4 {
    126    SocketAddrV4::new(ip_v4_addr_from_c(addr.sin_addr), u16::from_be(addr.sin_port))
    127}
    128
    129fn socket_addr_v6_from_c(addr: c::sockaddr_in6) -> SocketAddrV6 {
    130    SocketAddrV6::new(
    131        ip_v6_addr_from_c(addr.sin6_addr),
    132        u16::from_be(addr.sin6_port),
    133        addr.sin6_flowinfo,
    134        addr.sin6_scope_id,
    135    )
    136}
    137
    138/// A type with the same memory layout as `c::sockaddr`. Used in converting Rust level
    139/// SocketAddr* types into their system representation. The benefit of this specific
    140/// type over using `c::sockaddr_storage` is that this type is exactly as large as it
    141/// needs to be and not a lot larger. And it can be initialized more cleanly from Rust.
    142#[repr(C)]
    143union SocketAddrCRepr {
    144    v4: c::sockaddr_in,
    145    v6: c::sockaddr_in6,
    146}
    147
    148impl SocketAddrCRepr {
    149    fn as_ptr(&self) -> *const c::sockaddr {
    150        self as *const _ as *const c::sockaddr
    151    }
    152}
    153
    154fn socket_addr_to_c(addr: &SocketAddr) -> (SocketAddrCRepr, c::socklen_t) {
    155    match addr {
    156        SocketAddr::V4(a) => {
    157            let sockaddr = SocketAddrCRepr { v4: socket_addr_v4_to_c(a) };
    158            (sockaddr, size_of::<c::sockaddr_in>() as c::socklen_t)
    159        }
    160        SocketAddr::V6(a) => {
    161            let sockaddr = SocketAddrCRepr { v6: socket_addr_v6_to_c(a) };
    162            (sockaddr, size_of::<c::sockaddr_in6>() as c::socklen_t)
    163        }
    164    }
    165}
    166
    167unsafe fn socket_addr_from_c(
    168    storage: *const c::sockaddr_storage,
    169    len: usize,
    170) -> io::Result<SocketAddr> {
    171    match (*storage).ss_family as c_int {
    172        c::AF_INET => {
    173            assert!(len >= size_of::<c::sockaddr_in>());
    174            Ok(SocketAddr::V4(socket_addr_v4_from_c(unsafe {
    175                *(storage as *const _ as *const c::sockaddr_in)
    176            })))
    177        }
    178        c::AF_INET6 => {
    179            assert!(len >= size_of::<c::sockaddr_in6>());
    180            Ok(SocketAddr::V6(socket_addr_v6_from_c(unsafe {
    181                *(storage as *const _ as *const c::sockaddr_in6)
    182            })))
    183        }
    184        _ => Err(io::const_error!(ErrorKind::InvalidInput, "invalid argument")),
    185    }
    186}
    187
    188////////////////////////////////////////////////////////////////////////////////
    189// sockaddr and misc bindings
    190////////////////////////////////////////////////////////////////////////////////
    191
    192pub fn setsockopt<T>(
    193    sock: &Socket,
    194    level: c_int,
    195    option_name: c_int,
    196    option_value: T,
    197) -> io::Result<()> {
    198    unsafe {
    199        cvt(c::setsockopt(
    200            sock.as_raw(),
    201            level,
    202            option_name,
    203            (&raw const option_value) as *const _,
    204            size_of::<T>() as c::socklen_t,
    205        ))?;
    206        Ok(())
    207    }
    208}
    209
    210pub fn getsockopt<T: Copy>(sock: &Socket, level: c_int, option_name: c_int) -> io::Result<T> {
    211    unsafe {
    212        let mut option_value: T = mem::zeroed();
    213        let mut option_len = size_of::<T>() as c::socklen_t;
    214        cvt(c::getsockopt(
    215            sock.as_raw(),
    216            level,
    217            option_name,
    218            (&raw mut option_value) as *mut _,
    219            &mut option_len,
    220        ))?;
    221        Ok(option_value)
    222    }
    223}
    224
    225fn sockname<F>(f: F) -> io::Result<SocketAddr>
    226where
    227    F: FnOnce(*mut c::sockaddr, *mut c::socklen_t) -> c_int,
    228{
    229    unsafe {
    230        let mut storage: c::sockaddr_storage = mem::zeroed();
    231        let mut len = size_of_val(&storage) as c::socklen_t;
    232        cvt(f((&raw mut storage) as *mut _, &mut len))?;
    233        socket_addr_from_c(&storage, len as usize)
    234    }
    235}
    236
    237#[cfg(target_os = "android")]
    238fn to_ipv6mr_interface(value: u32) -> c_int {
    239    value as c_int
    240}
    241
    242#[cfg(not(target_os = "android"))]
    243fn to_ipv6mr_interface(value: u32) -> crate::ffi::c_uint {
    244    value as crate::ffi::c_uint
    245}
    246
    247////////////////////////////////////////////////////////////////////////////////
    248// get_host_addresses
    249////////////////////////////////////////////////////////////////////////////////
    250
    251pub struct LookupHost {
    252    original: *mut c::addrinfo,
    253    cur: *mut c::addrinfo,
    254    port: u16,
    255}
    256
    257impl LookupHost {
    258    pub fn port(&self) -> u16 {
    259        self.port
    260    }
    261}
    262
    263impl Iterator for LookupHost {
    264    type Item = SocketAddr;
    265    fn next(&mut self) -> Option<SocketAddr> {
    266        loop {
    267            unsafe {
    268                let cur = self.cur.as_ref()?;
    269                self.cur = cur.ai_next;
    270                match socket_addr_from_c(cur.ai_addr.cast(), cur.ai_addrlen as usize) {
    271                    Ok(addr) => return Some(addr),
    272                    Err(_) => continue,
    273                }
    274            }
    275        }
    276    }
    277}
    278
    279unsafe impl Sync for LookupHost {}
    280unsafe impl Send for LookupHost {}
    281
    282impl Drop for LookupHost {
    283    fn drop(&mut self) {
    284        unsafe { c::freeaddrinfo(self.original) }
    285    }
    286}
    287
    288impl TryFrom<&str> for LookupHost {
    289    type Error = io::Error;
    290
    291    fn try_from(s: &str) -> io::Result<LookupHost> {
    292        macro_rules! try_opt {
    293            ($e:expr, $msg:expr) => {
    294                match $e {
    295                    Some(r) => r,
    296                    None => return Err(io::const_error!(io::ErrorKind::InvalidInput, $msg)),
    297                }
    298            };
    299        }
    300
    301        // split the string by ':' and convert the second part to u16
    302        let (host, port_str) = try_opt!(s.rsplit_once(':'), "invalid socket address");
    303        let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
    304        (host, port).try_into()
    305    }
    306}
    307
    308impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
    309    type Error = io::Error;
    310
    311    fn try_from((host, port): (&'a str, u16)) -> io::Result<LookupHost> {
    312        init();
    313
    314        run_with_cstr(host.as_bytes(), &|c_host| {
    315            let mut hints: c::addrinfo = unsafe { mem::zeroed() };
    316            hints.ai_socktype = c::SOCK_STREAM;
    317            let mut res = ptr::null_mut();
    318            unsafe {
    319                cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res))
    320                    .map(|_| LookupHost { original: res, cur: res, port })
    321            }
    322        })
    323    }
    324}
    325
    326////////////////////////////////////////////////////////////////////////////////
    327// TCP streams
    328////////////////////////////////////////////////////////////////////////////////
    329
    330pub struct TcpStream {
    331    inner: Socket,
    332}
    333
    334impl TcpStream {
    335    pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
    336        let addr = addr?;
    337
    338        init();
    339
    340        let sock = Socket::new(addr, c::SOCK_STREAM)?;
    341        sock.connect(addr)?;
    342        Ok(TcpStream { inner: sock })
    343    }
    344
    345    pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
    346        init();
    347
    348        let sock = Socket::new(addr, c::SOCK_STREAM)?;
    349        sock.connect_timeout(addr, timeout)?;
    350        Ok(TcpStream { inner: sock })
    351    }
    352
    353    #[inline]
    354    pub fn socket(&self) -> &Socket {
    355        &self.inner
    356    }
    357
    358    pub fn into_socket(self) -> Socket {
    359        self.inner
    360    }
    361
    362    pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
    363        self.inner.set_timeout(dur, c::SO_RCVTIMEO)
    364    }
    365
    366    pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
    367        self.inner.set_timeout(dur, c::SO_SNDTIMEO)
    368    }
    369
    370    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
    371        self.inner.timeout(c::SO_RCVTIMEO)
    372    }
    373
    374    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
    375        self.inner.timeout(c::SO_SNDTIMEO)
    376    }
    377
    378    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
    379        self.inner.peek(buf)
    380    }
    381
    382    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
    383        self.inner.read(buf)
    384    }
    385
    386    pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> {
    387        self.inner.read_buf(buf)
    388    }
    389
    390    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
    391        self.inner.read_vectored(bufs)
    392    }
    393
    394    #[inline]
    395    pub fn is_read_vectored(&self) -> bool {
    396        self.inner.is_read_vectored()
    397    }
    398
    399    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
    400        let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
    401        let ret = cvt(unsafe {
    402            c::send(self.inner.as_raw(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
    403        })?;
    404        Ok(ret as usize)
    405    }
    406
    407    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
    408        self.inner.write_vectored(bufs)
    409    }
    410
    411    #[inline]
    412    pub fn is_write_vectored(&self) -> bool {
    413        self.inner.is_write_vectored()
    414    }
    415
    416    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
    417        sockname(|buf, len| unsafe { c::getpeername(self.inner.as_raw(), buf, len) })
    418    }
    419
    420    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
    421        sockname(|buf, len| unsafe { c::getsockname(self.inner.as_raw(), buf, len) })
    422    }
    423
    424    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
    425        self.inner.shutdown(how)
    426    }
    427
    428    pub fn duplicate(&self) -> io::Result<TcpStream> {
    429        self.inner.duplicate().map(|s| TcpStream { inner: s })
    430    }
    431
    432    pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
    433        self.inner.set_linger(linger)
    434    }
    435
    436    pub fn linger(&self) -> io::Result<Option<Duration>> {
    437        self.inner.linger()
    438    }
    439
    440    pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
    441        self.inner.set_nodelay(nodelay)
    442    }
    443
    444    pub fn nodelay(&self) -> io::Result<bool> {
    445        self.inner.nodelay()
    446    }
    447
    448    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
    449        setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
    450    }
    451
    452    pub fn ttl(&self) -> io::Result<u32> {
    453        let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
    454        Ok(raw as u32)
    455    }
    456
    457    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
    458        self.inner.take_error()
    459    }
    460
    461    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
    462        self.inner.set_nonblocking(nonblocking)
    463    }
    464}
    465
    466impl AsInner<Socket> for TcpStream {
    467    #[inline]
    468    fn as_inner(&self) -> &Socket {
    469        &self.inner
    470    }
    471}
    472
    473impl FromInner<Socket> for TcpStream {
    474    fn from_inner(socket: Socket) -> TcpStream {
    475        TcpStream { inner: socket }
    476    }
    477}
    478
    479impl fmt::Debug for TcpStream {
    480    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    481        let mut res = f.debug_struct("TcpStream");
    482
    483        if let Ok(addr) = self.socket_addr() {
    484            res.field("addr", &addr);
    485        }
    486
    487        if let Ok(peer) = self.peer_addr() {
    488            res.field("peer", &peer);
    489        }
    490
    491        let name = if cfg!(windows) { "socket" } else { "fd" };
    492        res.field(name, &self.inner.as_raw()).finish()
    493    }
    494}
    495
    496////////////////////////////////////////////////////////////////////////////////
    497// TCP listeners
    498////////////////////////////////////////////////////////////////////////////////
    499
    500pub struct TcpListener {
    501    inner: Socket,
    502}
    503
    504impl TcpListener {
    505    pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
    506        let addr = addr?;
    507
    508        init();
    509
    510        let sock = Socket::new(addr, c::SOCK_STREAM)?;
    511
    512        // On platforms with Berkeley-derived sockets, this allows to quickly
    513        // rebind a socket, without needing to wait for the OS to clean up the
    514        // previous one.
    515        //
    516        // On Windows, this allows rebinding sockets which are actively in use,
    517        // which allows “socket hijacking”, so we explicitly don't set it here.
    518        // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse
    519        #[cfg(not(windows))]
    520        setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?;
    521
    522        // Bind our new socket
    523        let (addr, len) = socket_addr_to_c(addr);
    524        cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
    525
    526        cfg_if::cfg_if! {
    527            if #[cfg(target_os = "horizon")] {
    528                // The 3DS doesn't support a big connection backlog. Sometimes
    529                // it allows up to about 37, but other times it doesn't even
    530                // accept 32. There may be a global limitation causing this.
    531                let backlog = 20;
    532            } else if #[cfg(target_os = "haiku")] {
    533                // Haiku does not support a queue length > 32
    534                // https://github.com/haiku/haiku/blob/979a0bc487864675517fb2fab28f87dc8bf43041/headers/posix/sys/socket.h#L81
    535                let backlog = 32;
    536            } else {
    537                // The default for all other platforms
    538                let backlog = 128;
    539            }
    540        }
    541
    542        // Start listening
    543        cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
    544        Ok(TcpListener { inner: sock })
    545    }
    546
    547    #[inline]
    548    pub fn socket(&self) -> &Socket {
    549        &self.inner
    550    }
    551
    552    pub fn into_socket(self) -> Socket {
    553        self.inner
    554    }
    555
    556    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
    557        sockname(|buf, len| unsafe { c::getsockname(self.inner.as_raw(), buf, len) })
    558    }
    559
    560    pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
    561        // The `accept` function will fill in the storage with the address,
    562        // so we don't need to zero it here.
    563        // reference: https://linux.die.net/man/2/accept4
    564        let mut storage: mem::MaybeUninit<c::sockaddr_storage> = mem::MaybeUninit::uninit();
    565        let mut len = size_of_val(&storage) as c::socklen_t;
    566        let sock = self.inner.accept(storage.as_mut_ptr() as *mut _, &mut len)?;
    567        let addr = unsafe { socket_addr_from_c(storage.as_ptr(), len as usize)? };
    568        Ok((TcpStream { inner: sock }, addr))
    569    }
    570
    571    pub fn duplicate(&self) -> io::Result<TcpListener> {
    572        self.inner.duplicate().map(|s| TcpListener { inner: s })
    573    }
    574
    575    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
    576        setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
    577    }
    578
    579    pub fn ttl(&self) -> io::Result<u32> {
    580        let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
    581        Ok(raw as u32)
    582    }
    583
    584    pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
    585        setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int)
    586    }
    587
    588    pub fn only_v6(&self) -> io::Result<bool> {
    589        let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY)?;
    590        Ok(raw != 0)
    591    }
    592
    593    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
    594        self.inner.take_error()
    595    }
    596
    597    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
    598        self.inner.set_nonblocking(nonblocking)
    599    }
    600}
    601
    602impl FromInner<Socket> for TcpListener {
    603    fn from_inner(socket: Socket) -> TcpListener {
    604        TcpListener { inner: socket }
    605    }
    606}
    607
    608impl fmt::Debug for TcpListener {
    609    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    610        let mut res = f.debug_struct("TcpListener");
    611
    612        if let Ok(addr) = self.socket_addr() {
    613            res.field("addr", &addr);
    614        }
    615
    616        let name = if cfg!(windows) { "socket" } else { "fd" };
    617        res.field(name, &self.inner.as_raw()).finish()
    618    }
    619}
    620
    621////////////////////////////////////////////////////////////////////////////////
    622// UDP
    623////////////////////////////////////////////////////////////////////////////////
    624
    625pub struct UdpSocket {
    626    inner: Socket,
    627}
    628
    629impl UdpSocket {
    630    pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
    631        let addr = addr?;
    632
    633        init();
    634
    635        let sock = Socket::new(addr, c::SOCK_DGRAM)?;
    636        let (addr, len) = socket_addr_to_c(addr);
    637        cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
    638        Ok(UdpSocket { inner: sock })
    639    }
    640
    641    #[inline]
    642    pub fn socket(&self) -> &Socket {
    643        &self.inner
    644    }
    645
    646    pub fn into_socket(self) -> Socket {
    647        self.inner
    648    }
    649
    650    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
    651        sockname(|buf, len| unsafe { c::getpeername(self.inner.as_raw(), buf, len) })
    652    }
    653
    654    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
    655        sockname(|buf, len| unsafe { c::getsockname(self.inner.as_raw(), buf, len) })
    656    }
    657
    658    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
    659        self.inner.recv_from(buf)
    660    }
    661
    662    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
    663        self.inner.peek_from(buf)
    664    }
    665
    666    pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
    667        let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
    668        let (dst, dstlen) = socket_addr_to_c(dst);
    669        let ret = cvt(unsafe {
    670            c::sendto(
    671                self.inner.as_raw(),
    672                buf.as_ptr() as *const c_void,
    673                len,
    674                MSG_NOSIGNAL,
    675                dst.as_ptr(),
    676                dstlen,
    677            )
    678        })?;
    679        Ok(ret as usize)
    680    }
    681
    682    pub fn duplicate(&self) -> io::Result<UdpSocket> {
    683        self.inner.duplicate().map(|s| UdpSocket { inner: s })
    684    }
    685
    686    pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
    687        self.inner.set_timeout(dur, c::SO_RCVTIMEO)
    688    }
    689
    690    pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
    691        self.inner.set_timeout(dur, c::SO_SNDTIMEO)
    692    }
    693
    694    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
    695        self.inner.timeout(c::SO_RCVTIMEO)
    696    }
    697
    698    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
    699        self.inner.timeout(c::SO_SNDTIMEO)
    700    }
    701
    702    pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
    703        setsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST, broadcast as c_int)
    704    }
    705
    706    pub fn broadcast(&self) -> io::Result<bool> {
    707        let raw: c_int = getsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST)?;
    708        Ok(raw != 0)
    709    }
    710
    711    pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
    712        setsockopt(
    713            &self.inner,
    714            c::IPPROTO_IP,
    715            c::IP_MULTICAST_LOOP,
    716            multicast_loop_v4 as IpV4MultiCastType,
    717        )
    718    }
    719
    720    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
    721        let raw: IpV4MultiCastType = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP)?;
    722        Ok(raw != 0)
    723    }
    724
    725    pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
    726        setsockopt(
    727            &self.inner,
    728            c::IPPROTO_IP,
    729            c::IP_MULTICAST_TTL,
    730            multicast_ttl_v4 as IpV4MultiCastType,
    731        )
    732    }
    733
    734    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
    735        let raw: IpV4MultiCastType = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL)?;
    736        Ok(raw as u32)
    737    }
    738
    739    pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
    740        setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP, multicast_loop_v6 as c_int)
    741    }
    742
    743    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
    744        let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP)?;
    745        Ok(raw != 0)
    746    }
    747
    748    pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
    749        let mreq = c::ip_mreq {
    750            imr_multiaddr: ip_v4_addr_to_c(multiaddr),
    751            imr_interface: ip_v4_addr_to_c(interface),
    752        };
    753        setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq)
    754    }
    755
    756    pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
    757        let mreq = c::ipv6_mreq {
    758            ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
    759            ipv6mr_interface: to_ipv6mr_interface(interface),
    760        };
    761        setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq)
    762    }
    763
    764    pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
    765        let mreq = c::ip_mreq {
    766            imr_multiaddr: ip_v4_addr_to_c(multiaddr),
    767            imr_interface: ip_v4_addr_to_c(interface),
    768        };
    769        setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq)
    770    }
    771
    772    pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
    773        let mreq = c::ipv6_mreq {
    774            ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
    775            ipv6mr_interface: to_ipv6mr_interface(interface),
    776        };
    777        setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq)
    778    }
    779
    780    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
    781        setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
    782    }
    783
    784    pub fn ttl(&self) -> io::Result<u32> {
    785        let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
    786        Ok(raw as u32)
    787    }
    788
    789    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
    790        self.inner.take_error()
    791    }
    792
    793    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
    794        self.inner.set_nonblocking(nonblocking)
    795    }
    796
    797    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
    798        self.inner.read(buf)
    799    }
    800
    801    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
    802        self.inner.peek(buf)
    803    }
    804
    805    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
    806        let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
    807        let ret = cvt(unsafe {
    808            c::send(self.inner.as_raw(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
    809        })?;
    810        Ok(ret as usize)
    811    }
    812
    813    pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> {
    814        let (addr, len) = socket_addr_to_c(addr?);
    815        cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
    816    }
    817}
    818
    819impl FromInner<Socket> for UdpSocket {
    820    fn from_inner(socket: Socket) -> UdpSocket {
    821        UdpSocket { inner: socket }
    822    }
    823}
    824
    825impl fmt::Debug for UdpSocket {
    826    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    827        let mut res = f.debug_struct("UdpSocket");
    828
    829        if let Ok(addr) = self.socket_addr() {
    830            res.field("addr", &addr);
    831        }
    832
    833        let name = if cfg!(windows) { "socket" } else { "fd" };
    834        res.field(name, &self.inner.as_raw()).finish()
    835    }
    836}