Skip to main content

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

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