Skip to main content

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

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