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