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