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