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