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