socket2/
socket.rs

1// Copyright 2015 The Rust Project Developers.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use std::fmt;
10use std::io::{self, Read, Write};
11#[cfg(not(target_os = "redox"))]
12use std::io::{IoSlice, IoSliceMut};
13use std::mem::MaybeUninit;
14#[cfg(not(target_os = "nto"))]
15use std::net::Ipv6Addr;
16use std::net::{self, Ipv4Addr, Shutdown};
17#[cfg(unix)]
18use std::os::unix::io::{FromRawFd, IntoRawFd};
19#[cfg(windows)]
20use std::os::windows::io::{FromRawSocket, IntoRawSocket};
21use std::time::Duration;
22
23use crate::sys::{self, c_int, getsockopt, setsockopt, Bool};
24#[cfg(all(unix, not(target_os = "redox")))]
25use crate::MsgHdrMut;
26use crate::{Domain, Protocol, SockAddr, TcpKeepalive, Type};
27#[cfg(not(target_os = "redox"))]
28use crate::{MaybeUninitSlice, MsgHdr, RecvFlags};
29
30/// Owned wrapper around a system socket.
31///
32/// This type simply wraps an instance of a file descriptor (`c_int`) on Unix
33/// and an instance of `SOCKET` on Windows. This is the main type exported by
34/// this crate and is intended to mirror the raw semantics of sockets on
35/// platforms as closely as possible. Almost all methods correspond to
36/// precisely one libc or OS API call which is essentially just a "Rustic
37/// translation" of what's below.
38///
39/// ## Converting to and from other types
40///
41/// This type can be freely converted into the network primitives provided by
42/// the standard library, such as [`TcpStream`] or [`UdpSocket`], using the
43/// [`From`] trait, see the example below.
44///
45/// [`TcpStream`]: std::net::TcpStream
46/// [`UdpSocket`]: std::net::UdpSocket
47///
48/// # Notes
49///
50/// Some methods that set options on `Socket` require two system calls to set
51/// their options without overwriting previously set options. We do this by
52/// first getting the current settings, applying the desired changes, and then
53/// updating the settings. This means that the operation is **not** atomic. This
54/// can lead to a data race when two threads are changing options in parallel.
55///
56/// # Examples
57/// ```no_run
58/// # fn main() -> std::io::Result<()> {
59/// use std::net::{SocketAddr, TcpListener};
60/// use socket2::{Socket, Domain, Type};
61///
62/// // create a TCP listener
63/// let socket = Socket::new(Domain::IPV6, Type::STREAM, None)?;
64///
65/// let address: SocketAddr = "[::1]:12345".parse().unwrap();
66/// let address = address.into();
67/// socket.bind(&address)?;
68/// socket.listen(128)?;
69///
70/// let listener: TcpListener = socket.into();
71/// // ...
72/// # drop(listener);
73/// # Ok(()) }
74/// ```
75pub struct Socket {
76    inner: Inner,
77}
78
79/// Store a `TcpStream` internally to take advantage of its niche optimizations on Unix platforms.
80pub(crate) type Inner = std::net::TcpStream;
81
82impl Socket {
83    /// # Safety
84    ///
85    /// The caller must ensure `raw` is a valid file descriptor/socket. NOTE:
86    /// this should really be marked `unsafe`, but this being an internal
87    /// function, often passed as mapping function, it's makes it very
88    /// inconvenient to mark it as `unsafe`.
89    pub(crate) fn from_raw(raw: sys::Socket) -> Socket {
90        Socket {
91            inner: unsafe {
92                // SAFETY: the caller must ensure that `raw` is a valid file
93                // descriptor, but when it isn't it could return I/O errors, or
94                // potentially close a fd it doesn't own. All of that isn't
95                // memory unsafe, so it's not desired but never memory unsafe or
96                // causes UB.
97                //
98                // However there is one exception. We use `TcpStream` to
99                // represent the `Socket` internally (see `Inner` type),
100                // `TcpStream` has a layout optimisation that doesn't allow for
101                // negative file descriptors (as those are always invalid).
102                // Violating this assumption (fd never negative) causes UB,
103                // something we don't want. So check for that we have this
104                // `assert!`.
105                #[cfg(unix)]
106                assert!(raw >= 0, "tried to create a `Socket` with an invalid fd");
107                sys::socket_from_raw(raw)
108            },
109        }
110    }
111
112    pub(crate) fn as_raw(&self) -> sys::Socket {
113        sys::socket_as_raw(&self.inner)
114    }
115
116    pub(crate) fn into_raw(self) -> sys::Socket {
117        sys::socket_into_raw(self.inner)
118    }
119
120    /// Creates a new socket and sets common flags.
121    ///
122    /// This function corresponds to `socket(2)` on Unix and `WSASocketW` on
123    /// Windows.
124    ///
125    /// On Unix-like systems, the close-on-exec flag is set on the new socket.
126    /// Additionally, on Apple platforms `SOCK_NOSIGPIPE` is set. On Windows,
127    /// the socket is made non-inheritable.
128    ///
129    /// [`Socket::new_raw`] can be used if you don't want these flags to be set.
130    #[doc = man_links!(socket(2))]
131    pub fn new(domain: Domain, ty: Type, protocol: Option<Protocol>) -> io::Result<Socket> {
132        let ty = set_common_type(ty);
133        Socket::new_raw(domain, ty, protocol).and_then(set_common_flags)
134    }
135
136    /// Creates a new socket ready to be configured.
137    ///
138    /// This function corresponds to `socket(2)` on Unix and `WSASocketW` on
139    /// Windows and simply creates a new socket, no other configuration is done.
140    pub fn new_raw(domain: Domain, ty: Type, protocol: Option<Protocol>) -> io::Result<Socket> {
141        let protocol = protocol.map_or(0, |p| p.0);
142        sys::socket(domain.0, ty.0, protocol).map(Socket::from_raw)
143    }
144
145    /// Creates a pair of sockets which are connected to each other.
146    ///
147    /// This function corresponds to `socketpair(2)`.
148    ///
149    /// This function sets the same flags as in done for [`Socket::new`],
150    /// [`Socket::pair_raw`] can be used if you don't want to set those flags.
151    #[doc = man_links!(unix: socketpair(2))]
152    #[cfg(all(feature = "all", unix))]
153    #[cfg_attr(docsrs, doc(cfg(all(feature = "all", unix))))]
154    pub fn pair(
155        domain: Domain,
156        ty: Type,
157        protocol: Option<Protocol>,
158    ) -> io::Result<(Socket, Socket)> {
159        let ty = set_common_type(ty);
160        let (a, b) = Socket::pair_raw(domain, ty, protocol)?;
161        let a = set_common_flags(a)?;
162        let b = set_common_flags(b)?;
163        Ok((a, b))
164    }
165
166    /// Creates a pair of sockets which are connected to each other.
167    ///
168    /// This function corresponds to `socketpair(2)`.
169    #[cfg(all(feature = "all", unix))]
170    #[cfg_attr(docsrs, doc(cfg(all(feature = "all", unix))))]
171    pub fn pair_raw(
172        domain: Domain,
173        ty: Type,
174        protocol: Option<Protocol>,
175    ) -> io::Result<(Socket, Socket)> {
176        let protocol = protocol.map_or(0, |p| p.0);
177        sys::socketpair(domain.0, ty.0, protocol)
178            .map(|[a, b]| (Socket::from_raw(a), Socket::from_raw(b)))
179    }
180
181    /// Binds this socket to the specified address.
182    ///
183    /// This function directly corresponds to the `bind(2)` function on Windows
184    /// and Unix.
185    #[doc = man_links!(bind(2))]
186    pub fn bind(&self, address: &SockAddr) -> io::Result<()> {
187        sys::bind(self.as_raw(), address)
188    }
189
190    /// Initiate a connection on this socket to the specified address.
191    ///
192    /// This function directly corresponds to the `connect(2)` function on
193    /// Windows and Unix.
194    ///
195    /// An error will be returned if `listen` or `connect` has already been
196    /// called on this builder.
197    #[doc = man_links!(connect(2))]
198    ///
199    /// # Notes
200    ///
201    /// When using a non-blocking connect (by setting the socket into
202    /// non-blocking mode before calling this function), socket option can't be
203    /// set *while connecting*. This will cause errors on Windows. Socket
204    /// options can be safely set before and after connecting the socket.
205    ///
206    /// On Cygwin, a Unix domain socket connect blocks until the server accepts
207    /// it. If the behavior is not expected, try [`Socket::set_no_peercred`]
208    /// (Cygwin only).
209    #[allow(rustdoc::broken_intra_doc_links)] // Socket::set_no_peercred
210    pub fn connect(&self, address: &SockAddr) -> io::Result<()> {
211        sys::connect(self.as_raw(), address)
212    }
213
214    /// Initiate a connection on this socket to the specified address, only
215    /// only waiting for a certain period of time for the connection to be
216    /// established.
217    ///
218    /// Unlike many other methods on `Socket`, this does *not* correspond to a
219    /// single C function. It sets the socket to nonblocking mode, connects via
220    /// connect(2), and then waits for the connection to complete with poll(2)
221    /// on Unix and select on Windows. When the connection is complete, the
222    /// socket is set back to blocking mode. On Unix, this will loop over
223    /// `EINTR` errors.
224    ///
225    /// # Warnings
226    ///
227    /// The non-blocking state of the socket is overridden by this function -
228    /// it will be returned in blocking mode on success, and in an indeterminate
229    /// state on failure.
230    ///
231    /// If the connection request times out, it may still be processing in the
232    /// background - a second call to `connect` or `connect_timeout` may fail.
233    pub fn connect_timeout(&self, addr: &SockAddr, timeout: Duration) -> io::Result<()> {
234        self.set_nonblocking(true)?;
235        let res = self.connect(addr);
236        self.set_nonblocking(false)?;
237
238        match res {
239            Ok(()) => return Ok(()),
240            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
241            #[cfg(unix)]
242            Err(ref e) if e.raw_os_error() == Some(libc::EINPROGRESS) => {}
243            Err(e) => return Err(e),
244        }
245
246        sys::poll_connect(self, timeout)
247    }
248
249    /// Mark a socket as ready to accept incoming connection requests using
250    /// [`Socket::accept()`].
251    ///
252    /// This function directly corresponds to the `listen(2)` function on
253    /// Windows and Unix.
254    ///
255    /// An error will be returned if `listen` or `connect` has already been
256    /// called on this builder.
257    #[doc = man_links!(listen(2))]
258    pub fn listen(&self, backlog: c_int) -> io::Result<()> {
259        sys::listen(self.as_raw(), backlog)
260    }
261
262    /// Accept a new incoming connection from this listener.
263    ///
264    /// This function uses `accept4(2)` on platforms that support it and
265    /// `accept(2)` platforms that do not.
266    ///
267    /// This function sets the same flags as in done for [`Socket::new`],
268    /// [`Socket::accept_raw`] can be used if you don't want to set those flags.
269    #[doc = man_links!(accept(2))]
270    ///
271    /// # Notes
272    ///
273    /// On Cygwin, a Unix domain socket connect blocks until the server accepts
274    /// it. If the behavior is not expected, try [`Socket::set_no_peercred`]
275    /// (Cygwin only).
276    #[allow(rustdoc::broken_intra_doc_links)] // Socket::set_no_peercred
277    pub fn accept(&self) -> io::Result<(Socket, SockAddr)> {
278        // Use `accept4` on platforms that support it.
279        #[cfg(any(
280            target_os = "android",
281            target_os = "dragonfly",
282            target_os = "freebsd",
283            target_os = "fuchsia",
284            target_os = "illumos",
285            target_os = "linux",
286            target_os = "netbsd",
287            target_os = "openbsd",
288            target_os = "cygwin",
289        ))]
290        return self._accept4(libc::SOCK_CLOEXEC);
291
292        // Fall back to `accept` on platforms that do not support `accept4`.
293        #[cfg(not(any(
294            target_os = "android",
295            target_os = "dragonfly",
296            target_os = "freebsd",
297            target_os = "fuchsia",
298            target_os = "illumos",
299            target_os = "linux",
300            target_os = "netbsd",
301            target_os = "openbsd",
302            target_os = "cygwin",
303        )))]
304        {
305            let (socket, addr) = self.accept_raw()?;
306            let socket = set_common_flags(socket)?;
307            // `set_common_flags` does not disable inheritance on Windows because `Socket::new`
308            // unlike `accept` is able to create the socket with inheritance disabled.
309            #[cfg(windows)]
310            socket._set_no_inherit(true)?;
311            Ok((socket, addr))
312        }
313    }
314
315    /// Accept a new incoming connection from this listener.
316    ///
317    /// This function directly corresponds to the `accept(2)` function on
318    /// Windows and Unix.
319    pub fn accept_raw(&self) -> io::Result<(Socket, SockAddr)> {
320        sys::accept(self.as_raw()).map(|(inner, addr)| (Socket::from_raw(inner), addr))
321    }
322
323    /// Returns the socket address of the local half of this socket.
324    ///
325    /// This function directly corresponds to the `getsockname(2)` function on
326    /// Windows and Unix.
327    #[doc = man_links!(getsockname(2))]
328    ///
329    /// # Notes
330    ///
331    /// Depending on the OS this may return an error if the socket is not
332    /// [bound].
333    ///
334    /// [bound]: Socket::bind
335    pub fn local_addr(&self) -> io::Result<SockAddr> {
336        sys::getsockname(self.as_raw())
337    }
338
339    /// Returns the socket address of the remote peer of this socket.
340    ///
341    /// This function directly corresponds to the `getpeername(2)` function on
342    /// Windows and Unix.
343    #[doc = man_links!(getpeername(2))]
344    ///
345    /// # Notes
346    ///
347    /// This returns an error if the socket is not [`connect`ed].
348    ///
349    /// [`connect`ed]: Socket::connect
350    pub fn peer_addr(&self) -> io::Result<SockAddr> {
351        sys::getpeername(self.as_raw())
352    }
353
354    /// Returns the [`Type`] of this socket by checking the `SO_TYPE` option on
355    /// this socket.
356    pub fn r#type(&self) -> io::Result<Type> {
357        unsafe { getsockopt::<c_int>(self.as_raw(), sys::SOL_SOCKET, sys::SO_TYPE).map(Type) }
358    }
359
360    /// Creates a new independently owned handle to the underlying socket.
361    ///
362    /// # Notes
363    ///
364    /// On Unix this uses `F_DUPFD_CLOEXEC` and thus sets the `FD_CLOEXEC` on
365    /// the returned socket.
366    ///
367    /// On Windows this uses `WSA_FLAG_NO_HANDLE_INHERIT` setting inheriting to
368    /// false.
369    ///
370    /// On Windows this can **not** be used function cannot be used on a
371    /// QOS-enabled socket, see
372    /// <https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsaduplicatesocketw>.
373    pub fn try_clone(&self) -> io::Result<Socket> {
374        sys::try_clone(self.as_raw()).map(Socket::from_raw)
375    }
376
377    /// Returns true if this socket is set to nonblocking mode, false otherwise.
378    ///
379    /// # Notes
380    ///
381    /// On Unix this corresponds to calling `fcntl` returning the value of
382    /// `O_NONBLOCK`.
383    ///
384    /// On Windows it is not possible retrieve the nonblocking mode status.
385    #[cfg(all(feature = "all", unix))]
386    #[cfg_attr(docsrs, doc(cfg(all(feature = "all", unix))))]
387    pub fn nonblocking(&self) -> io::Result<bool> {
388        sys::nonblocking(self.as_raw())
389    }
390
391    /// Moves this socket into or out of nonblocking mode.
392    ///
393    /// # Notes
394    ///
395    /// On Unix this corresponds to calling `fcntl` (un)setting `O_NONBLOCK`.
396    ///
397    /// On Windows this corresponds to calling `ioctlsocket` (un)setting
398    /// `FIONBIO`.
399    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
400        sys::set_nonblocking(self.as_raw(), nonblocking)
401    }
402
403    /// Shuts down the read, write, or both halves of this connection.
404    ///
405    /// This function will cause all pending and future I/O on the specified
406    /// portions to return immediately with an appropriate value.
407    #[doc = man_links!(shutdown(2))]
408    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
409        sys::shutdown(self.as_raw(), how)
410    }
411
412    /// Receives data on the socket from the remote address to which it is
413    /// connected.
414    ///
415    /// The [`connect`] method will connect this socket to a remote address.
416    /// This method might fail if the socket is not connected.
417    #[doc = man_links!(recv(2))]
418    ///
419    /// [`connect`]: Socket::connect
420    ///
421    /// # Safety
422    ///
423    /// Normally casting a `&mut [u8]` to `&mut [MaybeUninit<u8>]` would be
424    /// unsound, as that allows us to write uninitialised bytes to the buffer.
425    /// However this implementation promises to not write uninitialised bytes to
426    /// the `buf`fer and passes it directly to `recv(2)` system call. This
427    /// promise ensures that this function can be called using a `buf`fer of
428    /// type `&mut [u8]`.
429    ///
430    /// Note that the [`io::Read::read`] implementation calls this function with
431    /// a `buf`fer of type `&mut [u8]`, allowing initialised buffers to be used
432    /// without using `unsafe`.
433    pub fn recv(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
434        self.recv_with_flags(buf, 0)
435    }
436
437    /// Receives out-of-band (OOB) data on the socket from the remote address to
438    /// which it is connected by setting the `MSG_OOB` flag for this call.
439    ///
440    /// For more information, see [`recv`], [`out_of_band_inline`].
441    ///
442    /// [`recv`]: Socket::recv
443    /// [`out_of_band_inline`]: Socket::out_of_band_inline
444    #[cfg_attr(target_os = "redox", allow(rustdoc::broken_intra_doc_links))]
445    pub fn recv_out_of_band(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
446        self.recv_with_flags(buf, sys::MSG_OOB)
447    }
448
449    /// Identical to [`recv`] but allows for specification of arbitrary flags to
450    /// the underlying `recv` call.
451    ///
452    /// [`recv`]: Socket::recv
453    pub fn recv_with_flags(
454        &self,
455        buf: &mut [MaybeUninit<u8>],
456        flags: sys::c_int,
457    ) -> io::Result<usize> {
458        sys::recv(self.as_raw(), buf, flags)
459    }
460
461    /// Receives data on the socket from the remote address to which it is
462    /// connected. Unlike [`recv`] this allows passing multiple buffers.
463    ///
464    /// The [`connect`] method will connect this socket to a remote address.
465    /// This method might fail if the socket is not connected.
466    ///
467    /// In addition to the number of bytes read, this function returns the flags
468    /// for the received message. See [`RecvFlags`] for more information about
469    /// the returned flags.
470    #[doc = man_links!(recvmsg(2))]
471    ///
472    /// [`recv`]: Socket::recv
473    /// [`connect`]: Socket::connect
474    ///
475    /// # Safety
476    ///
477    /// Normally casting a `IoSliceMut` to `MaybeUninitSlice` would be unsound,
478    /// as that allows us to write uninitialised bytes to the buffer. However
479    /// this implementation promises to not write uninitialised bytes to the
480    /// `bufs` and passes it directly to `recvmsg(2)` system call. This promise
481    /// ensures that this function can be called using `bufs` of type `&mut
482    /// [IoSliceMut]`.
483    ///
484    /// Note that the [`io::Read::read_vectored`] implementation calls this
485    /// function with `buf`s of type `&mut [IoSliceMut]`, allowing initialised
486    /// buffers to be used without using `unsafe`.
487    #[cfg(not(target_os = "redox"))]
488    #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
489    pub fn recv_vectored(
490        &self,
491        bufs: &mut [MaybeUninitSlice<'_>],
492    ) -> io::Result<(usize, RecvFlags)> {
493        self.recv_vectored_with_flags(bufs, 0)
494    }
495
496    /// Identical to [`recv_vectored`] but allows for specification of arbitrary
497    /// flags to the underlying `recvmsg`/`WSARecv` call.
498    ///
499    /// [`recv_vectored`]: Socket::recv_vectored
500    ///
501    /// # Safety
502    ///
503    /// `recv_from_vectored` makes the same safety guarantees regarding `bufs`
504    /// as [`recv_vectored`].
505    ///
506    /// [`recv_vectored`]: Socket::recv_vectored
507    #[cfg(not(target_os = "redox"))]
508    #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
509    pub fn recv_vectored_with_flags(
510        &self,
511        bufs: &mut [MaybeUninitSlice<'_>],
512        flags: c_int,
513    ) -> io::Result<(usize, RecvFlags)> {
514        sys::recv_vectored(self.as_raw(), bufs, flags)
515    }
516
517    /// Receives data on the socket from the remote adress to which it is
518    /// connected, without removing that data from the queue. On success,
519    /// returns the number of bytes peeked.
520    ///
521    /// Successive calls return the same data. This is accomplished by passing
522    /// `MSG_PEEK` as a flag to the underlying `recv` system call.
523    ///
524    /// # Safety
525    ///
526    /// `peek` makes the same safety guarantees regarding the `buf`fer as
527    /// [`recv`].
528    ///
529    /// [`recv`]: Socket::recv
530    pub fn peek(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
531        self.recv_with_flags(buf, sys::MSG_PEEK)
532    }
533
534    /// Receives data from the socket. On success, returns the number of bytes
535    /// read and the address from whence the data came.
536    #[doc = man_links!(recvfrom(2))]
537    ///
538    /// # Safety
539    ///
540    /// `recv_from` makes the same safety guarantees regarding the `buf`fer as
541    /// [`recv`].
542    ///
543    /// [`recv`]: Socket::recv
544    pub fn recv_from(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<(usize, SockAddr)> {
545        self.recv_from_with_flags(buf, 0)
546    }
547
548    /// Identical to [`recv_from`] but allows for specification of arbitrary
549    /// flags to the underlying `recvfrom` call.
550    ///
551    /// [`recv_from`]: Socket::recv_from
552    pub fn recv_from_with_flags(
553        &self,
554        buf: &mut [MaybeUninit<u8>],
555        flags: c_int,
556    ) -> io::Result<(usize, SockAddr)> {
557        sys::recv_from(self.as_raw(), buf, flags)
558    }
559
560    /// Receives data from the socket. Returns the amount of bytes read, the
561    /// [`RecvFlags`] and the remote address from the data is coming. Unlike
562    /// [`recv_from`] this allows passing multiple buffers.
563    #[doc = man_links!(recvmsg(2))]
564    ///
565    /// [`recv_from`]: Socket::recv_from
566    ///
567    /// # Safety
568    ///
569    /// `recv_from_vectored` makes the same safety guarantees regarding `bufs`
570    /// as [`recv_vectored`].
571    ///
572    /// [`recv_vectored`]: Socket::recv_vectored
573    #[cfg(not(target_os = "redox"))]
574    #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
575    pub fn recv_from_vectored(
576        &self,
577        bufs: &mut [MaybeUninitSlice<'_>],
578    ) -> io::Result<(usize, RecvFlags, SockAddr)> {
579        self.recv_from_vectored_with_flags(bufs, 0)
580    }
581
582    /// Identical to [`recv_from_vectored`] but allows for specification of
583    /// arbitrary flags to the underlying `recvmsg`/`WSARecvFrom` call.
584    ///
585    /// [`recv_from_vectored`]: Socket::recv_from_vectored
586    ///
587    /// # Safety
588    ///
589    /// `recv_from_vectored` makes the same safety guarantees regarding `bufs`
590    /// as [`recv_vectored`].
591    ///
592    /// [`recv_vectored`]: Socket::recv_vectored
593    #[cfg(not(target_os = "redox"))]
594    #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
595    pub fn recv_from_vectored_with_flags(
596        &self,
597        bufs: &mut [MaybeUninitSlice<'_>],
598        flags: c_int,
599    ) -> io::Result<(usize, RecvFlags, SockAddr)> {
600        sys::recv_from_vectored(self.as_raw(), bufs, flags)
601    }
602
603    /// Receives data from the socket, without removing it from the queue.
604    ///
605    /// Successive calls return the same data. This is accomplished by passing
606    /// `MSG_PEEK` as a flag to the underlying `recvfrom` system call.
607    ///
608    /// On success, returns the number of bytes peeked and the address from
609    /// whence the data came.
610    ///
611    /// # Safety
612    ///
613    /// `peek_from` makes the same safety guarantees regarding the `buf`fer as
614    /// [`recv`].
615    ///
616    /// # Note: Datagram Sockets
617    /// For datagram sockets, the behavior of this method when `buf` is smaller than
618    /// the datagram at the head of the receive queue differs between Windows and
619    /// Unix-like platforms (Linux, macOS, BSDs, etc: colloquially termed "*nix").
620    ///
621    /// On *nix platforms, the datagram is truncated to the length of `buf`.
622    ///
623    /// On Windows, an error corresponding to `WSAEMSGSIZE` will be returned.
624    ///
625    /// For consistency between platforms, be sure to provide a sufficiently large buffer to avoid
626    /// truncation; the exact size required depends on the underlying protocol.
627    ///
628    /// If you just want to know the sender of the data, try [`peek_sender`].
629    ///
630    /// [`recv`]: Socket::recv
631    /// [`peek_sender`]: Socket::peek_sender
632    pub fn peek_from(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<(usize, SockAddr)> {
633        self.recv_from_with_flags(buf, sys::MSG_PEEK)
634    }
635
636    /// Retrieve the sender for the data at the head of the receive queue.
637    ///
638    /// This is equivalent to calling [`peek_from`] with a zero-sized buffer,
639    /// but suppresses the `WSAEMSGSIZE` error on Windows.
640    ///
641    /// [`peek_from`]: Socket::peek_from
642    pub fn peek_sender(&self) -> io::Result<SockAddr> {
643        sys::peek_sender(self.as_raw())
644    }
645
646    /// Receive a message from a socket using a message structure.
647    ///
648    /// This is not supported on Windows as calling `WSARecvMsg` (the `recvmsg`
649    /// equivalent) is not straight forward on Windows. See
650    /// <https://github.com/microsoft/Windows-classic-samples/blob/7cbd99ac1d2b4a0beffbaba29ea63d024ceff700/Samples/Win7Samples/netds/winsock/recvmsg/rmmc.cpp>
651    /// for an example (in C++).
652    #[doc = man_links!(recvmsg(2))]
653    #[cfg(all(unix, not(target_os = "redox")))]
654    #[cfg_attr(docsrs, doc(cfg(all(unix, not(target_os = "redox")))))]
655    pub fn recvmsg(&self, msg: &mut MsgHdrMut<'_, '_, '_>, flags: sys::c_int) -> io::Result<usize> {
656        sys::recvmsg(self.as_raw(), msg, flags)
657    }
658
659    /// Sends data on the socket to a connected peer.
660    ///
661    /// This is typically used on TCP sockets or datagram sockets which have
662    /// been connected.
663    ///
664    /// On success returns the number of bytes that were sent.
665    #[doc = man_links!(send(2))]
666    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
667        self.send_with_flags(buf, 0)
668    }
669
670    /// Identical to [`send`] but allows for specification of arbitrary flags to the underlying
671    /// `send` call.
672    ///
673    /// [`send`]: Socket::send
674    pub fn send_with_flags(&self, buf: &[u8], flags: c_int) -> io::Result<usize> {
675        sys::send(self.as_raw(), buf, flags)
676    }
677
678    /// Send data to the connected peer. Returns the amount of bytes written.
679    #[cfg(not(target_os = "redox"))]
680    #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
681    pub fn send_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
682        self.send_vectored_with_flags(bufs, 0)
683    }
684
685    /// Identical to [`send_vectored`] but allows for specification of arbitrary
686    /// flags to the underlying `sendmsg`/`WSASend` call.
687    #[doc = man_links!(sendmsg(2))]
688    ///
689    /// [`send_vectored`]: Socket::send_vectored
690    #[cfg(not(target_os = "redox"))]
691    #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
692    pub fn send_vectored_with_flags(
693        &self,
694        bufs: &[IoSlice<'_>],
695        flags: c_int,
696    ) -> io::Result<usize> {
697        sys::send_vectored(self.as_raw(), bufs, flags)
698    }
699
700    /// Sends out-of-band (OOB) data on the socket to connected peer
701    /// by setting the `MSG_OOB` flag for this call.
702    ///
703    /// For more information, see [`send`], [`out_of_band_inline`].
704    ///
705    /// [`send`]: Socket::send
706    /// [`out_of_band_inline`]: Socket::out_of_band_inline
707    #[cfg_attr(target_os = "redox", allow(rustdoc::broken_intra_doc_links))]
708    pub fn send_out_of_band(&self, buf: &[u8]) -> io::Result<usize> {
709        self.send_with_flags(buf, sys::MSG_OOB)
710    }
711
712    /// Sends data on the socket to the given address. On success, returns the
713    /// number of bytes written.
714    ///
715    /// This is typically used on UDP or datagram-oriented sockets.
716    #[doc = man_links!(sendto(2))]
717    pub fn send_to(&self, buf: &[u8], addr: &SockAddr) -> io::Result<usize> {
718        self.send_to_with_flags(buf, addr, 0)
719    }
720
721    /// Identical to [`send_to`] but allows for specification of arbitrary flags
722    /// to the underlying `sendto` call.
723    ///
724    /// [`send_to`]: Socket::send_to
725    pub fn send_to_with_flags(
726        &self,
727        buf: &[u8],
728        addr: &SockAddr,
729        flags: c_int,
730    ) -> io::Result<usize> {
731        sys::send_to(self.as_raw(), buf, addr, flags)
732    }
733
734    /// Send data to a peer listening on `addr`. Returns the amount of bytes
735    /// written.
736    #[doc = man_links!(sendmsg(2))]
737    #[cfg(not(target_os = "redox"))]
738    #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
739    pub fn send_to_vectored(&self, bufs: &[IoSlice<'_>], addr: &SockAddr) -> io::Result<usize> {
740        self.send_to_vectored_with_flags(bufs, addr, 0)
741    }
742
743    /// Identical to [`send_to_vectored`] but allows for specification of
744    /// arbitrary flags to the underlying `sendmsg`/`WSASendTo` call.
745    ///
746    /// [`send_to_vectored`]: Socket::send_to_vectored
747    #[cfg(not(target_os = "redox"))]
748    #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
749    pub fn send_to_vectored_with_flags(
750        &self,
751        bufs: &[IoSlice<'_>],
752        addr: &SockAddr,
753        flags: c_int,
754    ) -> io::Result<usize> {
755        sys::send_to_vectored(self.as_raw(), bufs, addr, flags)
756    }
757
758    /// Send a message on a socket using a message structure.
759    #[doc = man_links!(sendmsg(2))]
760    #[cfg(not(target_os = "redox"))]
761    #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
762    pub fn sendmsg(&self, msg: &MsgHdr<'_, '_, '_>, flags: sys::c_int) -> io::Result<usize> {
763        sys::sendmsg(self.as_raw(), msg, flags)
764    }
765}
766
767/// Set `SOCK_CLOEXEC` and `NO_HANDLE_INHERIT` on the `ty`pe on platforms that
768/// support it.
769#[inline(always)]
770const fn set_common_type(ty: Type) -> Type {
771    // On platforms that support it set `SOCK_CLOEXEC`.
772    #[cfg(any(
773        target_os = "android",
774        target_os = "dragonfly",
775        target_os = "freebsd",
776        target_os = "fuchsia",
777        target_os = "hurd",
778        target_os = "illumos",
779        target_os = "linux",
780        target_os = "netbsd",
781        target_os = "openbsd",
782        target_os = "cygwin",
783    ))]
784    let ty = ty._cloexec();
785
786    // On windows set `NO_HANDLE_INHERIT`.
787    #[cfg(windows)]
788    let ty = ty._no_inherit();
789
790    ty
791}
792
793/// Set `FD_CLOEXEC` and `NOSIGPIPE` on the `socket` for platforms that need it.
794#[inline(always)]
795#[allow(clippy::unnecessary_wraps)]
796fn set_common_flags(socket: Socket) -> io::Result<Socket> {
797    // On platforms that don't have `SOCK_CLOEXEC` use `FD_CLOEXEC`.
798    #[cfg(all(
799        unix,
800        not(any(
801            target_os = "android",
802            target_os = "dragonfly",
803            target_os = "freebsd",
804            target_os = "fuchsia",
805            target_os = "hurd",
806            target_os = "illumos",
807            target_os = "linux",
808            target_os = "netbsd",
809            target_os = "openbsd",
810            target_os = "espidf",
811            target_os = "vita",
812            target_os = "cygwin",
813        ))
814    ))]
815    socket._set_cloexec(true)?;
816
817    // On Apple platforms set `NOSIGPIPE`.
818    #[cfg(any(
819        target_os = "ios",
820        target_os = "visionos",
821        target_os = "macos",
822        target_os = "tvos",
823        target_os = "watchos",
824    ))]
825    socket._set_nosigpipe(true)?;
826
827    Ok(socket)
828}
829
830/// A local interface specified by its index or an address assigned to it.
831///
832/// `Index(0)` and `Address(Ipv4Addr::UNSPECIFIED)` are equivalent and indicate
833/// that an appropriate interface should be selected by the system.
834#[cfg(not(any(
835    target_os = "haiku",
836    target_os = "illumos",
837    target_os = "netbsd",
838    target_os = "redox",
839    target_os = "solaris",
840)))]
841#[derive(Debug)]
842pub enum InterfaceIndexOrAddress {
843    /// An interface index.
844    Index(u32),
845    /// An address assigned to an interface.
846    Address(Ipv4Addr),
847}
848
849/// Socket options get/set using `SOL_SOCKET`.
850///
851/// Additional documentation can be found in documentation of the OS.
852/// * Linux: <https://man7.org/linux/man-pages/man7/socket.7.html>
853/// * Windows: <https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options>
854impl Socket {
855    /// Get the value of the `SO_BROADCAST` option for this socket.
856    ///
857    /// For more information about this option, see [`set_broadcast`].
858    ///
859    /// [`set_broadcast`]: Socket::set_broadcast
860    pub fn broadcast(&self) -> io::Result<bool> {
861        unsafe {
862            getsockopt::<c_int>(self.as_raw(), sys::SOL_SOCKET, sys::SO_BROADCAST)
863                .map(|broadcast| broadcast != 0)
864        }
865    }
866
867    /// Set the value of the `SO_BROADCAST` option for this socket.
868    ///
869    /// When enabled, this socket is allowed to send packets to a broadcast
870    /// address.
871    pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
872        unsafe {
873            setsockopt(
874                self.as_raw(),
875                sys::SOL_SOCKET,
876                sys::SO_BROADCAST,
877                broadcast as c_int,
878            )
879        }
880    }
881
882    /// Get the value of the `SO_ERROR` option on this socket.
883    ///
884    /// This will retrieve the stored error in the underlying socket, clearing
885    /// the field in the process. This can be useful for checking errors between
886    /// calls.
887    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
888        match unsafe { getsockopt::<c_int>(self.as_raw(), sys::SOL_SOCKET, sys::SO_ERROR) } {
889            Ok(0) => Ok(None),
890            Ok(errno) => Ok(Some(io::Error::from_raw_os_error(errno))),
891            Err(err) => Err(err),
892        }
893    }
894
895    /// Get the value of the `SO_KEEPALIVE` option on this socket.
896    ///
897    /// For more information about this option, see [`set_keepalive`].
898    ///
899    /// [`set_keepalive`]: Socket::set_keepalive
900    pub fn keepalive(&self) -> io::Result<bool> {
901        unsafe {
902            getsockopt::<Bool>(self.as_raw(), sys::SOL_SOCKET, sys::SO_KEEPALIVE)
903                .map(|keepalive| keepalive != 0)
904        }
905    }
906
907    /// Set value for the `SO_KEEPALIVE` option on this socket.
908    ///
909    /// Enable sending of keep-alive messages on connection-oriented sockets.
910    pub fn set_keepalive(&self, keepalive: bool) -> io::Result<()> {
911        unsafe {
912            setsockopt(
913                self.as_raw(),
914                sys::SOL_SOCKET,
915                sys::SO_KEEPALIVE,
916                keepalive as c_int,
917            )
918        }
919    }
920
921    /// Get the value of the `SO_LINGER` option on this socket.
922    ///
923    /// For more information about this option, see [`set_linger`].
924    ///
925    /// [`set_linger`]: Socket::set_linger
926    pub fn linger(&self) -> io::Result<Option<Duration>> {
927        unsafe {
928            getsockopt::<sys::linger>(self.as_raw(), sys::SOL_SOCKET, sys::SO_LINGER)
929                .map(from_linger)
930        }
931    }
932
933    /// Set value for the `SO_LINGER` option on this socket.
934    ///
935    /// If `linger` is not `None`, a close(2) or shutdown(2) will not return
936    /// until all queued messages for the socket have been successfully sent or
937    /// the linger timeout has been reached. Otherwise, the call returns
938    /// immediately and the closing is done in the background. When the socket
939    /// is closed as part of exit(2), it always lingers in the background.
940    ///
941    /// # Notes
942    ///
943    /// On most OSs the duration only has a precision of seconds and will be
944    /// silently truncated.
945    ///
946    /// On Apple platforms (e.g. macOS, iOS, etc) this uses `SO_LINGER_SEC`.
947    pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
948        let linger = into_linger(linger);
949        unsafe { setsockopt(self.as_raw(), sys::SOL_SOCKET, sys::SO_LINGER, linger) }
950    }
951
952    /// Get value for the `SO_OOBINLINE` option on this socket.
953    ///
954    /// For more information about this option, see [`set_out_of_band_inline`].
955    ///
956    /// [`set_out_of_band_inline`]: Socket::set_out_of_band_inline
957    #[cfg(not(target_os = "redox"))]
958    #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
959    pub fn out_of_band_inline(&self) -> io::Result<bool> {
960        unsafe {
961            getsockopt::<c_int>(self.as_raw(), sys::SOL_SOCKET, sys::SO_OOBINLINE)
962                .map(|oob_inline| oob_inline != 0)
963        }
964    }
965
966    /// Set value for the `SO_OOBINLINE` option on this socket.
967    ///
968    /// If this option is enabled, out-of-band data is directly placed into the
969    /// receive data stream. Otherwise, out-of-band data is passed only when the
970    /// `MSG_OOB` flag is set during receiving. As per RFC6093, TCP sockets
971    /// using the Urgent mechanism are encouraged to set this flag.
972    #[cfg(not(target_os = "redox"))]
973    #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
974    pub fn set_out_of_band_inline(&self, oob_inline: bool) -> io::Result<()> {
975        unsafe {
976            setsockopt(
977                self.as_raw(),
978                sys::SOL_SOCKET,
979                sys::SO_OOBINLINE,
980                oob_inline as c_int,
981            )
982        }
983    }
984
985    /// Get value for the `SO_PASSCRED` option on this socket.
986    ///
987    /// For more information about this option, see [`set_passcred`].
988    ///
989    /// [`set_passcred`]: Socket::set_passcred
990    #[cfg(any(target_os = "linux", target_os = "cygwin"))]
991    #[cfg_attr(docsrs, doc(cfg(any(target_os = "linux", target_os = "cygwin"))))]
992    pub fn passcred(&self) -> io::Result<bool> {
993        unsafe {
994            getsockopt::<c_int>(self.as_raw(), sys::SOL_SOCKET, sys::SO_PASSCRED)
995                .map(|passcred| passcred != 0)
996        }
997    }
998
999    /// Set value for the `SO_PASSCRED` option on this socket.
1000    ///
1001    /// If this option is enabled, enables the receiving of the `SCM_CREDENTIALS`
1002    /// control messages.
1003    #[cfg(any(target_os = "linux", target_os = "cygwin"))]
1004    #[cfg_attr(docsrs, doc(cfg(any(target_os = "linux", target_os = "cygwin"))))]
1005    pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
1006        unsafe {
1007            setsockopt(
1008                self.as_raw(),
1009                sys::SOL_SOCKET,
1010                sys::SO_PASSCRED,
1011                passcred as c_int,
1012            )
1013        }
1014    }
1015
1016    /// Get value for the `SO_RCVBUF` option on this socket.
1017    ///
1018    /// For more information about this option, see [`set_recv_buffer_size`].
1019    ///
1020    /// [`set_recv_buffer_size`]: Socket::set_recv_buffer_size
1021    pub fn recv_buffer_size(&self) -> io::Result<usize> {
1022        unsafe {
1023            getsockopt::<c_int>(self.as_raw(), sys::SOL_SOCKET, sys::SO_RCVBUF)
1024                .map(|size| size as usize)
1025        }
1026    }
1027
1028    /// Set value for the `SO_RCVBUF` option on this socket.
1029    ///
1030    /// Changes the size of the operating system's receive buffer associated
1031    /// with the socket.
1032    pub fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> {
1033        unsafe {
1034            setsockopt(
1035                self.as_raw(),
1036                sys::SOL_SOCKET,
1037                sys::SO_RCVBUF,
1038                size as c_int,
1039            )
1040        }
1041    }
1042
1043    /// Get value for the `SO_RCVTIMEO` option on this socket.
1044    ///
1045    /// If the returned timeout is `None`, then `read` and `recv` calls will
1046    /// block indefinitely.
1047    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
1048        sys::timeout_opt(self.as_raw(), sys::SOL_SOCKET, sys::SO_RCVTIMEO)
1049    }
1050
1051    /// Set value for the `SO_RCVTIMEO` option on this socket.
1052    ///
1053    /// If `timeout` is `None`, then `read` and `recv` calls will block
1054    /// indefinitely.
1055    pub fn set_read_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
1056        sys::set_timeout_opt(self.as_raw(), sys::SOL_SOCKET, sys::SO_RCVTIMEO, duration)
1057    }
1058
1059    /// Get the value of the `SO_REUSEADDR` option on this socket.
1060    ///
1061    /// For more information about this option, see [`set_reuse_address`].
1062    ///
1063    /// [`set_reuse_address`]: Socket::set_reuse_address
1064    pub fn reuse_address(&self) -> io::Result<bool> {
1065        unsafe {
1066            getsockopt::<c_int>(self.as_raw(), sys::SOL_SOCKET, sys::SO_REUSEADDR)
1067                .map(|reuse| reuse != 0)
1068        }
1069    }
1070
1071    /// Set value for the `SO_REUSEADDR` option on this socket.
1072    ///
1073    /// This indicates that further calls to `bind` may allow reuse of local
1074    /// addresses. For IPv4 sockets this means that a socket may bind even when
1075    /// there's a socket already listening on this port.
1076    pub fn set_reuse_address(&self, reuse: bool) -> io::Result<()> {
1077        unsafe {
1078            setsockopt(
1079                self.as_raw(),
1080                sys::SOL_SOCKET,
1081                sys::SO_REUSEADDR,
1082                reuse as c_int,
1083            )
1084        }
1085    }
1086
1087    /// Get the value of the `SO_SNDBUF` option on this socket.
1088    ///
1089    /// For more information about this option, see [`set_send_buffer_size`].
1090    ///
1091    /// [`set_send_buffer_size`]: Socket::set_send_buffer_size
1092    pub fn send_buffer_size(&self) -> io::Result<usize> {
1093        unsafe {
1094            getsockopt::<c_int>(self.as_raw(), sys::SOL_SOCKET, sys::SO_SNDBUF)
1095                .map(|size| size as usize)
1096        }
1097    }
1098
1099    /// Set value for the `SO_SNDBUF` option on this socket.
1100    ///
1101    /// Changes the size of the operating system's send buffer associated with
1102    /// the socket.
1103    pub fn set_send_buffer_size(&self, size: usize) -> io::Result<()> {
1104        unsafe {
1105            setsockopt(
1106                self.as_raw(),
1107                sys::SOL_SOCKET,
1108                sys::SO_SNDBUF,
1109                size as c_int,
1110            )
1111        }
1112    }
1113
1114    /// Get value for the `SO_SNDTIMEO` option on this socket.
1115    ///
1116    /// If the returned timeout is `None`, then `write` and `send` calls will
1117    /// block indefinitely.
1118    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
1119        sys::timeout_opt(self.as_raw(), sys::SOL_SOCKET, sys::SO_SNDTIMEO)
1120    }
1121
1122    /// Set value for the `SO_SNDTIMEO` option on this socket.
1123    ///
1124    /// If `timeout` is `None`, then `write` and `send` calls will block
1125    /// indefinitely.
1126    pub fn set_write_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
1127        sys::set_timeout_opt(self.as_raw(), sys::SOL_SOCKET, sys::SO_SNDTIMEO, duration)
1128    }
1129}
1130
1131const fn from_linger(linger: sys::linger) -> Option<Duration> {
1132    if linger.l_onoff == 0 {
1133        None
1134    } else {
1135        Some(Duration::from_secs(linger.l_linger as u64))
1136    }
1137}
1138
1139const fn into_linger(duration: Option<Duration>) -> sys::linger {
1140    match duration {
1141        Some(duration) => sys::linger {
1142            l_onoff: 1,
1143            l_linger: duration.as_secs() as _,
1144        },
1145        None => sys::linger {
1146            l_onoff: 0,
1147            l_linger: 0,
1148        },
1149    }
1150}
1151
1152/// Socket options for IPv4 sockets, get/set using `IPPROTO_IP`.
1153///
1154/// Additional documentation can be found in documentation of the OS.
1155/// * Linux: <https://man7.org/linux/man-pages/man7/ip.7.html>
1156/// * Windows: <https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options>
1157impl Socket {
1158    /// This method is deprecated, use [`crate::Socket::header_included_v4`].
1159    #[cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))]
1160    #[cfg_attr(
1161        docsrs,
1162        doc(cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf")))))
1163    )]
1164    #[deprecated = "Use `Socket::header_included_v4` instead"]
1165    pub fn header_included(&self) -> io::Result<bool> {
1166        self.header_included_v4()
1167    }
1168    /// Get the value of the `IP_HDRINCL` option on this socket.
1169    ///
1170    /// For more information about this option, see [`set_header_included`].
1171    ///
1172    /// [`set_header_included`]: Socket::set_header_included
1173    #[cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))]
1174    #[cfg_attr(
1175        docsrs,
1176        doc(cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf")))))
1177    )]
1178    pub fn header_included_v4(&self) -> io::Result<bool> {
1179        unsafe {
1180            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, sys::IP_HDRINCL)
1181                .map(|included| included != 0)
1182        }
1183    }
1184
1185    /// This method is deprecated, use [`crate::Socket::set_header_included_v4`].
1186    #[cfg_attr(
1187        any(target_os = "fuchsia", target_os = "illumos", target_os = "solaris"),
1188        allow(rustdoc::broken_intra_doc_links)
1189    )]
1190    #[cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))]
1191    #[cfg_attr(
1192        docsrs,
1193        doc(cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf")))))
1194    )]
1195    #[deprecated = "Use `Socket::set_header_included_v4` instead"]
1196    pub fn set_header_included(&self, included: bool) -> io::Result<()> {
1197        self.set_header_included_v4(included)
1198    }
1199
1200    /// Set the value of the `IP_HDRINCL` option on this socket.
1201    ///
1202    /// If enabled, the user supplies an IP header in front of the user data.
1203    /// Valid only for [`SOCK_RAW`] sockets; see [raw(7)] for more information.
1204    /// When this flag is enabled, the values set by `IP_OPTIONS`, [`IP_TTL`],
1205    /// and [`IP_TOS`] are ignored.
1206    ///
1207    /// [`SOCK_RAW`]: Type::RAW
1208    /// [raw(7)]: https://man7.org/linux/man-pages/man7/raw.7.html
1209    /// [`IP_TTL`]: Socket::set_ttl
1210    /// [`IP_TOS`]: Socket::set_tos
1211    #[cfg_attr(
1212        any(target_os = "fuchsia", target_os = "illumos", target_os = "solaris"),
1213        allow(rustdoc::broken_intra_doc_links)
1214    )]
1215    #[cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))]
1216    #[cfg_attr(
1217        docsrs,
1218        doc(cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf")))))
1219    )]
1220    pub fn set_header_included_v4(&self, included: bool) -> io::Result<()> {
1221        unsafe {
1222            setsockopt(
1223                self.as_raw(),
1224                sys::IPPROTO_IP,
1225                sys::IP_HDRINCL,
1226                included as c_int,
1227            )
1228        }
1229    }
1230
1231    /// Get the value of the `IP_TRANSPARENT` option on this socket.
1232    ///
1233    /// For more information about this option, see [`set_ip_transparent`].
1234    ///
1235    /// [`set_ip_transparent`]: Socket::set_ip_transparent
1236    #[cfg(all(feature = "all", target_os = "linux"))]
1237    #[cfg_attr(docsrs, doc(cfg(all(feature = "all", target_os = "linux"))))]
1238    pub fn ip_transparent(&self) -> io::Result<bool> {
1239        unsafe {
1240            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, libc::IP_TRANSPARENT)
1241                .map(|transparent| transparent != 0)
1242        }
1243    }
1244
1245    /// Set the value of the `IP_TRANSPARENT` option on this socket.
1246    ///
1247    /// Setting this boolean option enables transparent proxying
1248    /// on this socket.  This socket option allows the calling
1249    /// application to bind to a nonlocal IP address and operate
1250    /// both as a client and a server with the foreign address as
1251    /// the local endpoint.  NOTE: this requires that routing be
1252    /// set up in a way that packets going to the foreign address
1253    /// are routed through the TProxy box (i.e., the system
1254    /// hosting the application that employs the IP_TRANSPARENT
1255    /// socket option).  Enabling this socket option requires
1256    /// superuser privileges (the `CAP_NET_ADMIN` capability).
1257    ///
1258    /// TProxy redirection with the iptables TPROXY target also
1259    /// requires that this option be set on the redirected socket.
1260    #[cfg(all(feature = "all", target_os = "linux"))]
1261    #[cfg_attr(docsrs, doc(cfg(all(feature = "all", target_os = "linux"))))]
1262    pub fn set_ip_transparent(&self, transparent: bool) -> io::Result<()> {
1263        unsafe {
1264            setsockopt(
1265                self.as_raw(),
1266                sys::IPPROTO_IP,
1267                libc::IP_TRANSPARENT,
1268                transparent as c_int,
1269            )
1270        }
1271    }
1272
1273    /// Join a multicast group using `IP_ADD_MEMBERSHIP` option on this socket.
1274    ///
1275    /// This function specifies a new multicast group for this socket to join.
1276    /// The address must be a valid multicast address, and `interface` is the
1277    /// address of the local interface with which the system should join the
1278    /// multicast group. If it's [`Ipv4Addr::UNSPECIFIED`] (`INADDR_ANY`) then
1279    /// an appropriate interface is chosen by the system.
1280    pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
1281        let mreq = sys::IpMreq {
1282            imr_multiaddr: sys::to_in_addr(multiaddr),
1283            imr_interface: sys::to_in_addr(interface),
1284        };
1285        unsafe { setsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_ADD_MEMBERSHIP, mreq) }
1286    }
1287
1288    /// Leave a multicast group using `IP_DROP_MEMBERSHIP` option on this socket.
1289    ///
1290    /// For more information about this option, see [`join_multicast_v4`].
1291    ///
1292    /// [`join_multicast_v4`]: Socket::join_multicast_v4
1293    pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
1294        let mreq = sys::IpMreq {
1295            imr_multiaddr: sys::to_in_addr(multiaddr),
1296            imr_interface: sys::to_in_addr(interface),
1297        };
1298        unsafe {
1299            setsockopt(
1300                self.as_raw(),
1301                sys::IPPROTO_IP,
1302                sys::IP_DROP_MEMBERSHIP,
1303                mreq,
1304            )
1305        }
1306    }
1307
1308    /// Join a multicast group using `IP_ADD_MEMBERSHIP` option on this socket.
1309    ///
1310    /// This function specifies a new multicast group for this socket to join.
1311    /// The address must be a valid multicast address, and `interface` specifies
1312    /// the local interface with which the system should join the multicast
1313    /// group. See [`InterfaceIndexOrAddress`].
1314    #[cfg(not(any(
1315        target_os = "aix",
1316        target_os = "haiku",
1317        target_os = "illumos",
1318        target_os = "netbsd",
1319        target_os = "openbsd",
1320        target_os = "redox",
1321        target_os = "solaris",
1322        target_os = "nto",
1323        target_os = "espidf",
1324        target_os = "vita",
1325        target_os = "cygwin",
1326    )))]
1327    pub fn join_multicast_v4_n(
1328        &self,
1329        multiaddr: &Ipv4Addr,
1330        interface: &InterfaceIndexOrAddress,
1331    ) -> io::Result<()> {
1332        let mreqn = sys::to_mreqn(multiaddr, interface);
1333        unsafe {
1334            setsockopt(
1335                self.as_raw(),
1336                sys::IPPROTO_IP,
1337                sys::IP_ADD_MEMBERSHIP,
1338                mreqn,
1339            )
1340        }
1341    }
1342
1343    /// Leave a multicast group using `IP_DROP_MEMBERSHIP` option on this socket.
1344    ///
1345    /// For more information about this option, see [`join_multicast_v4_n`].
1346    ///
1347    /// [`join_multicast_v4_n`]: Socket::join_multicast_v4_n
1348    #[cfg(not(any(
1349        target_os = "aix",
1350        target_os = "haiku",
1351        target_os = "illumos",
1352        target_os = "netbsd",
1353        target_os = "openbsd",
1354        target_os = "redox",
1355        target_os = "solaris",
1356        target_os = "nto",
1357        target_os = "espidf",
1358        target_os = "vita",
1359        target_os = "cygwin",
1360    )))]
1361    pub fn leave_multicast_v4_n(
1362        &self,
1363        multiaddr: &Ipv4Addr,
1364        interface: &InterfaceIndexOrAddress,
1365    ) -> io::Result<()> {
1366        let mreqn = sys::to_mreqn(multiaddr, interface);
1367        unsafe {
1368            setsockopt(
1369                self.as_raw(),
1370                sys::IPPROTO_IP,
1371                sys::IP_DROP_MEMBERSHIP,
1372                mreqn,
1373            )
1374        }
1375    }
1376
1377    /// Join a multicast SSM channel using `IP_ADD_SOURCE_MEMBERSHIP` option on this socket.
1378    ///
1379    /// This function specifies a new multicast channel for this socket to join.
1380    /// The group must be a valid SSM group address, the source must be the address of the sender
1381    /// and `interface` is the address of the local interface with which the system should join the
1382    /// multicast group. If it's [`Ipv4Addr::UNSPECIFIED`] (`INADDR_ANY`) then
1383    /// an appropriate interface is chosen by the system.
1384    #[cfg(not(any(
1385        target_os = "dragonfly",
1386        target_os = "haiku",
1387        target_os = "hurd",
1388        target_os = "netbsd",
1389        target_os = "openbsd",
1390        target_os = "redox",
1391        target_os = "fuchsia",
1392        target_os = "nto",
1393        target_os = "espidf",
1394        target_os = "vita",
1395    )))]
1396    pub fn join_ssm_v4(
1397        &self,
1398        source: &Ipv4Addr,
1399        group: &Ipv4Addr,
1400        interface: &Ipv4Addr,
1401    ) -> io::Result<()> {
1402        let mreqs = sys::IpMreqSource {
1403            imr_multiaddr: sys::to_in_addr(group),
1404            imr_interface: sys::to_in_addr(interface),
1405            imr_sourceaddr: sys::to_in_addr(source),
1406        };
1407        unsafe {
1408            setsockopt(
1409                self.as_raw(),
1410                sys::IPPROTO_IP,
1411                sys::IP_ADD_SOURCE_MEMBERSHIP,
1412                mreqs,
1413            )
1414        }
1415    }
1416
1417    /// Leave a multicast group using `IP_DROP_SOURCE_MEMBERSHIP` option on this socket.
1418    ///
1419    /// For more information about this option, see [`join_ssm_v4`].
1420    ///
1421    /// [`join_ssm_v4`]: Socket::join_ssm_v4
1422    #[cfg(not(any(
1423        target_os = "dragonfly",
1424        target_os = "haiku",
1425        target_os = "hurd",
1426        target_os = "netbsd",
1427        target_os = "openbsd",
1428        target_os = "redox",
1429        target_os = "fuchsia",
1430        target_os = "nto",
1431        target_os = "espidf",
1432        target_os = "vita",
1433    )))]
1434    pub fn leave_ssm_v4(
1435        &self,
1436        source: &Ipv4Addr,
1437        group: &Ipv4Addr,
1438        interface: &Ipv4Addr,
1439    ) -> io::Result<()> {
1440        let mreqs = sys::IpMreqSource {
1441            imr_multiaddr: sys::to_in_addr(group),
1442            imr_interface: sys::to_in_addr(interface),
1443            imr_sourceaddr: sys::to_in_addr(source),
1444        };
1445        unsafe {
1446            setsockopt(
1447                self.as_raw(),
1448                sys::IPPROTO_IP,
1449                sys::IP_DROP_SOURCE_MEMBERSHIP,
1450                mreqs,
1451            )
1452        }
1453    }
1454
1455    /// Get the value of the `IP_MULTICAST_ALL` option for this socket.
1456    ///
1457    /// For more information about this option, see [`set_multicast_all_v4`].
1458    ///
1459    /// [`set_multicast_all_v4`]: Socket::set_multicast_all_v4
1460    #[cfg(all(feature = "all", target_os = "linux"))]
1461    #[cfg_attr(docsrs, doc(cfg(all(feature = "all", target_os = "linux"))))]
1462    pub fn multicast_all_v4(&self) -> io::Result<bool> {
1463        unsafe {
1464            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, libc::IP_MULTICAST_ALL)
1465                .map(|all| all != 0)
1466        }
1467    }
1468
1469    /// Set the value of the `IP_MULTICAST_ALL` option for this socket.
1470    ///
1471    /// This option can be used to modify the delivery policy of
1472    /// multicast messages.  The argument is a boolean
1473    /// (defaults to true).  If set to true, the socket will receive
1474    /// messages from all the groups that have been joined
1475    /// globally on the whole system.  Otherwise, it will deliver
1476    /// messages only from the groups that have been explicitly
1477    /// joined (for example via the `IP_ADD_MEMBERSHIP` option) on
1478    /// this particular socket.
1479    #[cfg(all(feature = "all", target_os = "linux"))]
1480    #[cfg_attr(docsrs, doc(cfg(all(feature = "all", target_os = "linux"))))]
1481    pub fn set_multicast_all_v4(&self, all: bool) -> io::Result<()> {
1482        unsafe {
1483            setsockopt(
1484                self.as_raw(),
1485                sys::IPPROTO_IP,
1486                libc::IP_MULTICAST_ALL,
1487                all as c_int,
1488            )
1489        }
1490    }
1491
1492    /// Get the value of the `IP_MULTICAST_IF` option for this socket.
1493    ///
1494    /// For more information about this option, see [`set_multicast_if_v4`].
1495    ///
1496    /// [`set_multicast_if_v4`]: Socket::set_multicast_if_v4
1497    pub fn multicast_if_v4(&self) -> io::Result<Ipv4Addr> {
1498        unsafe {
1499            getsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_IF).map(sys::from_in_addr)
1500        }
1501    }
1502
1503    /// Set the value of the `IP_MULTICAST_IF` option for this socket.
1504    ///
1505    /// Specifies the interface to use for routing multicast packets.
1506    pub fn set_multicast_if_v4(&self, interface: &Ipv4Addr) -> io::Result<()> {
1507        let interface = sys::to_in_addr(interface);
1508        unsafe {
1509            setsockopt(
1510                self.as_raw(),
1511                sys::IPPROTO_IP,
1512                sys::IP_MULTICAST_IF,
1513                interface,
1514            )
1515        }
1516    }
1517
1518    /// Get the value of the `IP_MULTICAST_LOOP` option for this socket.
1519    ///
1520    /// For more information about this option, see [`set_multicast_loop_v4`].
1521    ///
1522    /// [`set_multicast_loop_v4`]: Socket::set_multicast_loop_v4
1523    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
1524        unsafe {
1525            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_LOOP)
1526                .map(|loop_v4| loop_v4 != 0)
1527        }
1528    }
1529
1530    /// Set the value of the `IP_MULTICAST_LOOP` option for this socket.
1531    ///
1532    /// If enabled, multicast packets will be looped back to the local socket.
1533    /// Note that this may not have any affect on IPv6 sockets.
1534    pub fn set_multicast_loop_v4(&self, loop_v4: bool) -> io::Result<()> {
1535        unsafe {
1536            setsockopt(
1537                self.as_raw(),
1538                sys::IPPROTO_IP,
1539                sys::IP_MULTICAST_LOOP,
1540                loop_v4 as c_int,
1541            )
1542        }
1543    }
1544
1545    /// Get the value of the `IP_MULTICAST_TTL` option for this socket.
1546    ///
1547    /// For more information about this option, see [`set_multicast_ttl_v4`].
1548    ///
1549    /// [`set_multicast_ttl_v4`]: Socket::set_multicast_ttl_v4
1550    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
1551        unsafe {
1552            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_TTL)
1553                .map(|ttl| ttl as u32)
1554        }
1555    }
1556
1557    /// Set the value of the `IP_MULTICAST_TTL` option for this socket.
1558    ///
1559    /// Indicates the time-to-live value of outgoing multicast packets for
1560    /// this socket. The default value is 1 which means that multicast packets
1561    /// don't leave the local network unless explicitly requested.
1562    ///
1563    /// Note that this may not have any affect on IPv6 sockets.
1564    pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
1565        unsafe {
1566            setsockopt(
1567                self.as_raw(),
1568                sys::IPPROTO_IP,
1569                sys::IP_MULTICAST_TTL,
1570                ttl as c_int,
1571            )
1572        }
1573    }
1574
1575    /// Get the value of the `IP_TTL` option for this socket.
1576    ///
1577    /// For more information about this option, see [`set_ttl`].
1578    ///
1579    /// [`set_ttl`]: Socket::set_ttl
1580    pub fn ttl(&self) -> io::Result<u32> {
1581        unsafe {
1582            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, sys::IP_TTL).map(|ttl| ttl as u32)
1583        }
1584    }
1585
1586    /// Set the value of the `IP_TTL` option for this socket.
1587    ///
1588    /// This value sets the time-to-live field that is used in every packet sent
1589    /// from this socket.
1590    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
1591        unsafe { setsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_TTL, ttl as c_int) }
1592    }
1593
1594    /// Set the value of the `IP_TOS` option for this socket.
1595    ///
1596    /// This value sets the type-of-service field that is used in every packet
1597    /// sent from this socket.
1598    ///
1599    /// NOTE: <https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options>
1600    /// documents that not all versions of windows support `IP_TOS`.
1601    #[cfg(not(any(
1602        target_os = "fuchsia",
1603        target_os = "redox",
1604        target_os = "solaris",
1605        target_os = "illumos",
1606        target_os = "haiku",
1607    )))]
1608    pub fn set_tos(&self, tos: u32) -> io::Result<()> {
1609        unsafe { setsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_TOS, tos as c_int) }
1610    }
1611
1612    /// Get the value of the `IP_TOS` option for this socket.
1613    ///
1614    /// For more information about this option, see [`set_tos`].
1615    ///
1616    /// NOTE: <https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options>
1617    /// documents that not all versions of windows support `IP_TOS`.
1618    ///
1619    /// [`set_tos`]: Socket::set_tos
1620    #[cfg(not(any(
1621        target_os = "fuchsia",
1622        target_os = "redox",
1623        target_os = "solaris",
1624        target_os = "illumos",
1625        target_os = "haiku",
1626    )))]
1627    pub fn tos(&self) -> io::Result<u32> {
1628        unsafe {
1629            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, sys::IP_TOS).map(|tos| tos as u32)
1630        }
1631    }
1632
1633    /// Set the value of the `IP_RECVTOS` option for this socket.
1634    ///
1635    /// If enabled, the `IP_TOS` ancillary message is passed with
1636    /// incoming packets. It contains a byte which specifies the
1637    /// Type of Service/Precedence field of the packet header.
1638    #[cfg(not(any(
1639        target_os = "aix",
1640        target_os = "dragonfly",
1641        target_os = "fuchsia",
1642        target_os = "hurd",
1643        target_os = "illumos",
1644        target_os = "netbsd",
1645        target_os = "openbsd",
1646        target_os = "redox",
1647        target_os = "solaris",
1648        target_os = "haiku",
1649        target_os = "nto",
1650        target_os = "espidf",
1651        target_os = "vita",
1652        target_os = "cygwin",
1653    )))]
1654    pub fn set_recv_tos(&self, recv_tos: bool) -> io::Result<()> {
1655        unsafe {
1656            setsockopt(
1657                self.as_raw(),
1658                sys::IPPROTO_IP,
1659                sys::IP_RECVTOS,
1660                recv_tos as c_int,
1661            )
1662        }
1663    }
1664
1665    /// Get the value of the `IP_RECVTOS` option for this socket.
1666    ///
1667    /// For more information about this option, see [`set_recv_tos`].
1668    ///
1669    /// [`set_recv_tos`]: Socket::set_recv_tos
1670    #[cfg(not(any(
1671        target_os = "aix",
1672        target_os = "dragonfly",
1673        target_os = "fuchsia",
1674        target_os = "hurd",
1675        target_os = "illumos",
1676        target_os = "netbsd",
1677        target_os = "openbsd",
1678        target_os = "redox",
1679        target_os = "solaris",
1680        target_os = "haiku",
1681        target_os = "nto",
1682        target_os = "espidf",
1683        target_os = "vita",
1684        target_os = "cygwin",
1685    )))]
1686    pub fn recv_tos(&self) -> io::Result<bool> {
1687        unsafe {
1688            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, sys::IP_RECVTOS)
1689                .map(|recv_tos| recv_tos > 0)
1690        }
1691    }
1692}
1693
1694/// Socket options for IPv6 sockets, get/set using `IPPROTO_IPV6`.
1695///
1696/// Additional documentation can be found in documentation of the OS.
1697/// * Linux: <https://man7.org/linux/man-pages/man7/ipv6.7.html>
1698/// * Windows: <https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options>
1699impl Socket {
1700    /// Get the value of the `IP_HDRINCL` option on this socket.
1701    ///
1702    /// For more information about this option, see [`set_header_included`].
1703    ///
1704    /// [`set_header_included`]: Socket::set_header_included
1705    #[cfg(all(
1706        feature = "all",
1707        not(any(
1708            target_os = "redox",
1709            target_os = "espidf",
1710            target_os = "openbsd",
1711            target_os = "freebsd",
1712            target_os = "dragonfly",
1713            target_os = "netbsd"
1714        ))
1715    ))]
1716    #[cfg_attr(
1717        docsrs,
1718        doc(cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf")))))
1719    )]
1720    pub fn header_included_v6(&self) -> io::Result<bool> {
1721        unsafe {
1722            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IP_HDRINCL)
1723                .map(|included| included != 0)
1724        }
1725    }
1726
1727    /// Set the value of the `IP_HDRINCL` option on this socket.
1728    ///
1729    /// If enabled, the user supplies an IP header in front of the user data.
1730    /// Valid only for [`SOCK_RAW`] sockets; see [raw(7)] for more information.
1731    /// When this flag is enabled, the values set by `IP_OPTIONS` are ignored.
1732    ///
1733    /// [`SOCK_RAW`]: Type::RAW
1734    /// [raw(7)]: https://man7.org/linux/man-pages/man7/raw.7.html
1735    #[cfg_attr(
1736        any(target_os = "fuchsia", target_os = "illumos", target_os = "solaris"),
1737        allow(rustdoc::broken_intra_doc_links)
1738    )]
1739    #[cfg(all(
1740        feature = "all",
1741        not(any(
1742            target_os = "redox",
1743            target_os = "espidf",
1744            target_os = "openbsd",
1745            target_os = "freebsd",
1746            target_os = "dragonfly",
1747            target_os = "netbsd"
1748        ))
1749    ))]
1750    #[cfg_attr(
1751        docsrs,
1752        doc(cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf")))))
1753    )]
1754    pub fn set_header_included_v6(&self, included: bool) -> io::Result<()> {
1755        unsafe {
1756            setsockopt(
1757                self.as_raw(),
1758                sys::IPPROTO_IPV6,
1759                sys::IP_HDRINCL,
1760                included as c_int,
1761            )
1762        }
1763    }
1764
1765    /// Join a multicast group using `IPV6_ADD_MEMBERSHIP` option on this socket.
1766    ///
1767    /// Some OSs use `IPV6_JOIN_GROUP` for this option.
1768    ///
1769    /// This function specifies a new multicast group for this socket to join.
1770    /// The address must be a valid multicast address, and `interface` is the
1771    /// index of the interface to join/leave (or 0 to indicate any interface).
1772    #[cfg(not(target_os = "nto"))]
1773    pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
1774        let mreq = sys::Ipv6Mreq {
1775            ipv6mr_multiaddr: sys::to_in6_addr(multiaddr),
1776            // NOTE: some OSs use `c_int`, others use `c_uint`.
1777            ipv6mr_interface: interface as _,
1778        };
1779        unsafe {
1780            setsockopt(
1781                self.as_raw(),
1782                sys::IPPROTO_IPV6,
1783                sys::IPV6_ADD_MEMBERSHIP,
1784                mreq,
1785            )
1786        }
1787    }
1788
1789    /// Leave a multicast group using `IPV6_DROP_MEMBERSHIP` option on this socket.
1790    ///
1791    /// Some OSs use `IPV6_LEAVE_GROUP` for this option.
1792    ///
1793    /// For more information about this option, see [`join_multicast_v6`].
1794    ///
1795    /// [`join_multicast_v6`]: Socket::join_multicast_v6
1796    #[cfg(not(target_os = "nto"))]
1797    pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
1798        let mreq = sys::Ipv6Mreq {
1799            ipv6mr_multiaddr: sys::to_in6_addr(multiaddr),
1800            // NOTE: some OSs use `c_int`, others use `c_uint`.
1801            ipv6mr_interface: interface as _,
1802        };
1803        unsafe {
1804            setsockopt(
1805                self.as_raw(),
1806                sys::IPPROTO_IPV6,
1807                sys::IPV6_DROP_MEMBERSHIP,
1808                mreq,
1809            )
1810        }
1811    }
1812
1813    /// Get the value of the `IPV6_MULTICAST_HOPS` option for this socket
1814    ///
1815    /// For more information about this option, see [`set_multicast_hops_v6`].
1816    ///
1817    /// [`set_multicast_hops_v6`]: Socket::set_multicast_hops_v6
1818    pub fn multicast_hops_v6(&self) -> io::Result<u32> {
1819        unsafe {
1820            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_HOPS)
1821                .map(|hops| hops as u32)
1822        }
1823    }
1824
1825    /// Set the value of the `IPV6_MULTICAST_HOPS` option for this socket
1826    ///
1827    /// Indicates the number of "routers" multicast packets will transit for
1828    /// this socket. The default value is 1 which means that multicast packets
1829    /// don't leave the local network unless explicitly requested.
1830    pub fn set_multicast_hops_v6(&self, hops: u32) -> io::Result<()> {
1831        unsafe {
1832            setsockopt(
1833                self.as_raw(),
1834                sys::IPPROTO_IPV6,
1835                sys::IPV6_MULTICAST_HOPS,
1836                hops as c_int,
1837            )
1838        }
1839    }
1840
1841    /// Get the value of the `IPV6_MULTICAST_ALL` option for this socket.
1842    ///
1843    /// For more information about this option, see [`set_multicast_all_v6`].
1844    ///
1845    /// [`set_multicast_all_v6`]: Socket::set_multicast_all_v6
1846    #[cfg(all(feature = "all", target_os = "linux"))]
1847    #[cfg_attr(docsrs, doc(cfg(all(feature = "all", target_os = "linux"))))]
1848    pub fn multicast_all_v6(&self) -> io::Result<bool> {
1849        unsafe {
1850            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, libc::IPV6_MULTICAST_ALL)
1851                .map(|all| all != 0)
1852        }
1853    }
1854
1855    /// Set the value of the `IPV6_MULTICAST_ALL` option for this socket.
1856    ///
1857    /// This option can be used to modify the delivery policy of
1858    /// multicast messages.  The argument is a boolean
1859    /// (defaults to true).  If set to true, the socket will receive
1860    /// messages from all the groups that have been joined
1861    /// globally on the whole system.  Otherwise, it will deliver
1862    /// messages only from the groups that have been explicitly
1863    /// joined (for example via the `IPV6_ADD_MEMBERSHIP` option) on
1864    /// this particular socket.
1865    #[cfg(all(feature = "all", target_os = "linux"))]
1866    #[cfg_attr(docsrs, doc(cfg(all(feature = "all", target_os = "linux"))))]
1867    pub fn set_multicast_all_v6(&self, all: bool) -> io::Result<()> {
1868        unsafe {
1869            setsockopt(
1870                self.as_raw(),
1871                sys::IPPROTO_IPV6,
1872                libc::IPV6_MULTICAST_ALL,
1873                all as c_int,
1874            )
1875        }
1876    }
1877
1878    /// Get the value of the `IPV6_MULTICAST_IF` option for this socket.
1879    ///
1880    /// For more information about this option, see [`set_multicast_if_v6`].
1881    ///
1882    /// [`set_multicast_if_v6`]: Socket::set_multicast_if_v6
1883    pub fn multicast_if_v6(&self) -> io::Result<u32> {
1884        unsafe {
1885            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_IF)
1886                .map(|interface| interface as u32)
1887        }
1888    }
1889
1890    /// Set the value of the `IPV6_MULTICAST_IF` option for this socket.
1891    ///
1892    /// Specifies the interface to use for routing multicast packets. Unlike
1893    /// ipv4, this is generally required in ipv6 contexts where network routing
1894    /// prefixes may overlap.
1895    pub fn set_multicast_if_v6(&self, interface: u32) -> io::Result<()> {
1896        unsafe {
1897            setsockopt(
1898                self.as_raw(),
1899                sys::IPPROTO_IPV6,
1900                sys::IPV6_MULTICAST_IF,
1901                interface as c_int,
1902            )
1903        }
1904    }
1905
1906    /// Get the value of the `IPV6_MULTICAST_LOOP` option for this socket.
1907    ///
1908    /// For more information about this option, see [`set_multicast_loop_v6`].
1909    ///
1910    /// [`set_multicast_loop_v6`]: Socket::set_multicast_loop_v6
1911    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
1912        unsafe {
1913            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_LOOP)
1914                .map(|loop_v6| loop_v6 != 0)
1915        }
1916    }
1917
1918    /// Set the value of the `IPV6_MULTICAST_LOOP` option for this socket.
1919    ///
1920    /// Controls whether this socket sees the multicast packets it sends itself.
1921    /// Note that this may not have any affect on IPv4 sockets.
1922    pub fn set_multicast_loop_v6(&self, loop_v6: bool) -> io::Result<()> {
1923        unsafe {
1924            setsockopt(
1925                self.as_raw(),
1926                sys::IPPROTO_IPV6,
1927                sys::IPV6_MULTICAST_LOOP,
1928                loop_v6 as c_int,
1929            )
1930        }
1931    }
1932
1933    /// Get the value of the `IPV6_UNICAST_HOPS` option for this socket.
1934    ///
1935    /// Specifies the hop limit for ipv6 unicast packets
1936    pub fn unicast_hops_v6(&self) -> io::Result<u32> {
1937        unsafe {
1938            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_UNICAST_HOPS)
1939                .map(|hops| hops as u32)
1940        }
1941    }
1942
1943    /// Set the value for the `IPV6_UNICAST_HOPS` option on this socket.
1944    ///
1945    /// Specifies the hop limit for ipv6 unicast packets
1946    pub fn set_unicast_hops_v6(&self, hops: u32) -> io::Result<()> {
1947        unsafe {
1948            setsockopt(
1949                self.as_raw(),
1950                sys::IPPROTO_IPV6,
1951                sys::IPV6_UNICAST_HOPS,
1952                hops as c_int,
1953            )
1954        }
1955    }
1956
1957    /// Get the value of the `IPV6_V6ONLY` option for this socket.
1958    ///
1959    /// For more information about this option, see [`set_only_v6`].
1960    ///
1961    /// [`set_only_v6`]: Socket::set_only_v6
1962    pub fn only_v6(&self) -> io::Result<bool> {
1963        unsafe {
1964            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_V6ONLY)
1965                .map(|only_v6| only_v6 != 0)
1966        }
1967    }
1968
1969    /// Set the value for the `IPV6_V6ONLY` option on this socket.
1970    ///
1971    /// If this is set to `true` then the socket is restricted to sending and
1972    /// receiving IPv6 packets only. In this case two IPv4 and IPv6 applications
1973    /// can bind the same port at the same time.
1974    ///
1975    /// If this is set to `false` then the socket can be used to send and
1976    /// receive packets from an IPv4-mapped IPv6 address.
1977    pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
1978        unsafe {
1979            setsockopt(
1980                self.as_raw(),
1981                sys::IPPROTO_IPV6,
1982                sys::IPV6_V6ONLY,
1983                only_v6 as c_int,
1984            )
1985        }
1986    }
1987
1988    /// Get the value of the `IPV6_RECVTCLASS` option for this socket.
1989    ///
1990    /// For more information about this option, see [`set_recv_tclass_v6`].
1991    ///
1992    /// [`set_recv_tclass_v6`]: Socket::set_recv_tclass_v6
1993    #[cfg(not(any(
1994        target_os = "dragonfly",
1995        target_os = "fuchsia",
1996        target_os = "illumos",
1997        target_os = "netbsd",
1998        target_os = "openbsd",
1999        target_os = "redox",
2000        target_os = "solaris",
2001        target_os = "haiku",
2002        target_os = "hurd",
2003        target_os = "espidf",
2004        target_os = "vita",
2005    )))]
2006    pub fn recv_tclass_v6(&self) -> io::Result<bool> {
2007        unsafe {
2008            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_RECVTCLASS)
2009                .map(|recv_tclass| recv_tclass > 0)
2010        }
2011    }
2012
2013    /// Set the value of the `IPV6_RECVTCLASS` option for this socket.
2014    ///
2015    /// If enabled, the `IPV6_TCLASS` ancillary message is passed with incoming
2016    /// packets. It contains a byte which specifies the traffic class field of
2017    /// the packet header.
2018    #[cfg(not(any(
2019        target_os = "dragonfly",
2020        target_os = "fuchsia",
2021        target_os = "illumos",
2022        target_os = "netbsd",
2023        target_os = "openbsd",
2024        target_os = "redox",
2025        target_os = "solaris",
2026        target_os = "haiku",
2027        target_os = "hurd",
2028        target_os = "espidf",
2029        target_os = "vita",
2030    )))]
2031    pub fn set_recv_tclass_v6(&self, recv_tclass: bool) -> io::Result<()> {
2032        unsafe {
2033            setsockopt(
2034                self.as_raw(),
2035                sys::IPPROTO_IPV6,
2036                sys::IPV6_RECVTCLASS,
2037                recv_tclass as c_int,
2038            )
2039        }
2040    }
2041
2042    /// Get the value of the `IPV6_RECVHOPLIMIT` option for this socket.
2043    ///
2044    /// For more information about this option, see [`set_recv_hoplimit_v6`].
2045    ///
2046    /// [`set_recv_hoplimit_v6`]: Socket::set_recv_hoplimit_v6
2047    #[cfg(all(
2048        feature = "all",
2049        not(any(
2050            windows,
2051            target_os = "dragonfly",
2052            target_os = "fuchsia",
2053            target_os = "illumos",
2054            target_os = "netbsd",
2055            target_os = "openbsd",
2056            target_os = "redox",
2057            target_os = "solaris",
2058            target_os = "haiku",
2059            target_os = "hurd",
2060            target_os = "espidf",
2061            target_os = "vita",
2062            target_os = "cygwin",
2063        ))
2064    ))]
2065    pub fn recv_hoplimit_v6(&self) -> io::Result<bool> {
2066        unsafe {
2067            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_RECVHOPLIMIT)
2068                .map(|recv_hoplimit| recv_hoplimit > 0)
2069        }
2070    }
2071    /// Set the value of the `IPV6_RECVHOPLIMIT` option for this socket.
2072    ///
2073    /// The received hop limit is returned as ancillary data by recvmsg()
2074    /// only if the application has enabled the IPV6_RECVHOPLIMIT socket
2075    /// option:
2076    #[cfg(all(
2077        feature = "all",
2078        not(any(
2079            windows,
2080            target_os = "dragonfly",
2081            target_os = "fuchsia",
2082            target_os = "illumos",
2083            target_os = "netbsd",
2084            target_os = "openbsd",
2085            target_os = "redox",
2086            target_os = "solaris",
2087            target_os = "haiku",
2088            target_os = "hurd",
2089            target_os = "espidf",
2090            target_os = "vita",
2091            target_os = "cygwin",
2092        ))
2093    ))]
2094    pub fn set_recv_hoplimit_v6(&self, recv_hoplimit: bool) -> io::Result<()> {
2095        unsafe {
2096            setsockopt(
2097                self.as_raw(),
2098                sys::IPPROTO_IPV6,
2099                sys::IPV6_RECVHOPLIMIT,
2100                recv_hoplimit as c_int,
2101            )
2102        }
2103    }
2104}
2105
2106/// Socket options for TCP sockets, get/set using `IPPROTO_TCP`.
2107///
2108/// Additional documentation can be found in documentation of the OS.
2109/// * Linux: <https://man7.org/linux/man-pages/man7/tcp.7.html>
2110/// * Windows: <https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options>
2111impl Socket {
2112    /// Get the value of the `TCP_KEEPIDLE` option on this socket.
2113    ///
2114    /// This returns the value of `TCP_KEEPALIVE` on macOS and iOS and `TCP_KEEPIDLE` on all other
2115    /// supported Unix operating systems.
2116    #[cfg(all(
2117        feature = "all",
2118        not(any(
2119            windows,
2120            target_os = "haiku",
2121            target_os = "openbsd",
2122            target_os = "vita"
2123        ))
2124    ))]
2125    #[cfg_attr(
2126        docsrs,
2127        doc(cfg(all(
2128            feature = "all",
2129            not(any(
2130                windows,
2131                target_os = "haiku",
2132                target_os = "openbsd",
2133                target_os = "vita"
2134            ))
2135        )))
2136    )]
2137    pub fn keepalive_time(&self) -> io::Result<Duration> {
2138        sys::keepalive_time(self.as_raw())
2139    }
2140
2141    /// Get the value of the `TCP_KEEPINTVL` option on this socket.
2142    ///
2143    /// For more information about this option, see [`set_tcp_keepalive`].
2144    ///
2145    /// [`set_tcp_keepalive`]: Socket::set_tcp_keepalive
2146    #[cfg(all(
2147        feature = "all",
2148        any(
2149            target_os = "android",
2150            target_os = "dragonfly",
2151            target_os = "freebsd",
2152            target_os = "fuchsia",
2153            target_os = "illumos",
2154            target_os = "ios",
2155            target_os = "visionos",
2156            target_os = "linux",
2157            target_os = "macos",
2158            target_os = "netbsd",
2159            target_os = "tvos",
2160            target_os = "watchos",
2161            target_os = "cygwin",
2162        )
2163    ))]
2164    #[cfg_attr(
2165        docsrs,
2166        doc(cfg(all(
2167            feature = "all",
2168            any(
2169                target_os = "android",
2170                target_os = "dragonfly",
2171                target_os = "freebsd",
2172                target_os = "fuchsia",
2173                target_os = "illumos",
2174                target_os = "ios",
2175                target_os = "visionos",
2176                target_os = "linux",
2177                target_os = "macos",
2178                target_os = "netbsd",
2179                target_os = "tvos",
2180                target_os = "watchos",
2181            )
2182        )))
2183    )]
2184    pub fn keepalive_interval(&self) -> io::Result<Duration> {
2185        unsafe {
2186            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_TCP, sys::TCP_KEEPINTVL)
2187                .map(|secs| Duration::from_secs(secs as u64))
2188        }
2189    }
2190
2191    /// Get the value of the `TCP_KEEPCNT` option on this socket.
2192    ///
2193    /// For more information about this option, see [`set_tcp_keepalive`].
2194    ///
2195    /// [`set_tcp_keepalive`]: Socket::set_tcp_keepalive
2196    #[cfg(all(
2197        feature = "all",
2198        any(
2199            target_os = "android",
2200            target_os = "dragonfly",
2201            target_os = "freebsd",
2202            target_os = "fuchsia",
2203            target_os = "illumos",
2204            target_os = "ios",
2205            target_os = "visionos",
2206            target_os = "linux",
2207            target_os = "macos",
2208            target_os = "netbsd",
2209            target_os = "tvos",
2210            target_os = "watchos",
2211            target_os = "cygwin",
2212        )
2213    ))]
2214    #[cfg_attr(
2215        docsrs,
2216        doc(cfg(all(
2217            feature = "all",
2218            any(
2219                target_os = "android",
2220                target_os = "dragonfly",
2221                target_os = "freebsd",
2222                target_os = "fuchsia",
2223                target_os = "illumos",
2224                target_os = "ios",
2225                target_os = "visionos",
2226                target_os = "linux",
2227                target_os = "macos",
2228                target_os = "netbsd",
2229                target_os = "tvos",
2230                target_os = "watchos",
2231            )
2232        )))
2233    )]
2234    pub fn keepalive_retries(&self) -> io::Result<u32> {
2235        unsafe {
2236            getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_TCP, sys::TCP_KEEPCNT)
2237                .map(|retries| retries as u32)
2238        }
2239    }
2240
2241    /// Set parameters configuring TCP keepalive probes for this socket.
2242    ///
2243    /// The supported parameters depend on the operating system, and are
2244    /// configured using the [`TcpKeepalive`] struct. At a minimum, all systems
2245    /// support configuring the [keepalive time]: the time after which the OS
2246    /// will start sending keepalive messages on an idle connection.
2247    ///
2248    /// [keepalive time]: TcpKeepalive::with_time
2249    ///
2250    /// # Notes
2251    ///
2252    /// * This will enable `SO_KEEPALIVE` on this socket, if it is not already
2253    ///   enabled.
2254    /// * On some platforms, such as Windows, any keepalive parameters *not*
2255    ///   configured by the `TcpKeepalive` struct passed to this function may be
2256    ///   overwritten with their default values. Therefore, this function should
2257    ///   either only be called once per socket, or the same parameters should
2258    ///   be passed every time it is called.
2259    ///
2260    /// # Examples
2261    ///
2262    /// ```
2263    /// use std::time::Duration;
2264    ///
2265    /// use socket2::{Socket, TcpKeepalive, Domain, Type};
2266    ///
2267    /// # fn main() -> std::io::Result<()> {
2268    /// let socket = Socket::new(Domain::IPV4, Type::STREAM, None)?;
2269    /// let keepalive = TcpKeepalive::new()
2270    ///     .with_time(Duration::from_secs(4));
2271    ///     // Depending on the target operating system, we may also be able to
2272    ///     // configure the keepalive probe interval and/or the number of
2273    ///     // retries here as well.
2274    ///
2275    /// socket.set_tcp_keepalive(&keepalive)?;
2276    /// # Ok(()) }
2277    /// ```
2278    ///
2279    pub fn set_tcp_keepalive(&self, params: &TcpKeepalive) -> io::Result<()> {
2280        self.set_keepalive(true)?;
2281        sys::set_tcp_keepalive(self.as_raw(), params)
2282    }
2283
2284    /// Get the value of the `TCP_NODELAY` option on this socket.
2285    ///
2286    /// For more information about this option, see [`set_nodelay`].
2287    ///
2288    /// [`set_nodelay`]: Socket::set_nodelay
2289    pub fn nodelay(&self) -> io::Result<bool> {
2290        unsafe {
2291            getsockopt::<Bool>(self.as_raw(), sys::IPPROTO_TCP, sys::TCP_NODELAY)
2292                .map(|nodelay| nodelay != 0)
2293        }
2294    }
2295
2296    /// Set the value of the `TCP_NODELAY` option on this socket.
2297    ///
2298    /// If set, this option disables the Nagle algorithm. This means that
2299    /// segments are always sent as soon as possible, even if there is only a
2300    /// small amount of data. When not set, data is buffered until there is a
2301    /// sufficient amount to send out, thereby avoiding the frequent sending of
2302    /// small packets.
2303    pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
2304        unsafe {
2305            setsockopt(
2306                self.as_raw(),
2307                sys::IPPROTO_TCP,
2308                sys::TCP_NODELAY,
2309                nodelay as c_int,
2310            )
2311        }
2312    }
2313
2314    /// Get the value for the `SO_ORIGINAL_DST` option on this socket.
2315    #[cfg(all(
2316        feature = "all",
2317        any(
2318            target_os = "android",
2319            target_os = "fuchsia",
2320            target_os = "linux",
2321            target_os = "windows",
2322        )
2323    ))]
2324    #[cfg_attr(
2325        docsrs,
2326        doc(cfg(all(
2327            feature = "all",
2328            any(
2329                target_os = "android",
2330                target_os = "fuchsia",
2331                target_os = "linux",
2332                target_os = "windows",
2333            )
2334        )))
2335    )]
2336    pub fn original_dst(&self) -> io::Result<SockAddr> {
2337        sys::original_dst(self.as_raw())
2338    }
2339
2340    /// Get the value for the `IP6T_SO_ORIGINAL_DST` option on this socket.
2341    #[cfg(all(
2342        feature = "all",
2343        any(target_os = "android", target_os = "linux", target_os = "windows")
2344    ))]
2345    #[cfg_attr(
2346        docsrs,
2347        doc(cfg(all(
2348            feature = "all",
2349            any(target_os = "android", target_os = "linux", target_os = "windows")
2350        )))
2351    )]
2352    pub fn original_dst_ipv6(&self) -> io::Result<SockAddr> {
2353        sys::original_dst_ipv6(self.as_raw())
2354    }
2355}
2356
2357impl Read for Socket {
2358    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
2359        // Safety: the `recv` implementation promises not to write uninitialised
2360        // bytes to the `buf`fer, so this casting is safe.
2361        let buf = unsafe { &mut *(buf as *mut [u8] as *mut [MaybeUninit<u8>]) };
2362        self.recv(buf)
2363    }
2364
2365    #[cfg(not(target_os = "redox"))]
2366    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
2367        // Safety: both `IoSliceMut` and `MaybeUninitSlice` promise to have the
2368        // same layout, that of `iovec`/`WSABUF`. Furthermore, `recv_vectored`
2369        // promises to not write unitialised bytes to the `bufs` and pass it
2370        // directly to the `recvmsg` system call, so this is safe.
2371        let bufs = unsafe { &mut *(bufs as *mut [IoSliceMut<'_>] as *mut [MaybeUninitSlice<'_>]) };
2372        self.recv_vectored(bufs).map(|(n, _)| n)
2373    }
2374}
2375
2376impl<'a> Read for &'a Socket {
2377    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
2378        // Safety: see other `Read::read` impl.
2379        let buf = unsafe { &mut *(buf as *mut [u8] as *mut [MaybeUninit<u8>]) };
2380        self.recv(buf)
2381    }
2382
2383    #[cfg(not(target_os = "redox"))]
2384    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
2385        // Safety: see other `Read::read` impl.
2386        let bufs = unsafe { &mut *(bufs as *mut [IoSliceMut<'_>] as *mut [MaybeUninitSlice<'_>]) };
2387        self.recv_vectored(bufs).map(|(n, _)| n)
2388    }
2389}
2390
2391impl Write for Socket {
2392    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
2393        self.send(buf)
2394    }
2395
2396    #[cfg(not(target_os = "redox"))]
2397    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
2398        self.send_vectored(bufs)
2399    }
2400
2401    fn flush(&mut self) -> io::Result<()> {
2402        Ok(())
2403    }
2404}
2405
2406impl<'a> Write for &'a Socket {
2407    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
2408        self.send(buf)
2409    }
2410
2411    #[cfg(not(target_os = "redox"))]
2412    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
2413        self.send_vectored(bufs)
2414    }
2415
2416    fn flush(&mut self) -> io::Result<()> {
2417        Ok(())
2418    }
2419}
2420
2421impl fmt::Debug for Socket {
2422    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2423        f.debug_struct("Socket")
2424            .field("raw", &self.as_raw())
2425            .field("local_addr", &self.local_addr().ok())
2426            .field("peer_addr", &self.peer_addr().ok())
2427            .finish()
2428    }
2429}
2430
2431from!(net::TcpStream, Socket);
2432from!(net::TcpListener, Socket);
2433from!(net::UdpSocket, Socket);
2434from!(Socket, net::TcpStream);
2435from!(Socket, net::TcpListener);
2436from!(Socket, net::UdpSocket);