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