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