/rust/registry/src/index.crates.io-6f17d22bba15001f/socket2-0.5.9/src/lib.rs
Line | Count | Source (jump to first uncovered line) |
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 | | //! Utilities for creating and using sockets. |
10 | | //! |
11 | | //! The goal of this crate is to create and use a socket using advanced |
12 | | //! configuration options (those that are not available in the types in the |
13 | | //! standard library) without using any unsafe code. |
14 | | //! |
15 | | //! This crate provides as direct as possible access to the system's |
16 | | //! functionality for sockets, this means little effort to provide |
17 | | //! cross-platform utilities. It is up to the user to know how to use sockets |
18 | | //! when using this crate. *If you don't know how to create a socket using |
19 | | //! libc/system calls then this crate is not for you*. Most, if not all, |
20 | | //! functions directly relate to the equivalent system call with no error |
21 | | //! handling applied, so no handling errors such as [`EINTR`]. As a result using |
22 | | //! this crate can be a little wordy, but it should give you maximal flexibility |
23 | | //! over configuration of sockets. |
24 | | //! |
25 | | //! [`EINTR`]: std::io::ErrorKind::Interrupted |
26 | | //! |
27 | | //! # Examples |
28 | | //! |
29 | | //! ```no_run |
30 | | //! # fn main() -> std::io::Result<()> { |
31 | | //! use std::net::{SocketAddr, TcpListener}; |
32 | | //! use socket2::{Socket, Domain, Type}; |
33 | | //! |
34 | | //! // Create a TCP listener bound to two addresses. |
35 | | //! let socket = Socket::new(Domain::IPV6, Type::STREAM, None)?; |
36 | | //! |
37 | | //! socket.set_only_v6(false)?; |
38 | | //! let address: SocketAddr = "[::1]:12345".parse().unwrap(); |
39 | | //! socket.bind(&address.into())?; |
40 | | //! socket.listen(128)?; |
41 | | //! |
42 | | //! let listener: TcpListener = socket.into(); |
43 | | //! // ... |
44 | | //! # drop(listener); |
45 | | //! # Ok(()) } |
46 | | //! ``` |
47 | | //! |
48 | | //! ## Features |
49 | | //! |
50 | | //! This crate has a single feature `all`, which enables all functions even ones |
51 | | //! that are not available on all OSs. |
52 | | |
53 | | #![deny(missing_docs, missing_debug_implementations, rust_2018_idioms)] |
54 | | // Show required OS/features on docs.rs. |
55 | | #![cfg_attr(docsrs, feature(doc_cfg))] |
56 | | // Disallow warnings when running tests. |
57 | | #![cfg_attr(test, deny(warnings))] |
58 | | // Disallow warnings in examples. |
59 | | #![doc(test(attr(deny(warnings))))] |
60 | | |
61 | | use std::fmt; |
62 | | #[cfg(not(target_os = "redox"))] |
63 | | use std::io::IoSlice; |
64 | | #[cfg(not(target_os = "redox"))] |
65 | | use std::marker::PhantomData; |
66 | | #[cfg(not(target_os = "redox"))] |
67 | | use std::mem; |
68 | | use std::mem::MaybeUninit; |
69 | | use std::net::SocketAddr; |
70 | | use std::ops::{Deref, DerefMut}; |
71 | | use std::time::Duration; |
72 | | |
73 | | /// Macro to implement `fmt::Debug` for a type, printing the constant names |
74 | | /// rather than a number. |
75 | | /// |
76 | | /// Note this is used in the `sys` module and thus must be defined before |
77 | | /// defining the modules. |
78 | | macro_rules! impl_debug { |
79 | | ( |
80 | | // Type name for which to implement `fmt::Debug`. |
81 | | $type: path, |
82 | | $( |
83 | | $(#[$target: meta])* |
84 | | // The flag(s) to check. |
85 | | // Need to specific the libc crate because Windows doesn't use |
86 | | // `libc` but `windows_sys`. |
87 | | $libc: ident :: $flag: ident |
88 | | ),+ $(,)* |
89 | | ) => { |
90 | | impl std::fmt::Debug for $type { |
91 | 0 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
92 | 0 | let string = match self.0 { |
93 | | $( |
94 | | $(#[$target])* |
95 | 0 | $libc :: $flag => stringify!($flag), |
96 | | )+ |
97 | 0 | n => return write!(f, "{n}"), |
98 | | }; |
99 | 0 | f.write_str(string) |
100 | 0 | } Unexecuted instantiation: <socket2::Domain as core::fmt::Debug>::fmt Unexecuted instantiation: <socket2::Type as core::fmt::Debug>::fmt Unexecuted instantiation: <socket2::Protocol as core::fmt::Debug>::fmt |
101 | | } |
102 | | }; |
103 | | } |
104 | | |
105 | | /// Macro to convert from one network type to another. |
106 | | macro_rules! from { |
107 | | ($from: ty, $for: ty) => { |
108 | | impl From<$from> for $for { |
109 | 0 | fn from(socket: $from) -> $for { |
110 | 0 | #[cfg(unix)] |
111 | 0 | unsafe { |
112 | 0 | <$for>::from_raw_fd(socket.into_raw_fd()) |
113 | 0 | } |
114 | 0 | #[cfg(windows)] |
115 | 0 | unsafe { |
116 | 0 | <$for>::from_raw_socket(socket.into_raw_socket()) |
117 | 0 | } |
118 | 0 | } Unexecuted instantiation: <socket2::socket::Socket as core::convert::From<std::net::tcp::TcpStream>>::from Unexecuted instantiation: <socket2::socket::Socket as core::convert::From<std::net::tcp::TcpListener>>::from Unexecuted instantiation: <socket2::socket::Socket as core::convert::From<std::net::udp::UdpSocket>>::from Unexecuted instantiation: <socket2::socket::Socket as core::convert::From<std::os::unix::net::stream::UnixStream>>::from Unexecuted instantiation: <socket2::socket::Socket as core::convert::From<std::os::unix::net::listener::UnixListener>>::from Unexecuted instantiation: <socket2::socket::Socket as core::convert::From<std::os::unix::net::datagram::UnixDatagram>>::from Unexecuted instantiation: <std::net::tcp::TcpStream as core::convert::From<socket2::socket::Socket>>::from Unexecuted instantiation: <std::net::tcp::TcpListener as core::convert::From<socket2::socket::Socket>>::from Unexecuted instantiation: <std::net::udp::UdpSocket as core::convert::From<socket2::socket::Socket>>::from Unexecuted instantiation: <std::os::unix::net::datagram::UnixDatagram as core::convert::From<socket2::socket::Socket>>::from Unexecuted instantiation: <std::os::unix::net::stream::UnixStream as core::convert::From<socket2::socket::Socket>>::from Unexecuted instantiation: <std::os::unix::net::listener::UnixListener as core::convert::From<socket2::socket::Socket>>::from |
119 | | } |
120 | | }; |
121 | | } |
122 | | |
123 | | /// Link to online documentation for (almost) all supported OSs. |
124 | | #[rustfmt::skip] |
125 | | macro_rules! man_links { |
126 | | // Links to all OSs. |
127 | | ($syscall: tt ( $section: tt ) ) => { |
128 | | concat!( |
129 | | man_links!(__ intro), |
130 | | man_links!(__ unix $syscall($section)), |
131 | | man_links!(__ windows $syscall($section)), |
132 | | ) |
133 | | }; |
134 | | // Links to Unix-like OSs. |
135 | | (unix: $syscall: tt ( $section: tt ) ) => { |
136 | | concat!( |
137 | | man_links!(__ intro), |
138 | | man_links!(__ unix $syscall($section)), |
139 | | ) |
140 | | }; |
141 | | // Links to Windows only. |
142 | | (windows: $syscall: tt ( $section: tt ) ) => { |
143 | | concat!( |
144 | | man_links!(__ intro), |
145 | | man_links!(__ windows $syscall($section)), |
146 | | ) |
147 | | }; |
148 | | // Internals. |
149 | | (__ intro) => { |
150 | | "\n\nAdditional documentation can be found in manual of the OS:\n\n" |
151 | | }; |
152 | | // List for Unix-like OSs. |
153 | | (__ unix $syscall: tt ( $section: tt ) ) => { |
154 | | concat!( |
155 | | " * DragonFly BSD: <https://man.dragonflybsd.org/?command=", stringify!($syscall), "§ion=", stringify!($section), ">\n", |
156 | | " * FreeBSD: <https://www.freebsd.org/cgi/man.cgi?query=", stringify!($syscall), "&sektion=", stringify!($section), ">\n", |
157 | | " * Linux: <https://man7.org/linux/man-pages/man", stringify!($section), "/", stringify!($syscall), ".", stringify!($section), ".html>\n", |
158 | | " * macOS: <https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/", stringify!($syscall), ".", stringify!($section), ".html> (archived, actually for iOS)\n", |
159 | | " * NetBSD: <https://man.netbsd.org/", stringify!($syscall), ".", stringify!($section), ">\n", |
160 | | " * OpenBSD: <https://man.openbsd.org/", stringify!($syscall), ".", stringify!($section), ">\n", |
161 | | " * iOS: <https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/", stringify!($syscall), ".", stringify!($section), ".html> (archived)\n", |
162 | | " * illumos: <https://illumos.org/man/3SOCKET/", stringify!($syscall), ">\n", |
163 | | ) |
164 | | }; |
165 | | // List for Window (so just Windows). |
166 | | (__ windows $syscall: tt ( $section: tt ) ) => { |
167 | | concat!( |
168 | | " * Windows: <https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-", stringify!($syscall), ">\n", |
169 | | ) |
170 | | }; |
171 | | } |
172 | | |
173 | | mod sockaddr; |
174 | | mod socket; |
175 | | mod sockref; |
176 | | |
177 | | #[cfg_attr(unix, path = "sys/unix.rs")] |
178 | | #[cfg_attr(windows, path = "sys/windows.rs")] |
179 | | mod sys; |
180 | | |
181 | | #[cfg(not(any(windows, unix)))] |
182 | | compile_error!("Socket2 doesn't support the compile target"); |
183 | | |
184 | | use sys::c_int; |
185 | | |
186 | | pub use sockaddr::SockAddr; |
187 | | pub use socket::Socket; |
188 | | pub use sockref::SockRef; |
189 | | |
190 | | #[cfg(not(any( |
191 | | target_os = "haiku", |
192 | | target_os = "illumos", |
193 | | target_os = "netbsd", |
194 | | target_os = "redox", |
195 | | target_os = "solaris", |
196 | | )))] |
197 | | pub use socket::InterfaceIndexOrAddress; |
198 | | |
199 | | /// Specification of the communication domain for a socket. |
200 | | /// |
201 | | /// This is a newtype wrapper around an integer which provides a nicer API in |
202 | | /// addition to an injection point for documentation. Convenience constants such |
203 | | /// as [`Domain::IPV4`], [`Domain::IPV6`], etc, are provided to avoid reaching |
204 | | /// into libc for various constants. |
205 | | /// |
206 | | /// This type is freely interconvertible with C's `int` type, however, if a raw |
207 | | /// value needs to be provided. |
208 | | #[derive(Copy, Clone, Eq, PartialEq)] |
209 | | pub struct Domain(c_int); |
210 | | |
211 | | impl Domain { |
212 | | /// Domain for IPv4 communication, corresponding to `AF_INET`. |
213 | | pub const IPV4: Domain = Domain(sys::AF_INET); |
214 | | |
215 | | /// Domain for IPv6 communication, corresponding to `AF_INET6`. |
216 | | pub const IPV6: Domain = Domain(sys::AF_INET6); |
217 | | |
218 | | /// Domain for Unix socket communication, corresponding to `AF_UNIX`. |
219 | | pub const UNIX: Domain = Domain(sys::AF_UNIX); |
220 | | |
221 | | /// Returns the correct domain for `address`. |
222 | 0 | pub const fn for_address(address: SocketAddr) -> Domain { |
223 | 0 | match address { |
224 | 0 | SocketAddr::V4(_) => Domain::IPV4, |
225 | 0 | SocketAddr::V6(_) => Domain::IPV6, |
226 | | } |
227 | 0 | } |
228 | | } |
229 | | |
230 | | impl From<c_int> for Domain { |
231 | 0 | fn from(d: c_int) -> Domain { |
232 | 0 | Domain(d) |
233 | 0 | } |
234 | | } |
235 | | |
236 | | impl From<Domain> for c_int { |
237 | 0 | fn from(d: Domain) -> c_int { |
238 | 0 | d.0 |
239 | 0 | } |
240 | | } |
241 | | |
242 | | /// Specification of communication semantics on a socket. |
243 | | /// |
244 | | /// This is a newtype wrapper around an integer which provides a nicer API in |
245 | | /// addition to an injection point for documentation. Convenience constants such |
246 | | /// as [`Type::STREAM`], [`Type::DGRAM`], etc, are provided to avoid reaching |
247 | | /// into libc for various constants. |
248 | | /// |
249 | | /// This type is freely interconvertible with C's `int` type, however, if a raw |
250 | | /// value needs to be provided. |
251 | | #[derive(Copy, Clone, Eq, PartialEq)] |
252 | | pub struct Type(c_int); |
253 | | |
254 | | impl Type { |
255 | | /// Type corresponding to `SOCK_STREAM`. |
256 | | /// |
257 | | /// Used for protocols such as TCP. |
258 | | pub const STREAM: Type = Type(sys::SOCK_STREAM); |
259 | | |
260 | | /// Type corresponding to `SOCK_DGRAM`. |
261 | | /// |
262 | | /// Used for protocols such as UDP. |
263 | | pub const DGRAM: Type = Type(sys::SOCK_DGRAM); |
264 | | |
265 | | /// Type corresponding to `SOCK_DCCP`. |
266 | | /// |
267 | | /// Used for the DCCP protocol. |
268 | | #[cfg(all(feature = "all", target_os = "linux"))] |
269 | | #[cfg_attr(docsrs, doc(cfg(all(feature = "all", target_os = "linux"))))] |
270 | | pub const DCCP: Type = Type(sys::SOCK_DCCP); |
271 | | |
272 | | /// Type corresponding to `SOCK_SEQPACKET`. |
273 | | #[cfg(all(feature = "all", not(target_os = "espidf")))] |
274 | | #[cfg_attr(docsrs, doc(cfg(all(feature = "all", not(target_os = "espidf")))))] |
275 | | pub const SEQPACKET: Type = Type(sys::SOCK_SEQPACKET); |
276 | | |
277 | | /// Type corresponding to `SOCK_RAW`. |
278 | | #[cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))] |
279 | | #[cfg_attr( |
280 | | docsrs, |
281 | | doc(cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))) |
282 | | )] |
283 | | pub const RAW: Type = Type(sys::SOCK_RAW); |
284 | | } |
285 | | |
286 | | impl From<c_int> for Type { |
287 | 0 | fn from(t: c_int) -> Type { |
288 | 0 | Type(t) |
289 | 0 | } |
290 | | } |
291 | | |
292 | | impl From<Type> for c_int { |
293 | 0 | fn from(t: Type) -> c_int { |
294 | 0 | t.0 |
295 | 0 | } |
296 | | } |
297 | | |
298 | | /// Protocol specification used for creating sockets via `Socket::new`. |
299 | | /// |
300 | | /// This is a newtype wrapper around an integer which provides a nicer API in |
301 | | /// addition to an injection point for documentation. |
302 | | /// |
303 | | /// This type is freely interconvertible with C's `int` type, however, if a raw |
304 | | /// value needs to be provided. |
305 | | #[derive(Copy, Clone, Eq, PartialEq)] |
306 | | pub struct Protocol(c_int); |
307 | | |
308 | | impl Protocol { |
309 | | /// Protocol corresponding to `ICMPv4`. |
310 | | pub const ICMPV4: Protocol = Protocol(sys::IPPROTO_ICMP); |
311 | | |
312 | | /// Protocol corresponding to `ICMPv6`. |
313 | | pub const ICMPV6: Protocol = Protocol(sys::IPPROTO_ICMPV6); |
314 | | |
315 | | /// Protocol corresponding to `TCP`. |
316 | | pub const TCP: Protocol = Protocol(sys::IPPROTO_TCP); |
317 | | |
318 | | /// Protocol corresponding to `UDP`. |
319 | | pub const UDP: Protocol = Protocol(sys::IPPROTO_UDP); |
320 | | |
321 | | #[cfg(target_os = "linux")] |
322 | | /// Protocol corresponding to `MPTCP`. |
323 | | pub const MPTCP: Protocol = Protocol(sys::IPPROTO_MPTCP); |
324 | | |
325 | | /// Protocol corresponding to `DCCP`. |
326 | | #[cfg(all(feature = "all", target_os = "linux"))] |
327 | | #[cfg_attr(docsrs, doc(cfg(all(feature = "all", target_os = "linux"))))] |
328 | | pub const DCCP: Protocol = Protocol(sys::IPPROTO_DCCP); |
329 | | |
330 | | /// Protocol corresponding to `SCTP`. |
331 | | #[cfg(all(feature = "all", any(target_os = "freebsd", target_os = "linux")))] |
332 | | pub const SCTP: Protocol = Protocol(sys::IPPROTO_SCTP); |
333 | | |
334 | | /// Protocol corresponding to `UDPLITE`. |
335 | | #[cfg(all( |
336 | | feature = "all", |
337 | | any( |
338 | | target_os = "android", |
339 | | target_os = "freebsd", |
340 | | target_os = "fuchsia", |
341 | | target_os = "linux", |
342 | | ) |
343 | | ))] |
344 | | pub const UDPLITE: Protocol = Protocol(sys::IPPROTO_UDPLITE); |
345 | | |
346 | | /// Protocol corresponding to `DIVERT`. |
347 | | #[cfg(all(feature = "all", any(target_os = "freebsd", target_os = "openbsd")))] |
348 | | pub const DIVERT: Protocol = Protocol(sys::IPPROTO_DIVERT); |
349 | | } |
350 | | |
351 | | impl From<c_int> for Protocol { |
352 | 0 | fn from(p: c_int) -> Protocol { |
353 | 0 | Protocol(p) |
354 | 0 | } |
355 | | } |
356 | | |
357 | | impl From<Protocol> for c_int { |
358 | 0 | fn from(p: Protocol) -> c_int { |
359 | 0 | p.0 |
360 | 0 | } |
361 | | } |
362 | | |
363 | | /// Flags for incoming messages. |
364 | | /// |
365 | | /// Flags provide additional information about incoming messages. |
366 | | #[cfg(not(target_os = "redox"))] |
367 | | #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))] |
368 | | #[derive(Copy, Clone, Eq, PartialEq)] |
369 | | pub struct RecvFlags(c_int); |
370 | | |
371 | | #[cfg(not(target_os = "redox"))] |
372 | | impl RecvFlags { |
373 | | /// Check if the message contains a truncated datagram. |
374 | | /// |
375 | | /// This flag is only used for datagram-based sockets, |
376 | | /// not for stream sockets. |
377 | | /// |
378 | | /// On Unix this corresponds to the `MSG_TRUNC` flag. |
379 | | /// On Windows this corresponds to the `WSAEMSGSIZE` error code. |
380 | | #[cfg(not(target_os = "espidf"))] |
381 | 0 | pub const fn is_truncated(self) -> bool { |
382 | 0 | self.0 & sys::MSG_TRUNC != 0 |
383 | 0 | } |
384 | | } |
385 | | |
386 | | /// A version of [`IoSliceMut`] that allows the buffer to be uninitialised. |
387 | | /// |
388 | | /// [`IoSliceMut`]: std::io::IoSliceMut |
389 | | #[repr(transparent)] |
390 | | pub struct MaybeUninitSlice<'a>(sys::MaybeUninitSlice<'a>); |
391 | | |
392 | | impl<'a> fmt::Debug for MaybeUninitSlice<'a> { |
393 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
394 | 0 | fmt::Debug::fmt(self.0.as_slice(), fmt) |
395 | 0 | } |
396 | | } |
397 | | |
398 | | impl<'a> MaybeUninitSlice<'a> { |
399 | | /// Creates a new `MaybeUninitSlice` wrapping a byte slice. |
400 | | /// |
401 | | /// # Panics |
402 | | /// |
403 | | /// Panics on Windows if the slice is larger than 4GB. |
404 | 0 | pub fn new(buf: &'a mut [MaybeUninit<u8>]) -> MaybeUninitSlice<'a> { |
405 | 0 | MaybeUninitSlice(sys::MaybeUninitSlice::new(buf)) |
406 | 0 | } |
407 | | } |
408 | | |
409 | | impl<'a> Deref for MaybeUninitSlice<'a> { |
410 | | type Target = [MaybeUninit<u8>]; |
411 | | |
412 | 0 | fn deref(&self) -> &[MaybeUninit<u8>] { |
413 | 0 | self.0.as_slice() |
414 | 0 | } |
415 | | } |
416 | | |
417 | | impl<'a> DerefMut for MaybeUninitSlice<'a> { |
418 | 0 | fn deref_mut(&mut self) -> &mut [MaybeUninit<u8>] { |
419 | 0 | self.0.as_mut_slice() |
420 | 0 | } |
421 | | } |
422 | | |
423 | | /// Configures a socket's TCP keepalive parameters. |
424 | | /// |
425 | | /// See [`Socket::set_tcp_keepalive`]. |
426 | | #[derive(Debug, Clone)] |
427 | | pub struct TcpKeepalive { |
428 | | #[cfg_attr( |
429 | | any(target_os = "openbsd", target_os = "haiku", target_os = "vita"), |
430 | | allow(dead_code) |
431 | | )] |
432 | | time: Option<Duration>, |
433 | | #[cfg(not(any( |
434 | | target_os = "openbsd", |
435 | | target_os = "redox", |
436 | | target_os = "solaris", |
437 | | target_os = "nto", |
438 | | target_os = "espidf", |
439 | | target_os = "vita", |
440 | | target_os = "haiku", |
441 | | )))] |
442 | | interval: Option<Duration>, |
443 | | #[cfg(not(any( |
444 | | target_os = "openbsd", |
445 | | target_os = "redox", |
446 | | target_os = "solaris", |
447 | | target_os = "windows", |
448 | | target_os = "nto", |
449 | | target_os = "espidf", |
450 | | target_os = "vita", |
451 | | target_os = "haiku", |
452 | | )))] |
453 | | retries: Option<u32>, |
454 | | } |
455 | | |
456 | | impl TcpKeepalive { |
457 | | /// Returns a new, empty set of TCP keepalive parameters. |
458 | | #[allow(clippy::new_without_default)] |
459 | 0 | pub const fn new() -> TcpKeepalive { |
460 | 0 | TcpKeepalive { |
461 | 0 | time: None, |
462 | 0 | #[cfg(not(any( |
463 | 0 | target_os = "openbsd", |
464 | 0 | target_os = "redox", |
465 | 0 | target_os = "solaris", |
466 | 0 | target_os = "nto", |
467 | 0 | target_os = "espidf", |
468 | 0 | target_os = "vita", |
469 | 0 | target_os = "haiku", |
470 | 0 | )))] |
471 | 0 | interval: None, |
472 | 0 | #[cfg(not(any( |
473 | 0 | target_os = "openbsd", |
474 | 0 | target_os = "redox", |
475 | 0 | target_os = "solaris", |
476 | 0 | target_os = "windows", |
477 | 0 | target_os = "nto", |
478 | 0 | target_os = "espidf", |
479 | 0 | target_os = "vita", |
480 | 0 | target_os = "haiku", |
481 | 0 | )))] |
482 | 0 | retries: None, |
483 | 0 | } |
484 | 0 | } |
485 | | |
486 | | /// Set the amount of time after which TCP keepalive probes will be sent on |
487 | | /// idle connections. |
488 | | /// |
489 | | /// This will set `TCP_KEEPALIVE` on macOS and iOS, and |
490 | | /// `TCP_KEEPIDLE` on all other Unix operating systems, except |
491 | | /// OpenBSD and Haiku which don't support any way to set this |
492 | | /// option. On Windows, this sets the value of the `tcp_keepalive` |
493 | | /// struct's `keepalivetime` field. |
494 | | /// |
495 | | /// Some platforms specify this value in seconds, so sub-second |
496 | | /// specifications may be omitted. |
497 | 0 | pub const fn with_time(self, time: Duration) -> Self { |
498 | 0 | Self { |
499 | 0 | time: Some(time), |
500 | 0 | ..self |
501 | 0 | } |
502 | 0 | } |
503 | | |
504 | | /// Set the value of the `TCP_KEEPINTVL` option. On Windows, this sets the |
505 | | /// value of the `tcp_keepalive` struct's `keepaliveinterval` field. |
506 | | /// |
507 | | /// Sets the time interval between TCP keepalive probes. |
508 | | /// |
509 | | /// Some platforms specify this value in seconds, so sub-second |
510 | | /// specifications may be omitted. |
511 | | #[cfg(any( |
512 | | target_os = "android", |
513 | | target_os = "dragonfly", |
514 | | target_os = "freebsd", |
515 | | target_os = "fuchsia", |
516 | | target_os = "illumos", |
517 | | target_os = "ios", |
518 | | target_os = "visionos", |
519 | | target_os = "linux", |
520 | | target_os = "macos", |
521 | | target_os = "netbsd", |
522 | | target_os = "tvos", |
523 | | target_os = "watchos", |
524 | | target_os = "windows", |
525 | | ))] |
526 | | #[cfg_attr( |
527 | | docsrs, |
528 | | doc(cfg(any( |
529 | | target_os = "android", |
530 | | target_os = "dragonfly", |
531 | | target_os = "freebsd", |
532 | | target_os = "fuchsia", |
533 | | target_os = "illumos", |
534 | | target_os = "ios", |
535 | | target_os = "visionos", |
536 | | target_os = "linux", |
537 | | target_os = "macos", |
538 | | target_os = "netbsd", |
539 | | target_os = "tvos", |
540 | | target_os = "watchos", |
541 | | target_os = "windows", |
542 | | ))) |
543 | | )] |
544 | 0 | pub const fn with_interval(self, interval: Duration) -> Self { |
545 | 0 | Self { |
546 | 0 | interval: Some(interval), |
547 | 0 | ..self |
548 | 0 | } |
549 | 0 | } |
550 | | |
551 | | /// Set the value of the `TCP_KEEPCNT` option. |
552 | | /// |
553 | | /// Set the maximum number of TCP keepalive probes that will be sent before |
554 | | /// dropping a connection, if TCP keepalive is enabled on this socket. |
555 | | #[cfg(all( |
556 | | feature = "all", |
557 | | any( |
558 | | target_os = "android", |
559 | | target_os = "dragonfly", |
560 | | target_os = "freebsd", |
561 | | target_os = "fuchsia", |
562 | | target_os = "illumos", |
563 | | target_os = "ios", |
564 | | target_os = "visionos", |
565 | | target_os = "linux", |
566 | | target_os = "macos", |
567 | | target_os = "netbsd", |
568 | | target_os = "tvos", |
569 | | target_os = "watchos", |
570 | | ) |
571 | | ))] |
572 | | #[cfg_attr( |
573 | | docsrs, |
574 | | doc(cfg(all( |
575 | | feature = "all", |
576 | | any( |
577 | | target_os = "android", |
578 | | target_os = "dragonfly", |
579 | | target_os = "freebsd", |
580 | | target_os = "fuchsia", |
581 | | target_os = "illumos", |
582 | | target_os = "ios", |
583 | | target_os = "visionos", |
584 | | target_os = "linux", |
585 | | target_os = "macos", |
586 | | target_os = "netbsd", |
587 | | target_os = "tvos", |
588 | | target_os = "watchos", |
589 | | ) |
590 | | ))) |
591 | | )] |
592 | 0 | pub const fn with_retries(self, retries: u32) -> Self { |
593 | 0 | Self { |
594 | 0 | retries: Some(retries), |
595 | 0 | ..self |
596 | 0 | } |
597 | 0 | } |
598 | | } |
599 | | |
600 | | /// Configuration of a `sendmsg(2)` system call. |
601 | | /// |
602 | | /// This wraps `msghdr` on Unix and `WSAMSG` on Windows. Also see [`MsgHdrMut`] |
603 | | /// for the variant used by `recvmsg(2)`. |
604 | | #[cfg(not(target_os = "redox"))] |
605 | | pub struct MsgHdr<'addr, 'bufs, 'control> { |
606 | | inner: sys::msghdr, |
607 | | #[allow(clippy::type_complexity)] |
608 | | _lifetimes: PhantomData<(&'addr SockAddr, &'bufs IoSlice<'bufs>, &'control [u8])>, |
609 | | } |
610 | | |
611 | | #[cfg(not(target_os = "redox"))] |
612 | | impl<'addr, 'bufs, 'control> MsgHdr<'addr, 'bufs, 'control> { |
613 | | /// Create a new `MsgHdr` with all empty/zero fields. |
614 | | #[allow(clippy::new_without_default)] |
615 | 0 | pub fn new() -> MsgHdr<'addr, 'bufs, 'control> { |
616 | 0 | // SAFETY: all zero is valid for `msghdr` and `WSAMSG`. |
617 | 0 | MsgHdr { |
618 | 0 | inner: unsafe { mem::zeroed() }, |
619 | 0 | _lifetimes: PhantomData, |
620 | 0 | } |
621 | 0 | } |
622 | | |
623 | | /// Set the address (name) of the message. |
624 | | /// |
625 | | /// Corresponds to setting `msg_name` and `msg_namelen` on Unix and `name` |
626 | | /// and `namelen` on Windows. |
627 | 0 | pub fn with_addr(mut self, addr: &'addr SockAddr) -> Self { |
628 | 0 | sys::set_msghdr_name(&mut self.inner, addr); |
629 | 0 | self |
630 | 0 | } |
631 | | |
632 | | /// Set the buffer(s) of the message. |
633 | | /// |
634 | | /// Corresponds to setting `msg_iov` and `msg_iovlen` on Unix and `lpBuffers` |
635 | | /// and `dwBufferCount` on Windows. |
636 | 0 | pub fn with_buffers(mut self, bufs: &'bufs [IoSlice<'_>]) -> Self { |
637 | 0 | let ptr = bufs.as_ptr() as *mut _; |
638 | 0 | sys::set_msghdr_iov(&mut self.inner, ptr, bufs.len()); |
639 | 0 | self |
640 | 0 | } |
641 | | |
642 | | /// Set the control buffer of the message. |
643 | | /// |
644 | | /// Corresponds to setting `msg_control` and `msg_controllen` on Unix and |
645 | | /// `Control` on Windows. |
646 | 0 | pub fn with_control(mut self, buf: &'control [u8]) -> Self { |
647 | 0 | let ptr = buf.as_ptr() as *mut _; |
648 | 0 | sys::set_msghdr_control(&mut self.inner, ptr, buf.len()); |
649 | 0 | self |
650 | 0 | } |
651 | | |
652 | | /// Set the flags of the message. |
653 | | /// |
654 | | /// Corresponds to setting `msg_flags` on Unix and `dwFlags` on Windows. |
655 | 0 | pub fn with_flags(mut self, flags: sys::c_int) -> Self { |
656 | 0 | sys::set_msghdr_flags(&mut self.inner, flags); |
657 | 0 | self |
658 | 0 | } |
659 | | } |
660 | | |
661 | | #[cfg(not(target_os = "redox"))] |
662 | | impl<'name, 'bufs, 'control> fmt::Debug for MsgHdr<'name, 'bufs, 'control> { |
663 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
664 | 0 | "MsgHdr".fmt(fmt) |
665 | 0 | } |
666 | | } |
667 | | |
668 | | /// Configuration of a `recvmsg(2)` system call. |
669 | | /// |
670 | | /// This wraps `msghdr` on Unix and `WSAMSG` on Windows. Also see [`MsgHdr`] for |
671 | | /// the variant used by `sendmsg(2)`. |
672 | | #[cfg(not(target_os = "redox"))] |
673 | | pub struct MsgHdrMut<'addr, 'bufs, 'control> { |
674 | | inner: sys::msghdr, |
675 | | #[allow(clippy::type_complexity)] |
676 | | _lifetimes: PhantomData<( |
677 | | &'addr mut SockAddr, |
678 | | &'bufs mut MaybeUninitSlice<'bufs>, |
679 | | &'control mut [u8], |
680 | | )>, |
681 | | } |
682 | | |
683 | | #[cfg(not(target_os = "redox"))] |
684 | | impl<'addr, 'bufs, 'control> MsgHdrMut<'addr, 'bufs, 'control> { |
685 | | /// Create a new `MsgHdrMut` with all empty/zero fields. |
686 | | #[allow(clippy::new_without_default)] |
687 | 0 | pub fn new() -> MsgHdrMut<'addr, 'bufs, 'control> { |
688 | 0 | // SAFETY: all zero is valid for `msghdr` and `WSAMSG`. |
689 | 0 | MsgHdrMut { |
690 | 0 | inner: unsafe { mem::zeroed() }, |
691 | 0 | _lifetimes: PhantomData, |
692 | 0 | } |
693 | 0 | } |
694 | | |
695 | | /// Set the mutable address (name) of the message. |
696 | | /// |
697 | | /// Corresponds to setting `msg_name` and `msg_namelen` on Unix and `name` |
698 | | /// and `namelen` on Windows. |
699 | | #[allow(clippy::needless_pass_by_ref_mut)] |
700 | 0 | pub fn with_addr(mut self, addr: &'addr mut SockAddr) -> Self { |
701 | 0 | sys::set_msghdr_name(&mut self.inner, addr); |
702 | 0 | self |
703 | 0 | } |
704 | | |
705 | | /// Set the mutable buffer(s) of the message. |
706 | | /// |
707 | | /// Corresponds to setting `msg_iov` and `msg_iovlen` on Unix and `lpBuffers` |
708 | | /// and `dwBufferCount` on Windows. |
709 | 0 | pub fn with_buffers(mut self, bufs: &'bufs mut [MaybeUninitSlice<'_>]) -> Self { |
710 | 0 | sys::set_msghdr_iov(&mut self.inner, bufs.as_mut_ptr().cast(), bufs.len()); |
711 | 0 | self |
712 | 0 | } |
713 | | |
714 | | /// Set the mutable control buffer of the message. |
715 | | /// |
716 | | /// Corresponds to setting `msg_control` and `msg_controllen` on Unix and |
717 | | /// `Control` on Windows. |
718 | 0 | pub fn with_control(mut self, buf: &'control mut [MaybeUninit<u8>]) -> Self { |
719 | 0 | sys::set_msghdr_control(&mut self.inner, buf.as_mut_ptr().cast(), buf.len()); |
720 | 0 | self |
721 | 0 | } |
722 | | |
723 | | /// Returns the flags of the message. |
724 | 0 | pub fn flags(&self) -> RecvFlags { |
725 | 0 | sys::msghdr_flags(&self.inner) |
726 | 0 | } |
727 | | |
728 | | /// Gets the length of the control buffer. |
729 | | /// |
730 | | /// Can be used to determine how much, if any, of the control buffer was filled by `recvmsg`. |
731 | | /// |
732 | | /// Corresponds to `msg_controllen` on Unix and `Control.len` on Windows. |
733 | 0 | pub fn control_len(&self) -> usize { |
734 | 0 | sys::msghdr_control_len(&self.inner) |
735 | 0 | } |
736 | | } |
737 | | |
738 | | #[cfg(not(target_os = "redox"))] |
739 | | impl<'name, 'bufs, 'control> fmt::Debug for MsgHdrMut<'name, 'bufs, 'control> { |
740 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
741 | 0 | "MsgHdrMut".fmt(fmt) |
742 | 0 | } |
743 | | } |