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