]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys_common/net.rs
Rollup merge of #83393 - GuillaumeGomez:codeblock-tooltip-position, r=Nemo157
[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::ffi::CString;
7 use crate::fmt;
8 use crate::io::{self, Error, ErrorKind, IoSlice, IoSliceMut};
9 use crate::mem;
10 use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
11 use crate::ptr;
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",
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>(sock: &Socket, opt: c_int, val: c_int, payload: T) -> io::Result<()> {
62     unsafe {
63         let payload = &payload as *const T as *const c_void;
64         cvt(c::setsockopt(
65             *sock.as_inner(),
66             opt,
67             val,
68             payload,
69             mem::size_of::<T>() as c::socklen_t,
70         ))?;
71         Ok(())
72     }
73 }
74
75 pub fn getsockopt<T: Copy>(sock: &Socket, opt: c_int, val: c_int) -> io::Result<T> {
76     unsafe {
77         let mut slot: T = mem::zeroed();
78         let mut len = mem::size_of::<T>() as c::socklen_t;
79         cvt(c::getsockopt(*sock.as_inner(), opt, val, &mut slot as *mut _ as *mut _, &mut len))?;
80         assert_eq!(len as usize, mem::size_of::<T>());
81         Ok(slot)
82     }
83 }
84
85 fn sockname<F>(f: F) -> io::Result<SocketAddr>
86 where
87     F: FnOnce(*mut c::sockaddr, *mut c::socklen_t) -> c_int,
88 {
89     unsafe {
90         let mut storage: c::sockaddr_storage = mem::zeroed();
91         let mut len = mem::size_of_val(&storage) as c::socklen_t;
92         cvt(f(&mut storage as *mut _ as *mut _, &mut len))?;
93         sockaddr_to_addr(&storage, len as usize)
94     }
95 }
96
97 pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result<SocketAddr> {
98     match storage.ss_family as c_int {
99         c::AF_INET => {
100             assert!(len as usize >= mem::size_of::<c::sockaddr_in>());
101             Ok(SocketAddr::V4(FromInner::from_inner(unsafe {
102                 *(storage as *const _ as *const c::sockaddr_in)
103             })))
104         }
105         c::AF_INET6 => {
106             assert!(len as usize >= mem::size_of::<c::sockaddr_in6>());
107             Ok(SocketAddr::V6(FromInner::from_inner(unsafe {
108                 *(storage as *const _ as *const c::sockaddr_in6)
109             })))
110         }
111         _ => Err(Error::new_const(ErrorKind::InvalidInput, &"invalid argument")),
112     }
113 }
114
115 #[cfg(target_os = "android")]
116 fn to_ipv6mr_interface(value: u32) -> c_int {
117     value as c_int
118 }
119
120 #[cfg(not(target_os = "android"))]
121 fn to_ipv6mr_interface(value: u32) -> libc::c_uint {
122     value as libc::c_uint
123 }
124
125 ////////////////////////////////////////////////////////////////////////////////
126 // get_host_addresses
127 ////////////////////////////////////////////////////////////////////////////////
128
129 pub struct LookupHost {
130     original: *mut c::addrinfo,
131     cur: *mut c::addrinfo,
132     port: u16,
133 }
134
135 impl LookupHost {
136     pub fn port(&self) -> u16 {
137         self.port
138     }
139 }
140
141 impl Iterator for LookupHost {
142     type Item = SocketAddr;
143     fn next(&mut self) -> Option<SocketAddr> {
144         loop {
145             unsafe {
146                 let cur = self.cur.as_ref()?;
147                 self.cur = cur.ai_next;
148                 match sockaddr_to_addr(mem::transmute(cur.ai_addr), cur.ai_addrlen as usize) {
149                     Ok(addr) => return Some(addr),
150                     Err(_) => continue,
151                 }
152             }
153         }
154     }
155 }
156
157 unsafe impl Sync for LookupHost {}
158 unsafe impl Send for LookupHost {}
159
160 impl Drop for LookupHost {
161     fn drop(&mut self) {
162         unsafe { c::freeaddrinfo(self.original) }
163     }
164 }
165
166 impl TryFrom<&str> for LookupHost {
167     type Error = io::Error;
168
169     fn try_from(s: &str) -> io::Result<LookupHost> {
170         macro_rules! try_opt {
171             ($e:expr, $msg:expr) => {
172                 match $e {
173                     Some(r) => r,
174                     None => return Err(io::Error::new_const(io::ErrorKind::InvalidInput, &$msg)),
175                 }
176             };
177         }
178
179         // split the string by ':' and convert the second part to u16
180         let (host, port_str) = try_opt!(s.rsplit_once(':'), "invalid socket address");
181         let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
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.into_inner(),
589             imr_interface: interface.into_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.into_inner(),
605             imr_interface: interface.into_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 }