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