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            all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
563                let _ = limit;
564                Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
565            }
566            _ => unsafe {
567                setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int)
568            },
569        }
570    }
571
572    pub fn hop_limit_v6(&self) -> io::Result<u8> {
573        cfg_select! {
574            all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
575                Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
576            }
577            _ => {
578                let raw: c_int =
579                    unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)? };
580                Ok(raw as u8)
581            }
582        }
583    }
584
585    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
586        self.inner.take_error()
587    }
588
589    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
590        self.inner.set_nonblocking(nonblocking)
591    }
592}
593
594impl AsInner<Socket> for TcpStream {
595    #[inline]
596    fn as_inner(&self) -> &Socket {
597        &self.inner
598    }
599}
600
601impl FromInner<Socket> for TcpStream {
602    fn from_inner(socket: Socket) -> TcpStream {
603        TcpStream { inner: socket }
604    }
605}
606
607impl fmt::Debug for TcpStream {
608    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
609        let mut res = f.debug_struct("TcpStream");
610
611        if let Ok(addr) = self.socket_addr() {
612            res.field("addr", &addr);
613        }
614
615        if let Ok(peer) = self.peer_addr() {
616            res.field("peer", &peer);
617        }
618
619        let name = if cfg!(windows) { "socket" } else { "fd" };
620        res.field(name, &self.inner.as_raw()).finish()
621    }
622}
623
624////////////////////////////////////////////////////////////////////////////////
625// TCP listeners
626////////////////////////////////////////////////////////////////////////////////
627
628pub struct TcpListener {
629    inner: Socket,
630}
631
632impl TcpListener {
633    pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
634        init();
635        return each_addr(addr, inner);
636
637        fn inner(addr: &SocketAddr) -> io::Result<TcpListener> {
638            let sock = Socket::new(addr_family(addr), c::SOCK_STREAM)?;
639
640            // On platforms with Berkeley-derived sockets, this allows to quickly
641            // rebind a socket, without needing to wait for the OS to clean up the
642            // previous one.
643            //
644            // On Windows, this allows rebinding sockets which are actively in use,
645            // which allows “socket hijacking”, so we explicitly don't set it here.
646            // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse
647            #[cfg(not(windows))]
648            unsafe {
649                setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?
650            };
651
652            // Bind our new socket
653            let (addr, len) = socket_addr_to_c(addr);
654            cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
655
656            let backlog = if cfg!(target_os = "horizon") {
657                // The 3DS doesn't support a big connection backlog. Sometimes
658                // it allows up to about 37, but other times it doesn't even
659                // accept 32. There may be a global limitation causing this.
660                20
661            } else if cfg!(target_os = "haiku") {
662                // Haiku does not support a queue length > 32
663                // https://github.com/haiku/haiku/blob/979a0bc487864675517fb2fab28f87dc8bf43041/headers/posix/sys/socket.h#L81
664                32
665            } else {
666                // The default for all other platforms
667                128
668            };
669
670            // Start listening
671            cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
672            Ok(TcpListener { inner: sock })
673        }
674    }
675
676    #[inline]
677    pub fn socket(&self) -> &Socket {
678        &self.inner
679    }
680
681    pub fn into_socket(self) -> Socket {
682        self.inner
683    }
684
685    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
686        unsafe { sockname(|buf, len| c::getsockname(self.inner.as_raw(), buf, len)) }
687    }
688
689    pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
690        // The `accept` function will fill in the storage with the address,
691        // so we don't need to zero it here.
692        // reference: https://linux.die.net/man/2/accept4
693        let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit();
694        let mut len = size_of::<c::sockaddr_storage>() as c::socklen_t;
695        let sock = self.inner.accept(storage.as_mut_ptr() as *mut _, &mut len)?;
696        let addr = unsafe { socket_addr_from_c(storage.as_ptr(), len as usize)? };
697        Ok((TcpStream { inner: sock }, addr))
698    }
699
700    pub fn duplicate(&self) -> io::Result<TcpListener> {
701        self.inner.duplicate().map(|s| TcpListener { inner: s })
702    }
703
704    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
705        unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) }
706    }
707
708    pub fn ttl(&self) -> io::Result<u32> {
709        let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)? };
710        Ok(raw as u32)
711    }
712
713    pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
714        cfg_select! {
715            all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
716                let _ = limit;
717                Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
718            }
719            _ => unsafe {
720                setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int)
721            },
722        }
723    }
724
725    pub fn hop_limit_v6(&self) -> io::Result<u8> {
726        cfg_select! {
727            all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
728                Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
729            }
730            _ => {
731                let raw: c_int =
732                    unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)? };
733                Ok(raw as u8)
734            }
735        }
736    }
737
738    pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
739        unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int) }
740    }
741
742    pub fn only_v6(&self) -> io::Result<bool> {
743        let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY)? };
744        Ok(raw != 0)
745    }
746
747    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
748        self.inner.take_error()
749    }
750
751    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
752        self.inner.set_nonblocking(nonblocking)
753    }
754}
755
756impl FromInner<Socket> for TcpListener {
757    fn from_inner(socket: Socket) -> TcpListener {
758        TcpListener { inner: socket }
759    }
760}
761
762impl fmt::Debug for TcpListener {
763    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
764        let mut res = f.debug_struct("TcpListener");
765
766        if let Ok(addr) = self.socket_addr() {
767            res.field("addr", &addr);
768        }
769
770        let name = if cfg!(windows) { "socket" } else { "fd" };
771        res.field(name, &self.inner.as_raw()).finish()
772    }
773}
774
775////////////////////////////////////////////////////////////////////////////////
776// UDP
777////////////////////////////////////////////////////////////////////////////////
778
779pub struct UdpSocket {
780    inner: Socket,
781}
782
783impl UdpSocket {
784    pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
785        init();
786        return each_addr(addr, inner);
787
788        fn inner(addr: &SocketAddr) -> io::Result<UdpSocket> {
789            let sock = Socket::new(addr_family(addr), c::SOCK_DGRAM)?;
790            let (addr, len) = socket_addr_to_c(addr);
791            cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
792            Ok(UdpSocket { inner: sock })
793        }
794    }
795
796    #[inline]
797    pub fn socket(&self) -> &Socket {
798        &self.inner
799    }
800
801    pub fn into_socket(self) -> Socket {
802        self.inner
803    }
804
805    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
806        unsafe { sockname(|buf, len| c::getpeername(self.inner.as_raw(), buf, len)) }
807    }
808
809    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
810        unsafe { sockname(|buf, len| c::getsockname(self.inner.as_raw(), buf, len)) }
811    }
812
813    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
814        self.inner.recv_from(buf)
815    }
816
817    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
818        self.inner.peek_from(buf)
819    }
820
821    pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
822        if buf.len() > MAX_SEND_LEN {
823            return Err(io::Error::from_raw_os_error(c::EMSGSIZE));
824        }
825        let (dst, dstlen) = socket_addr_to_c(dst);
826        let ret = cvt(unsafe {
827            c::sendto(
828                self.inner.as_raw(),
829                buf.as_ptr() as *const c_void,
830                buf.len() as wrlen_t,
831                MSG_NOSIGNAL,
832                dst.as_ptr(),
833                dstlen,
834            )
835        })?;
836        Ok(ret as usize)
837    }
838
839    pub fn duplicate(&self) -> io::Result<UdpSocket> {
840        self.inner.duplicate().map(|s| UdpSocket { inner: s })
841    }
842
843    pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
844        self.inner.set_timeout(dur, c::SO_RCVTIMEO)
845    }
846
847    pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
848        self.inner.set_timeout(dur, c::SO_SNDTIMEO)
849    }
850
851    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
852        self.inner.timeout(c::SO_RCVTIMEO)
853    }
854
855    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
856        self.inner.timeout(c::SO_SNDTIMEO)
857    }
858
859    pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
860        unsafe { setsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST, broadcast as c_int) }
861    }
862
863    pub fn broadcast(&self) -> io::Result<bool> {
864        let raw: c_int = unsafe { getsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST)? };
865        Ok(raw != 0)
866    }
867
868    pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
869        unsafe {
870            setsockopt(
871                &self.inner,
872                c::IPPROTO_IP,
873                c::IP_MULTICAST_LOOP,
874                multicast_loop_v4 as IpV4MultiCastType,
875            )
876        }
877    }
878
879    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
880        let raw: IpV4MultiCastType =
881            unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP)? };
882        Ok(raw != 0)
883    }
884
885    pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
886        let ttl: u8 = multicast_ttl_v4
887            .try_into()
888            .map_err(|_| io::Error::from(io::ErrorKind::InvalidInput))?;
889        unsafe {
890            setsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL, ttl as IpV4MultiCastType)
891        }
892    }
893
894    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
895        let raw: IpV4MultiCastType =
896            unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL)? };
897        Ok(raw as u32)
898    }
899
900    pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
901        unsafe {
902            setsockopt(
903                &self.inner,
904                c::IPPROTO_IPV6,
905                c::IPV6_MULTICAST_LOOP,
906                multicast_loop_v6 as c_int,
907            )
908        }
909    }
910
911    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
912        let raw: c_int =
913            unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP)? };
914        Ok(raw != 0)
915    }
916
917    pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
918        let mreq = c::ip_mreq {
919            imr_multiaddr: ip_v4_addr_to_c(multiaddr),
920            imr_interface: ip_v4_addr_to_c(interface),
921        };
922        unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq) }
923    }
924
925    pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
926        let mreq = c::ipv6_mreq {
927            ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
928            ipv6mr_interface: to_ipv6mr_interface(interface),
929        };
930        unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq) }
931    }
932
933    pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
934        let mreq = c::ip_mreq {
935            imr_multiaddr: ip_v4_addr_to_c(multiaddr),
936            imr_interface: ip_v4_addr_to_c(interface),
937        };
938        unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq) }
939    }
940
941    pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
942        let mreq = c::ipv6_mreq {
943            ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
944            ipv6mr_interface: to_ipv6mr_interface(interface),
945        };
946        unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq) }
947    }
948
949    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
950        unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) }
951    }
952
953    pub fn ttl(&self) -> io::Result<u32> {
954        let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)? };
955        Ok(raw as u32)
956    }
957
958    pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
959        cfg_select! {
960            all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
961                let _ = limit;
962                Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
963            }
964            _ => unsafe {
965                setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int)
966            },
967        }
968    }
969
970    pub fn hop_limit_v6(&self) -> io::Result<u8> {
971        cfg_select! {
972            all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
973                Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
974            }
975            _ => {
976                let raw: c_int =
977                    unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)? };
978                Ok(raw as u8)
979            }
980        }
981    }
982
983    pub fn set_multicast_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
984        cfg_select! {
985            all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
986                let _ = limit;
987                Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
988            }
989            _ => unsafe {
990                setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS, limit as c_int)
991            },
992        }
993    }
994
995    pub fn multicast_hop_limit_v6(&self) -> io::Result<u8> {
996        cfg_select! {
997            all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
998                Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
999            }
1000            _ => {
1001                let raw: c_int =
1002                    unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS)? };
1003                Ok(raw as u8)
1004            }
1005        }
1006    }
1007
1008    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
1009        self.inner.take_error()
1010    }
1011
1012    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
1013        self.inner.set_nonblocking(nonblocking)
1014    }
1015
1016    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
1017        self.inner.read(buf)
1018    }
1019
1020    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
1021        self.inner.peek(buf)
1022    }
1023
1024    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
1025        if buf.len() > MAX_SEND_LEN {
1026            return Err(io::Error::from_raw_os_error(c::EMSGSIZE));
1027        }
1028        let ret = cvt(unsafe {
1029            c::send(
1030                self.inner.as_raw(),
1031                buf.as_ptr() as *const c_void,
1032                buf.len() as wrlen_t,
1033                MSG_NOSIGNAL,
1034            )
1035        })?;
1036        Ok(ret as usize)
1037    }
1038
1039    pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
1040        return each_addr(addr, |addr| inner(self, addr));
1041
1042        fn inner(this: &UdpSocket, addr: &SocketAddr) -> io::Result<()> {
1043            let (addr, len) = socket_addr_to_c(addr);
1044            cvt_r(|| unsafe { c::connect(this.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
1045        }
1046    }
1047}
1048
1049impl FromInner<Socket> for UdpSocket {
1050    fn from_inner(socket: Socket) -> UdpSocket {
1051        UdpSocket { inner: socket }
1052    }
1053}
1054
1055impl fmt::Debug for UdpSocket {
1056    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1057        let mut res = f.debug_struct("UdpSocket");
1058
1059        if let Ok(addr) = self.socket_addr() {
1060            res.field("addr", &addr);
1061        }
1062
1063        let name = if cfg!(windows) { "socket" } else { "fd" };
1064        res.field(name, &self.inner.as_raw()).finish()
1065    }
1066}