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