]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys_common/net.rs
Dogfood 'str_split_once()` in the std lib
[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(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(io::ErrorKind::InvalidInput, $msg)),
175                 }
176             };
177         }
178
179         // split the string by ':' and convert the second part to u16
180         let (port_str, host) = try_opt!(s.rsplit_once(':'), "invalid socket address");
181         let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
182
183         (host, port).try_into()
184     }
185 }
186
187 impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
188     type Error = io::Error;
189
190     fn try_from((host, port): (&'a str, u16)) -> io::Result<LookupHost> {
191         init();
192
193         let c_host = CString::new(host)?;
194         let mut hints: c::addrinfo = unsafe { mem::zeroed() };
195         hints.ai_socktype = c::SOCK_STREAM;
196         let mut res = ptr::null_mut();
197         unsafe {
198             cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res))
199                 .map(|_| LookupHost { original: res, cur: res, port })
200         }
201     }
202 }
203
204 ////////////////////////////////////////////////////////////////////////////////
205 // TCP streams
206 ////////////////////////////////////////////////////////////////////////////////
207
208 pub struct TcpStream {
209     inner: Socket,
210 }
211
212 impl TcpStream {
213     pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
214         let addr = addr?;
215
216         init();
217
218         let sock = Socket::new(addr, c::SOCK_STREAM)?;
219
220         let (addrp, len) = addr.into_inner();
221         cvt_r(|| unsafe { c::connect(*sock.as_inner(), addrp, len) })?;
222         Ok(TcpStream { inner: sock })
223     }
224
225     pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
226         init();
227
228         let sock = Socket::new(addr, c::SOCK_STREAM)?;
229         sock.connect_timeout(addr, timeout)?;
230         Ok(TcpStream { inner: sock })
231     }
232
233     pub fn socket(&self) -> &Socket {
234         &self.inner
235     }
236
237     pub fn into_socket(self) -> Socket {
238         self.inner
239     }
240
241     pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
242         self.inner.set_timeout(dur, c::SO_RCVTIMEO)
243     }
244
245     pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
246         self.inner.set_timeout(dur, c::SO_SNDTIMEO)
247     }
248
249     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
250         self.inner.timeout(c::SO_RCVTIMEO)
251     }
252
253     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
254         self.inner.timeout(c::SO_SNDTIMEO)
255     }
256
257     pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
258         self.inner.peek(buf)
259     }
260
261     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
262         self.inner.read(buf)
263     }
264
265     pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
266         self.inner.read_vectored(bufs)
267     }
268
269     #[inline]
270     pub fn is_read_vectored(&self) -> bool {
271         self.inner.is_read_vectored()
272     }
273
274     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
275         let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
276         let ret = cvt(unsafe {
277             c::send(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
278         })?;
279         Ok(ret as usize)
280     }
281
282     pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
283         self.inner.write_vectored(bufs)
284     }
285
286     #[inline]
287     pub fn is_write_vectored(&self) -> bool {
288         self.inner.is_write_vectored()
289     }
290
291     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
292         sockname(|buf, len| unsafe { c::getpeername(*self.inner.as_inner(), buf, len) })
293     }
294
295     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
296         sockname(|buf, len| unsafe { c::getsockname(*self.inner.as_inner(), buf, len) })
297     }
298
299     pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
300         self.inner.shutdown(how)
301     }
302
303     pub fn duplicate(&self) -> io::Result<TcpStream> {
304         self.inner.duplicate().map(|s| TcpStream { inner: s })
305     }
306
307     pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
308         self.inner.set_nodelay(nodelay)
309     }
310
311     pub fn nodelay(&self) -> io::Result<bool> {
312         self.inner.nodelay()
313     }
314
315     pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
316         setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
317     }
318
319     pub fn ttl(&self) -> io::Result<u32> {
320         let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
321         Ok(raw as u32)
322     }
323
324     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
325         self.inner.take_error()
326     }
327
328     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
329         self.inner.set_nonblocking(nonblocking)
330     }
331 }
332
333 impl FromInner<Socket> for TcpStream {
334     fn from_inner(socket: Socket) -> TcpStream {
335         TcpStream { inner: socket }
336     }
337 }
338
339 impl fmt::Debug for TcpStream {
340     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
341         let mut res = f.debug_struct("TcpStream");
342
343         if let Ok(addr) = self.socket_addr() {
344             res.field("addr", &addr);
345         }
346
347         if let Ok(peer) = self.peer_addr() {
348             res.field("peer", &peer);
349         }
350
351         let name = if cfg!(windows) { "socket" } else { "fd" };
352         res.field(name, &self.inner.as_inner()).finish()
353     }
354 }
355
356 ////////////////////////////////////////////////////////////////////////////////
357 // TCP listeners
358 ////////////////////////////////////////////////////////////////////////////////
359
360 pub struct TcpListener {
361     inner: Socket,
362 }
363
364 impl TcpListener {
365     pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
366         let addr = addr?;
367
368         init();
369
370         let sock = Socket::new(addr, c::SOCK_STREAM)?;
371
372         // On platforms with Berkeley-derived sockets, this allows to quickly
373         // rebind a socket, without needing to wait for the OS to clean up the
374         // previous one.
375         //
376         // On Windows, this allows rebinding sockets which are actively in use,
377         // which allows “socket hijacking”, so we explicitly don't set it here.
378         // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse
379         #[cfg(not(windows))]
380         setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?;
381
382         // Bind our new socket
383         let (addrp, len) = addr.into_inner();
384         cvt(unsafe { c::bind(*sock.as_inner(), addrp, len as _) })?;
385
386         // Start listening
387         cvt(unsafe { c::listen(*sock.as_inner(), 128) })?;
388         Ok(TcpListener { inner: sock })
389     }
390
391     pub fn socket(&self) -> &Socket {
392         &self.inner
393     }
394
395     pub fn into_socket(self) -> Socket {
396         self.inner
397     }
398
399     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
400         sockname(|buf, len| unsafe { c::getsockname(*self.inner.as_inner(), buf, len) })
401     }
402
403     pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
404         let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() };
405         let mut len = mem::size_of_val(&storage) as c::socklen_t;
406         let sock = self.inner.accept(&mut storage as *mut _ as *mut _, &mut len)?;
407         let addr = sockaddr_to_addr(&storage, len as usize)?;
408         Ok((TcpStream { inner: sock }, addr))
409     }
410
411     pub fn duplicate(&self) -> io::Result<TcpListener> {
412         self.inner.duplicate().map(|s| TcpListener { inner: s })
413     }
414
415     pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
416         setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
417     }
418
419     pub fn ttl(&self) -> io::Result<u32> {
420         let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
421         Ok(raw as u32)
422     }
423
424     pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
425         setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int)
426     }
427
428     pub fn only_v6(&self) -> io::Result<bool> {
429         let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY)?;
430         Ok(raw != 0)
431     }
432
433     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
434         self.inner.take_error()
435     }
436
437     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
438         self.inner.set_nonblocking(nonblocking)
439     }
440 }
441
442 impl FromInner<Socket> for TcpListener {
443     fn from_inner(socket: Socket) -> TcpListener {
444         TcpListener { inner: socket }
445     }
446 }
447
448 impl fmt::Debug for TcpListener {
449     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
450         let mut res = f.debug_struct("TcpListener");
451
452         if let Ok(addr) = self.socket_addr() {
453             res.field("addr", &addr);
454         }
455
456         let name = if cfg!(windows) { "socket" } else { "fd" };
457         res.field(name, &self.inner.as_inner()).finish()
458     }
459 }
460
461 ////////////////////////////////////////////////////////////////////////////////
462 // UDP
463 ////////////////////////////////////////////////////////////////////////////////
464
465 pub struct UdpSocket {
466     inner: Socket,
467 }
468
469 impl UdpSocket {
470     pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
471         let addr = addr?;
472
473         init();
474
475         let sock = Socket::new(addr, c::SOCK_DGRAM)?;
476         let (addrp, len) = addr.into_inner();
477         cvt(unsafe { c::bind(*sock.as_inner(), addrp, len as _) })?;
478         Ok(UdpSocket { inner: sock })
479     }
480
481     pub fn socket(&self) -> &Socket {
482         &self.inner
483     }
484
485     pub fn into_socket(self) -> Socket {
486         self.inner
487     }
488
489     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
490         sockname(|buf, len| unsafe { c::getpeername(*self.inner.as_inner(), buf, len) })
491     }
492
493     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
494         sockname(|buf, len| unsafe { c::getsockname(*self.inner.as_inner(), buf, len) })
495     }
496
497     pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
498         self.inner.recv_from(buf)
499     }
500
501     pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
502         self.inner.peek_from(buf)
503     }
504
505     pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
506         let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
507         let (dstp, dstlen) = dst.into_inner();
508         let ret = cvt(unsafe {
509             c::sendto(
510                 *self.inner.as_inner(),
511                 buf.as_ptr() as *const c_void,
512                 len,
513                 MSG_NOSIGNAL,
514                 dstp,
515                 dstlen,
516             )
517         })?;
518         Ok(ret as usize)
519     }
520
521     pub fn duplicate(&self) -> io::Result<UdpSocket> {
522         self.inner.duplicate().map(|s| UdpSocket { inner: s })
523     }
524
525     pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
526         self.inner.set_timeout(dur, c::SO_RCVTIMEO)
527     }
528
529     pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
530         self.inner.set_timeout(dur, c::SO_SNDTIMEO)
531     }
532
533     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
534         self.inner.timeout(c::SO_RCVTIMEO)
535     }
536
537     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
538         self.inner.timeout(c::SO_SNDTIMEO)
539     }
540
541     pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
542         setsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST, broadcast as c_int)
543     }
544
545     pub fn broadcast(&self) -> io::Result<bool> {
546         let raw: c_int = getsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST)?;
547         Ok(raw != 0)
548     }
549
550     pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
551         setsockopt(
552             &self.inner,
553             c::IPPROTO_IP,
554             c::IP_MULTICAST_LOOP,
555             multicast_loop_v4 as IpV4MultiCastType,
556         )
557     }
558
559     pub fn multicast_loop_v4(&self) -> io::Result<bool> {
560         let raw: IpV4MultiCastType = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP)?;
561         Ok(raw != 0)
562     }
563
564     pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
565         setsockopt(
566             &self.inner,
567             c::IPPROTO_IP,
568             c::IP_MULTICAST_TTL,
569             multicast_ttl_v4 as IpV4MultiCastType,
570         )
571     }
572
573     pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
574         let raw: IpV4MultiCastType = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL)?;
575         Ok(raw as u32)
576     }
577
578     pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
579         setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP, multicast_loop_v6 as c_int)
580     }
581
582     pub fn multicast_loop_v6(&self) -> io::Result<bool> {
583         let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP)?;
584         Ok(raw != 0)
585     }
586
587     pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
588         let mreq = c::ip_mreq {
589             imr_multiaddr: multiaddr.into_inner(),
590             imr_interface: interface.into_inner(),
591         };
592         setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq)
593     }
594
595     pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
596         let mreq = c::ipv6_mreq {
597             ipv6mr_multiaddr: *multiaddr.as_inner(),
598             ipv6mr_interface: to_ipv6mr_interface(interface),
599         };
600         setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq)
601     }
602
603     pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
604         let mreq = c::ip_mreq {
605             imr_multiaddr: multiaddr.into_inner(),
606             imr_interface: interface.into_inner(),
607         };
608         setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq)
609     }
610
611     pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
612         let mreq = c::ipv6_mreq {
613             ipv6mr_multiaddr: *multiaddr.as_inner(),
614             ipv6mr_interface: to_ipv6mr_interface(interface),
615         };
616         setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq)
617     }
618
619     pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
620         setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
621     }
622
623     pub fn ttl(&self) -> io::Result<u32> {
624         let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
625         Ok(raw as u32)
626     }
627
628     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
629         self.inner.take_error()
630     }
631
632     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
633         self.inner.set_nonblocking(nonblocking)
634     }
635
636     pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
637         self.inner.read(buf)
638     }
639
640     pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
641         self.inner.peek(buf)
642     }
643
644     pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
645         let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
646         let ret = cvt(unsafe {
647             c::send(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
648         })?;
649         Ok(ret as usize)
650     }
651
652     pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> {
653         let (addrp, len) = addr?.into_inner();
654         cvt_r(|| unsafe { c::connect(*self.inner.as_inner(), addrp, len) }).map(drop)
655     }
656 }
657
658 impl FromInner<Socket> for UdpSocket {
659     fn from_inner(socket: Socket) -> UdpSocket {
660         UdpSocket { inner: socket }
661     }
662 }
663
664 impl fmt::Debug for UdpSocket {
665     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
666         let mut res = f.debug_struct("UdpSocket");
667
668         if let Ok(addr) = self.socket_addr() {
669             res.field("addr", &addr);
670         }
671
672         let name = if cfg!(windows) { "socket" } else { "fd" };
673         res.field(name, &self.inner.as_inner()).finish()
674     }
675 }