]>
git.proxmox.com Git - cargo.git/blob - vendor/socket2/src/lib.rs
1 // Copyright 2015 The Rust Project Developers.
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.
9 //! Utilities for creating and using sockets.
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.
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.
25 //! [`EINTR`]: std::io::ErrorKind::Interrupted
30 //! # fn main() -> std::io::Result<()> {
31 //! use std::net::{SocketAddr, TcpListener};
32 //! use socket2::{Socket, Domain, Type};
34 //! // Create a TCP listener bound to two addresses.
35 //! let socket = Socket::new(Domain::IPV6, Type::STREAM, None)?;
37 //! socket.set_only_v6(false)?;
38 //! let address: SocketAddr = "[::1]:12345".parse().unwrap();
39 //! socket.bind(&address.into())?;
40 //! socket.listen(128)?;
42 //! let listener: TcpListener = socket.into();
50 //! This crate has a single feature `all`, which enables all functions even ones
51 //! that are not available on all OSs.
53 #![doc(html_root_url = "https://docs.rs/socket2/0.4")]
54 #![deny(missing_docs, missing_debug_implementations, rust_2018_idioms)]
55 // Show required OS/features on docs.rs.
56 #![cfg_attr(docsrs, feature(doc_cfg))]
57 // Disallow warnings when running tests.
58 #![cfg_attr(test, deny(warnings))]
59 // Disallow warnings in examples.
60 #![doc(test(attr(deny(warnings))))]
63 use std
::mem
::MaybeUninit
;
64 use std
::net
::SocketAddr
;
65 use std
::ops
::{Deref, DerefMut}
;
66 use std
::time
::Duration
;
68 /// Macro to implement `fmt::Debug` for a type, printing the constant names
69 /// rather than a number.
71 /// Note this is used in the `sys` module and thus must be defined before
72 /// defining the modules.
73 macro_rules
! impl_debug
{
75 // Type name for which to implement `fmt::Debug`.
79 // The flag(s) to check.
80 // Need to specific the libc crate because Windows doesn't use
81 // `libc` but `winapi`.
82 $libc
: ident
:: $flag
: ident
85 impl std
::fmt
::Debug
for $
type {
86 fn fmt(&self, f
: &mut std
::fmt
::Formatter
<'_
>) -> std
::fmt
::Result
{
87 let string
= match self.0 {
90 $libc
:: $flag
=> stringify
!($flag
),
92 n
=> return write
!(f
, "{}", n
),
100 /// Macro to convert from one network type to another.
102 ($from
: ty
, $
for: ty
) => {
103 impl From
<$from
> for $
for {
104 fn from(socket
: $from
) -> $
for {
107 <$
for>::from_raw_fd(socket
.into_raw_fd())
111 <$
for>::from_raw_socket(socket
.into_raw_socket())
122 #[cfg_attr(unix, path = "sys/unix.rs")]
123 #[cfg_attr(windows, path = "sys/windows.rs")]
126 #[cfg(not(any(windows, unix)))]
127 compile_error
!("Socket2 doesn't support the compile target");
131 pub use sockaddr
::SockAddr
;
132 pub use socket
::Socket
;
133 pub use sockref
::SockRef
;
137 target_os
= "illumos",
138 target_os
= "netbsd",
140 target_os
= "solaris",
142 pub use socket
::InterfaceIndexOrAddress
;
144 /// Specification of the communication domain for a socket.
146 /// This is a newtype wrapper around an integer which provides a nicer API in
147 /// addition to an injection point for documentation. Convenience constants such
148 /// as [`Domain::IPV4`], [`Domain::IPV6`], etc, are provided to avoid reaching
149 /// into libc for various constants.
151 /// This type is freely interconvertible with C's `int` type, however, if a raw
152 /// value needs to be provided.
153 #[derive(Copy, Clone, Eq, PartialEq)]
154 pub struct Domain(c_int
);
157 /// Domain for IPv4 communication, corresponding to `AF_INET`.
158 pub const IPV4
: Domain
= Domain(sys
::AF_INET
);
160 /// Domain for IPv6 communication, corresponding to `AF_INET6`.
161 pub const IPV6
: Domain
= Domain(sys
::AF_INET6
);
163 /// Returns the correct domain for `address`.
164 pub const fn for_address(address
: SocketAddr
) -> Domain
{
166 SocketAddr
::V4(_
) => Domain
::IPV4
,
167 SocketAddr
::V6(_
) => Domain
::IPV6
,
172 impl From
<c_int
> for Domain
{
173 fn from(d
: c_int
) -> Domain
{
178 impl From
<Domain
> for c_int
{
179 fn from(d
: Domain
) -> c_int
{
184 /// Specification of communication semantics on a socket.
186 /// This is a newtype wrapper around an integer which provides a nicer API in
187 /// addition to an injection point for documentation. Convenience constants such
188 /// as [`Type::STREAM`], [`Type::DGRAM`], etc, are provided to avoid reaching
189 /// into libc for various constants.
191 /// This type is freely interconvertible with C's `int` type, however, if a raw
192 /// value needs to be provided.
193 #[derive(Copy, Clone, Eq, PartialEq)]
194 pub struct Type(c_int
);
197 /// Type corresponding to `SOCK_STREAM`.
199 /// Used for protocols such as TCP.
200 pub const STREAM
: Type
= Type(sys
::SOCK_STREAM
);
202 /// Type corresponding to `SOCK_DGRAM`.
204 /// Used for protocols such as UDP.
205 pub const DGRAM
: Type
= Type(sys
::SOCK_DGRAM
);
207 /// Type corresponding to `SOCK_SEQPACKET`.
208 #[cfg(feature = "all")]
209 #[cfg_attr(docsrs, doc(cfg(feature = "all")))]
210 pub const SEQPACKET
: Type
= Type(sys
::SOCK_SEQPACKET
);
212 /// Type corresponding to `SOCK_RAW`.
213 #[cfg(all(feature = "all", not(target_os = "redox")))]
214 #[cfg_attr(docsrs, doc(cfg(all(feature = "all", not(target_os = "redox")))))]
215 pub const RAW
: Type
= Type(sys
::SOCK_RAW
);
218 impl From
<c_int
> for Type
{
219 fn from(t
: c_int
) -> Type
{
224 impl From
<Type
> for c_int
{
225 fn from(t
: Type
) -> c_int
{
230 /// Protocol specification used for creating sockets via `Socket::new`.
232 /// This is a newtype wrapper around an integer which provides a nicer API in
233 /// addition to an injection point for documentation.
235 /// This type is freely interconvertible with C's `int` type, however, if a raw
236 /// value needs to be provided.
237 #[derive(Copy, Clone, Eq, PartialEq)]
238 pub struct Protocol(c_int
);
241 /// Protocol corresponding to `ICMPv4`.
242 pub const ICMPV4
: Protocol
= Protocol(sys
::IPPROTO_ICMP
);
244 /// Protocol corresponding to `ICMPv6`.
245 pub const ICMPV6
: Protocol
= Protocol(sys
::IPPROTO_ICMPV6
);
247 /// Protocol corresponding to `TCP`.
248 pub const TCP
: Protocol
= Protocol(sys
::IPPROTO_TCP
);
250 /// Protocol corresponding to `UDP`.
251 pub const UDP
: Protocol
= Protocol(sys
::IPPROTO_UDP
);
254 impl From
<c_int
> for Protocol
{
255 fn from(p
: c_int
) -> Protocol
{
260 impl From
<Protocol
> for c_int
{
261 fn from(p
: Protocol
) -> c_int
{
266 /// Flags for incoming messages.
268 /// Flags provide additional information about incoming messages.
269 #[cfg(not(target_os = "redox"))]
270 #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
271 #[derive(Copy, Clone, Eq, PartialEq)]
272 pub struct RecvFlags(c_int
);
274 #[cfg(not(target_os = "redox"))]
276 /// Check if the message contains a truncated datagram.
278 /// This flag is only used for datagram-based sockets,
279 /// not for stream sockets.
281 /// On Unix this corresponds to the `MSG_TRUNC` flag.
282 /// On Windows this corresponds to the `WSAEMSGSIZE` error code.
283 pub const fn is_truncated(self) -> bool
{
284 self.0 & sys
::MSG_TRUNC
!= 0
288 /// A version of [`IoSliceMut`] that allows the buffer to be uninitialised.
290 /// [`IoSliceMut`]: std::io::IoSliceMut
292 pub struct MaybeUninitSlice
<'a
>(sys
::MaybeUninitSlice
<'a
>);
294 impl<'a
> fmt
::Debug
for MaybeUninitSlice
<'a
> {
295 fn fmt(&self, fmt
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
296 fmt
::Debug
::fmt(self.0.as_slice(), fmt
)
300 impl<'a
> MaybeUninitSlice
<'a
> {
301 /// Creates a new `MaybeUninitSlice` wrapping a byte slice.
305 /// Panics on Windows if the slice is larger than 4GB.
306 pub fn new(buf
: &'a
mut [MaybeUninit
<u8>]) -> MaybeUninitSlice
<'a
> {
307 MaybeUninitSlice(sys
::MaybeUninitSlice
::new(buf
))
311 impl<'a
> Deref
for MaybeUninitSlice
<'a
> {
312 type Target
= [MaybeUninit
<u8>];
314 fn deref(&self) -> &[MaybeUninit
<u8>] {
319 impl<'a
> DerefMut
for MaybeUninitSlice
<'a
> {
320 fn deref_mut(&mut self) -> &mut [MaybeUninit
<u8>] {
321 self.0.as_mut_slice()
325 /// Configures a socket's TCP keepalive parameters.
327 /// See [`Socket::set_tcp_keepalive`].
328 #[derive(Debug, Clone)]
329 pub struct TcpKeepalive
{
330 #[cfg_attr(target_os = "openbsd", allow(dead_code))]
331 time
: Option
<Duration
>,
332 #[cfg(not(any(target_os = "openbsd", target_os = "redox", target_os = "solaris")))]
333 interval
: Option
<Duration
>,
335 target_os
= "openbsd",
337 target_os
= "solaris",
338 target_os
= "windows"
340 retries
: Option
<u32>,
344 /// Returns a new, empty set of TCP keepalive parameters.
345 pub const fn new() -> TcpKeepalive
{
348 #[cfg(not(any(target_os = "openbsd", target_os = "redox", target_os = "solaris")))]
351 target_os
= "openbsd",
353 target_os
= "solaris",
354 target_os
= "windows"
360 /// Set the amount of time after which TCP keepalive probes will be sent on
361 /// idle connections.
363 /// This will set `TCP_KEEPALIVE` on macOS and iOS, and
364 /// `TCP_KEEPIDLE` on all other Unix operating systems, except
365 /// OpenBSD and Haiku which don't support any way to set this
366 /// option. On Windows, this sets the value of the `tcp_keepalive`
367 /// struct's `keepalivetime` field.
369 /// Some platforms specify this value in seconds, so sub-second
370 /// specifications may be omitted.
371 pub const fn with_time(self, time
: Duration
) -> Self {
378 /// Set the value of the `TCP_KEEPINTVL` option. On Windows, this sets the
379 /// value of the `tcp_keepalive` struct's `keepaliveinterval` field.
381 /// Sets the time interval between TCP keepalive probes.
383 /// Some platforms specify this value in seconds, so sub-second
384 /// specifications may be omitted.
388 target_os
= "android",
389 target_os
= "dragonfly",
390 target_os
= "freebsd",
391 target_os
= "fuchsia",
392 target_os
= "illumos",
394 target_os
= "netbsd",
395 target_vendor
= "apple",
404 target_os
= "android",
405 target_os
= "dragonfly",
406 target_os
= "freebsd",
407 target_os
= "fuchsia",
408 target_os
= "illumos",
410 target_os
= "netbsd",
411 target_vendor
= "apple",
416 pub const fn with_interval(self, interval
: Duration
) -> Self {
418 interval
: Some(interval
),
423 /// Set the value of the `TCP_KEEPCNT` option.
425 /// Set the maximum number of TCP keepalive probes that will be sent before
426 /// dropping a connection, if TCP keepalive is enabled on this socket.
431 target_os
= "android",
432 target_os
= "dragonfly",
433 target_os
= "freebsd",
434 target_os
= "fuchsia",
435 target_os
= "illumos",
437 target_os
= "netbsd",
438 target_vendor
= "apple",
446 target_os
= "android",
447 target_os
= "dragonfly",
448 target_os
= "freebsd",
449 target_os
= "fuchsia",
450 target_os
= "illumos",
452 target_os
= "netbsd",
453 target_vendor
= "apple",
457 pub const fn with_retries(self, retries
: u32) -> Self {
459 retries
: Some(retries
),