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