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