std/sys/net/connection/
socket.rs

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