RPM build fix (reverted CI changes which will need to be un-reverted or made conditional) and vendor Rust dependencies to make builds much faster in any CI system.

This commit is contained in:
Adam Ierymenko
2022-06-08 07:32:16 -04:00
parent 373ca30269
commit d5ca4e5f52
12611 changed files with 2898014 additions and 284 deletions

View File

@@ -0,0 +1 @@
{"files":{"Cargo.toml":"a8878d08e3b1b2f217ca564f02ffb908d07ddc8584edf29ac33738693be7e1a9","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"b870d442505bc8047b641815c8283f29fc213dcfd1331894802e6ae55cc09f1b","src/lib.rs":"b4409a10c9b4c1e16f20cc4b6cd087ad5fa0ec8fc701653bc93fedeb158583d2","src/sockaddr.rs":"bed988fb306072fdb67718f3a215180d18f78f32321fecf64797f4c1d6bc7d84","src/socket.rs":"2beb154dfbadeb79408d987d074acd4a8daaf28e2dcadac0357e2d4fd4be7526","src/sockref.rs":"02de263cce039aaddaee5d6c2bb3940bdfae5697a3fc9df47d226fb3cac03cd9","src/sys/unix.rs":"b784e64a55ce666d8b3c8e30949b6d4965d6961c1bb964017f7fc54c109b7ad7","src/sys/windows.rs":"85840bf5c99fc984c9126cebfb065caefa7a8158b1c6bbc1d876f347187eefdb"},"package":"66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"}

39
zeroidc/vendor/socket2/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,39 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "socket2"
version = "0.4.4"
authors = ["Alex Crichton <alex@alexcrichton.com>", "Thomas de Zeeuw <thomasdezeeuw@gmail.com>"]
include = ["Cargo.toml", "LICENSE-APACHE", "LICENSE-MIT", "README.md", "src/**/*.rs"]
description = "Utilities for handling networking sockets with a maximal amount of configuration\npossible intended.\n"
homepage = "https://github.com/rust-lang/socket2"
documentation = "https://docs.rs/socket2"
readme = "README.md"
keywords = ["io", "socket", "network"]
categories = ["api-bindings", "network-programming"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-lang/socket2"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.playground]
features = ["all"]
[features]
all = []
[target."cfg(unix)".dependencies.libc]
version = "0.2.114"
[target."cfg(windows)".dependencies.winapi]
version = "0.3.9"
features = ["handleapi", "ws2ipdef", "ws2tcpip"]

201
zeroidc/vendor/socket2/LICENSE-APACHE vendored Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

25
zeroidc/vendor/socket2/LICENSE-MIT vendored Normal file
View File

@@ -0,0 +1,25 @@
Copyright (c) 2014 Alex Crichton
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

84
zeroidc/vendor/socket2/README.md vendored Normal file
View File

@@ -0,0 +1,84 @@
# Socket2
Socket2 is a crate that provides utilities for creating and using sockets.
The goal of this crate is to create and use a socket using advanced
configuration options (those that are not available in the types in the standard
library) without using any unsafe code.
This crate provides as direct as possible access to the system's functionality
for sockets, this means little effort to provide cross-platform utilities. It is
up to the user to know how to use sockets when using this crate. *If you don't
know how to create a socket using libc/system calls then this crate is not for
you*. Most, if not all, functions directly relate to the equivalent system call
with no error handling applied, so no handling errors such as `EINTR`. As a
result using this crate can be a little wordy, but it should give you maximal
flexibility over configuration of sockets.
See the [API documentation] for more.
[API documentation]: https://docs.rs/socket2
# Two branches
Currently Socket2 supports two versions: v0.4 and v0.3. Version 0.4 is developed
in the master branch, version 0.3 in the [v0.3.x branch].
[v0.3.x branch]: https://github.com/rust-lang/socket2/tree/v0.3.x
# OS support
Socket2 attempts to support the same OS/architectures as Rust does, see
https://doc.rust-lang.org/nightly/rustc/platform-support.html. However this is
not always possible, below is current list of support OSs.
*If your favorite OS is not on the list consider contributing it! See [issue
#78].*
[issue #78]: https://github.com/rust-lang/socket2/issues/78
### Tier 1
These OSs are tested with each commit in the CI and must always pass the tests.
All functions/types/etc., excluding ones behind the `all` feature, must work on
these OSs.
* Linux
* macOS
* Windows
### Tier 2
These OSs are currently build in the CI, but not tested. Not all
functions/types/etc. may work on these OSs, even ones **not** behind the `all`
feature flag.
* Android
* FreeBSD
* Fuchsia
* iOS
* illumos
* NetBSD
* Redox
* Solaris
# Minimum Supported Rust Version (MSRV)
Socket2 uses 1.46.0 as MSRV.
# License
This project is licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this project by you, as defined in the Apache-2.0 license,
shall be dual licensed as above, without any additional terms or conditions.

442
zeroidc/vendor/socket2/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,442 @@
// Copyright 2015 The Rust Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Utilities for creating and using sockets.
//!
//! The goal of this crate is to create and use a socket using advanced
//! configuration options (those that are not available in the types in the
//! standard library) without using any unsafe code.
//!
//! This crate provides as direct as possible access to the system's
//! functionality for sockets, this means little effort to provide
//! cross-platform utilities. It is up to the user to know how to use sockets
//! when using this crate. *If you don't know how to create a socket using
//! libc/system calls then this crate is not for you*. Most, if not all,
//! functions directly relate to the equivalent system call with no error
//! handling applied, so no handling errors such as [`EINTR`]. As a result using
//! this crate can be a little wordy, but it should give you maximal flexibility
//! over configuration of sockets.
//!
//! [`EINTR`]: std::io::ErrorKind::Interrupted
//!
//! # Examples
//!
//! ```no_run
//! # fn main() -> std::io::Result<()> {
//! use std::net::{SocketAddr, TcpListener};
//! use socket2::{Socket, Domain, Type};
//!
//! // Create a TCP listener bound to two addresses.
//! let socket = Socket::new(Domain::IPV6, Type::STREAM, None)?;
//!
//! socket.set_only_v6(false)?;
//! let address: SocketAddr = "[::1]:12345".parse().unwrap();
//! socket.bind(&address.into())?;
//! socket.listen(128)?;
//!
//! let listener: TcpListener = socket.into();
//! // ...
//! # drop(listener);
//! # Ok(()) }
//! ```
//!
//! ## Features
//!
//! This crate has a single feature `all`, which enables all functions even ones
//! that are not available on all OSs.
#![doc(html_root_url = "https://docs.rs/socket2/0.3")]
#![deny(missing_docs, missing_debug_implementations, rust_2018_idioms)]
// Show required OS/features on docs.rs.
#![cfg_attr(docsrs, feature(doc_cfg))]
// Disallow warnings when running tests.
#![cfg_attr(test, deny(warnings))]
// Disallow warnings in examples.
#![doc(test(attr(deny(warnings))))]
use std::fmt;
use std::mem::MaybeUninit;
use std::net::SocketAddr;
use std::ops::{Deref, DerefMut};
use std::time::Duration;
/// Macro to implement `fmt::Debug` for a type, printing the constant names
/// rather than a number.
///
/// Note this is used in the `sys` module and thus must be defined before
/// defining the modules.
macro_rules! impl_debug {
(
// Type name for which to implement `fmt::Debug`.
$type: path,
$(
$(#[$target: meta])*
// The flag(s) to check.
// Need to specific the libc crate because Windows doesn't use
// `libc` but `winapi`.
$libc: ident :: $flag: ident
),+ $(,)*
) => {
impl std::fmt::Debug for $type {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let string = match self.0 {
$(
$(#[$target])*
$libc :: $flag => stringify!($flag),
)+
n => return write!(f, "{}", n),
};
f.write_str(string)
}
}
};
}
/// Macro to convert from one network type to another.
macro_rules! from {
($from: ty, $for: ty) => {
impl From<$from> for $for {
fn from(socket: $from) -> $for {
#[cfg(unix)]
unsafe {
<$for>::from_raw_fd(socket.into_raw_fd())
}
#[cfg(windows)]
unsafe {
<$for>::from_raw_socket(socket.into_raw_socket())
}
}
}
};
}
mod sockaddr;
mod socket;
mod sockref;
#[cfg_attr(unix, path = "sys/unix.rs")]
#[cfg_attr(windows, path = "sys/windows.rs")]
mod sys;
#[cfg(not(any(windows, unix)))]
compile_error!("Socket2 doesn't support the compile target");
use sys::c_int;
pub use sockaddr::SockAddr;
pub use socket::Socket;
pub use sockref::SockRef;
#[cfg(not(any(
target_os = "haiku",
target_os = "illumos",
target_os = "netbsd",
target_os = "redox",
target_os = "solaris",
)))]
pub use socket::InterfaceIndexOrAddress;
/// Specification of the communication domain for a socket.
///
/// This is a newtype wrapper around an integer which provides a nicer API in
/// addition to an injection point for documentation. Convenience constants such
/// as [`Domain::IPV4`], [`Domain::IPV6`], etc, are provided to avoid reaching
/// into libc for various constants.
///
/// This type is freely interconvertible with C's `int` type, however, if a raw
/// value needs to be provided.
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Domain(c_int);
impl Domain {
/// Domain for IPv4 communication, corresponding to `AF_INET`.
pub const IPV4: Domain = Domain(sys::AF_INET);
/// Domain for IPv6 communication, corresponding to `AF_INET6`.
pub const IPV6: Domain = Domain(sys::AF_INET6);
/// Returns the correct domain for `address`.
pub const fn for_address(address: SocketAddr) -> Domain {
match address {
SocketAddr::V4(_) => Domain::IPV4,
SocketAddr::V6(_) => Domain::IPV6,
}
}
}
impl From<c_int> for Domain {
fn from(d: c_int) -> Domain {
Domain(d)
}
}
impl From<Domain> for c_int {
fn from(d: Domain) -> c_int {
d.0
}
}
/// Specification of communication semantics on a socket.
///
/// This is a newtype wrapper around an integer which provides a nicer API in
/// addition to an injection point for documentation. Convenience constants such
/// as [`Type::STREAM`], [`Type::DGRAM`], etc, are provided to avoid reaching
/// into libc for various constants.
///
/// This type is freely interconvertible with C's `int` type, however, if a raw
/// value needs to be provided.
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Type(c_int);
impl Type {
/// Type corresponding to `SOCK_STREAM`.
///
/// Used for protocols such as TCP.
pub const STREAM: Type = Type(sys::SOCK_STREAM);
/// Type corresponding to `SOCK_DGRAM`.
///
/// Used for protocols such as UDP.
pub const DGRAM: Type = Type(sys::SOCK_DGRAM);
/// Type corresponding to `SOCK_SEQPACKET`.
#[cfg(feature = "all")]
#[cfg_attr(docsrs, doc(cfg(feature = "all")))]
pub const SEQPACKET: Type = Type(sys::SOCK_SEQPACKET);
/// Type corresponding to `SOCK_RAW`.
#[cfg(all(feature = "all", not(target_os = "redox")))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "all", not(target_os = "redox")))))]
pub const RAW: Type = Type(sys::SOCK_RAW);
}
impl From<c_int> for Type {
fn from(t: c_int) -> Type {
Type(t)
}
}
impl From<Type> for c_int {
fn from(t: Type) -> c_int {
t.0
}
}
/// Protocol specification used for creating sockets via `Socket::new`.
///
/// This is a newtype wrapper around an integer which provides a nicer API in
/// addition to an injection point for documentation.
///
/// This type is freely interconvertible with C's `int` type, however, if a raw
/// value needs to be provided.
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Protocol(c_int);
impl Protocol {
/// Protocol corresponding to `ICMPv4`.
pub const ICMPV4: Protocol = Protocol(sys::IPPROTO_ICMP);
/// Protocol corresponding to `ICMPv6`.
pub const ICMPV6: Protocol = Protocol(sys::IPPROTO_ICMPV6);
/// Protocol corresponding to `TCP`.
pub const TCP: Protocol = Protocol(sys::IPPROTO_TCP);
/// Protocol corresponding to `UDP`.
pub const UDP: Protocol = Protocol(sys::IPPROTO_UDP);
}
impl From<c_int> for Protocol {
fn from(p: c_int) -> Protocol {
Protocol(p)
}
}
impl From<Protocol> for c_int {
fn from(p: Protocol) -> c_int {
p.0
}
}
/// Flags for incoming messages.
///
/// Flags provide additional information about incoming messages.
#[cfg(not(target_os = "redox"))]
#[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct RecvFlags(c_int);
#[cfg(not(target_os = "redox"))]
impl RecvFlags {
/// Check if the message contains a truncated datagram.
///
/// This flag is only used for datagram-based sockets,
/// not for stream sockets.
///
/// On Unix this corresponds to the `MSG_TRUNC` flag.
/// On Windows this corresponds to the `WSAEMSGSIZE` error code.
pub const fn is_truncated(self) -> bool {
self.0 & sys::MSG_TRUNC != 0
}
}
/// A version of [`IoSliceMut`] that allows the buffer to be uninitialised.
///
/// [`IoSliceMut`]: std::io::IoSliceMut
#[repr(transparent)]
pub struct MaybeUninitSlice<'a>(sys::MaybeUninitSlice<'a>);
impl<'a> fmt::Debug for MaybeUninitSlice<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.0.as_slice(), fmt)
}
}
impl<'a> MaybeUninitSlice<'a> {
/// Creates a new `MaybeUninitSlice` wrapping a byte slice.
///
/// # Panics
///
/// Panics on Windows if the slice is larger than 4GB.
pub fn new(buf: &'a mut [MaybeUninit<u8>]) -> MaybeUninitSlice<'a> {
MaybeUninitSlice(sys::MaybeUninitSlice::new(buf))
}
}
impl<'a> Deref for MaybeUninitSlice<'a> {
type Target = [MaybeUninit<u8>];
fn deref(&self) -> &[MaybeUninit<u8>] {
self.0.as_slice()
}
}
impl<'a> DerefMut for MaybeUninitSlice<'a> {
fn deref_mut(&mut self) -> &mut [MaybeUninit<u8>] {
self.0.as_mut_slice()
}
}
/// Configures a socket's TCP keepalive parameters.
///
/// See [`Socket::set_tcp_keepalive`].
#[derive(Debug, Clone)]
pub struct TcpKeepalive {
time: Option<Duration>,
#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
interval: Option<Duration>,
#[cfg(not(any(target_os = "redox", target_os = "solaris", target_os = "windows")))]
retries: Option<u32>,
}
impl TcpKeepalive {
/// Returns a new, empty set of TCP keepalive parameters.
pub const fn new() -> TcpKeepalive {
TcpKeepalive {
time: None,
#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
interval: None,
#[cfg(not(any(target_os = "redox", target_os = "solaris", target_os = "windows")))]
retries: None,
}
}
/// Set the amount of time after which TCP keepalive probes will be sent on
/// idle connections.
///
/// This will set `TCP_KEEPALIVE` on macOS and iOS, and
/// `TCP_KEEPIDLE` on all other Unix operating systems, except
/// OpenBSD and Haiku which don't support any way to set this
/// option. On Windows, this sets the value of the `tcp_keepalive`
/// struct's `keepalivetime` field.
///
/// Some platforms specify this value in seconds, so sub-second
/// specifications may be omitted.
pub const fn with_time(self, time: Duration) -> Self {
Self {
time: Some(time),
..self
}
}
/// Set the value of the `TCP_KEEPINTVL` option. On Windows, this sets the
/// value of the `tcp_keepalive` struct's `keepaliveinterval` field.
///
/// Sets the time interval between TCP keepalive probes.
///
/// Some platforms specify this value in seconds, so sub-second
/// specifications may be omitted.
#[cfg(all(
feature = "all",
any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "linux",
target_os = "netbsd",
target_vendor = "apple",
windows,
)
))]
#[cfg_attr(
docsrs,
doc(cfg(all(
feature = "all",
any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "linux",
target_os = "netbsd",
target_vendor = "apple",
windows,
)
)))
)]
pub const fn with_interval(self, interval: Duration) -> Self {
Self {
interval: Some(interval),
..self
}
}
/// Set the value of the `TCP_KEEPCNT` option.
///
/// Set the maximum number of TCP keepalive probes that will be sent before
/// dropping a connection, if TCP keepalive is enabled on this socket.
#[cfg(all(
feature = "all",
any(
doc,
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "linux",
target_os = "netbsd",
target_vendor = "apple",
)
))]
#[cfg_attr(
docsrs,
doc(cfg(all(
feature = "all",
any(
target_os = "freebsd",
target_os = "fuchsia",
target_os = "linux",
target_os = "netbsd",
target_vendor = "apple",
)
)))
)]
pub const fn with_retries(self, retries: u32) -> Self {
Self {
retries: Some(retries),
..self
}
}
}

348
zeroidc/vendor/socket2/src/sockaddr.rs vendored Normal file
View File

@@ -0,0 +1,348 @@
use std::mem::{self, size_of, MaybeUninit};
use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
use std::{fmt, io};
use crate::sys::{
sa_family_t, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_storage, socklen_t, AF_INET,
AF_INET6,
};
#[cfg(windows)]
use winapi::shared::ws2ipdef::SOCKADDR_IN6_LH_u;
/// The address of a socket.
///
/// `SockAddr`s may be constructed directly to and from the standard library
/// [`SocketAddr`], [`SocketAddrV4`], and [`SocketAddrV6`] types.
pub struct SockAddr {
storage: sockaddr_storage,
len: socklen_t,
}
#[allow(clippy::len_without_is_empty)]
impl SockAddr {
/// Create a `SockAddr` from the underlying storage and its length.
///
/// # Safety
///
/// Caller must ensure that the address family and length match the type of
/// storage address. For example if `storage.ss_family` is set to `AF_INET`
/// the `storage` must be initialised as `sockaddr_in`, setting the content
/// and length appropriately.
///
/// # Examples
///
/// ```
/// # fn main() -> std::io::Result<()> {
/// # #[cfg(unix)] {
/// use std::io;
/// use std::mem;
/// use std::os::unix::io::AsRawFd;
///
/// use socket2::{SockAddr, Socket, Domain, Type};
///
/// let socket = Socket::new(Domain::IPV4, Type::STREAM, None)?;
///
/// // Initialise a `SocketAddr` byte calling `getsockname(2)`.
/// let mut addr_storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
/// let mut len = mem::size_of_val(&addr_storage) as libc::socklen_t;
///
/// // The `getsockname(2)` system call will intiliase `storage` for
/// // us, setting `len` to the correct length.
/// let res = unsafe {
/// libc::getsockname(
/// socket.as_raw_fd(),
/// (&mut addr_storage as *mut libc::sockaddr_storage).cast(),
/// &mut len,
/// )
/// };
/// if res == -1 {
/// return Err(io::Error::last_os_error());
/// }
///
/// let address = unsafe { SockAddr::new(addr_storage, len) };
/// # drop(address);
/// # }
/// # Ok(())
/// # }
/// ```
pub const unsafe fn new(storage: sockaddr_storage, len: socklen_t) -> SockAddr {
SockAddr { storage, len }
}
/// Initialise a `SockAddr` by calling the function `init`.
///
/// The type of the address storage and length passed to the function `init`
/// is OS/architecture specific.
///
/// The address is zeroed before `init` is called and is thus valid to
/// dereference and read from. The length initialised to the maximum length
/// of the storage.
///
/// # Safety
///
/// Caller must ensure that the address family and length match the type of
/// storage address. For example if `storage.ss_family` is set to `AF_INET`
/// the `storage` must be initialised as `sockaddr_in`, setting the content
/// and length appropriately.
///
/// # Examples
///
/// ```
/// # fn main() -> std::io::Result<()> {
/// # #[cfg(unix)] {
/// use std::io;
/// use std::os::unix::io::AsRawFd;
///
/// use socket2::{SockAddr, Socket, Domain, Type};
///
/// let socket = Socket::new(Domain::IPV4, Type::STREAM, None)?;
///
/// // Initialise a `SocketAddr` byte calling `getsockname(2)`.
/// let (_, address) = unsafe {
/// SockAddr::init(|addr_storage, len| {
/// // The `getsockname(2)` system call will intiliase `storage` for
/// // us, setting `len` to the correct length.
/// if libc::getsockname(socket.as_raw_fd(), addr_storage.cast(), len) == -1 {
/// Err(io::Error::last_os_error())
/// } else {
/// Ok(())
/// }
/// })
/// }?;
/// # drop(address);
/// # }
/// # Ok(())
/// # }
/// ```
pub unsafe fn init<F, T>(init: F) -> io::Result<(T, SockAddr)>
where
F: FnOnce(*mut sockaddr_storage, *mut socklen_t) -> io::Result<T>,
{
const STORAGE_SIZE: socklen_t = size_of::<sockaddr_storage>() as socklen_t;
// NOTE: `SockAddr::unix` depends on the storage being zeroed before
// calling `init`.
// NOTE: calling `recvfrom` with an empty buffer also depends on the
// storage being zeroed before calling `init` as the OS might not
// initialise it.
let mut storage = MaybeUninit::<sockaddr_storage>::zeroed();
let mut len = STORAGE_SIZE;
init(storage.as_mut_ptr(), &mut len).map(|res| {
debug_assert!(len <= STORAGE_SIZE, "overflown address storage");
let addr = SockAddr {
// Safety: zeroed-out `sockaddr_storage` is valid, caller must
// ensure at least `len` bytes are valid.
storage: storage.assume_init(),
len,
};
(res, addr)
})
}
/// Returns this address's family.
pub const fn family(&self) -> sa_family_t {
self.storage.ss_family
}
/// Returns the size of this address in bytes.
pub const fn len(&self) -> socklen_t {
self.len
}
/// Returns a raw pointer to the address.
pub const fn as_ptr(&self) -> *const sockaddr {
&self.storage as *const _ as *const _
}
/// Returns a raw pointer to the address storage.
#[cfg(all(unix, not(target_os = "redox")))]
pub(crate) const fn as_storage_ptr(&self) -> *const sockaddr_storage {
&self.storage
}
/// Returns this address as a `SocketAddr` if it is in the `AF_INET` (IPv4)
/// or `AF_INET6` (IPv6) family, otherwise returns `None`.
pub fn as_socket(&self) -> Option<SocketAddr> {
if self.storage.ss_family == AF_INET as sa_family_t {
// Safety: if the ss_family field is AF_INET then storage must be a sockaddr_in.
let addr = unsafe { &*(&self.storage as *const _ as *const sockaddr_in) };
let ip = crate::sys::from_in_addr(addr.sin_addr);
let port = u16::from_be(addr.sin_port);
Some(SocketAddr::V4(SocketAddrV4::new(ip, port)))
} else if self.storage.ss_family == AF_INET6 as sa_family_t {
// Safety: if the ss_family field is AF_INET6 then storage must be a sockaddr_in6.
let addr = unsafe { &*(&self.storage as *const _ as *const sockaddr_in6) };
let ip = crate::sys::from_in6_addr(addr.sin6_addr);
let port = u16::from_be(addr.sin6_port);
Some(SocketAddr::V6(SocketAddrV6::new(
ip,
port,
addr.sin6_flowinfo,
#[cfg(unix)]
addr.sin6_scope_id,
#[cfg(windows)]
unsafe {
*addr.u.sin6_scope_id()
},
)))
} else {
None
}
}
/// Returns this address as a [`SocketAddrV4`] if it is in the `AF_INET`
/// family.
pub fn as_socket_ipv4(&self) -> Option<SocketAddrV4> {
match self.as_socket() {
Some(SocketAddr::V4(addr)) => Some(addr),
_ => None,
}
}
/// Returns this address as a [`SocketAddrV6`] if it is in the `AF_INET6`
/// family.
pub fn as_socket_ipv6(&self) -> Option<SocketAddrV6> {
match self.as_socket() {
Some(SocketAddr::V6(addr)) => Some(addr),
_ => None,
}
}
}
impl From<SocketAddr> for SockAddr {
fn from(addr: SocketAddr) -> SockAddr {
match addr {
SocketAddr::V4(addr) => addr.into(),
SocketAddr::V6(addr) => addr.into(),
}
}
}
impl From<SocketAddrV4> for SockAddr {
fn from(addr: SocketAddrV4) -> SockAddr {
let sockaddr_in = sockaddr_in {
sin_family: AF_INET as sa_family_t,
sin_port: addr.port().to_be(),
sin_addr: crate::sys::to_in_addr(addr.ip()),
sin_zero: Default::default(),
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "haiku",
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"
))]
sin_len: 0,
};
let mut storage = MaybeUninit::<sockaddr_storage>::zeroed();
// Safety: A `sockaddr_in` is memory compatible with a `sockaddr_storage`
unsafe { (storage.as_mut_ptr() as *mut sockaddr_in).write(sockaddr_in) };
SockAddr {
storage: unsafe { storage.assume_init() },
len: mem::size_of::<sockaddr_in>() as socklen_t,
}
}
}
impl From<SocketAddrV6> for SockAddr {
fn from(addr: SocketAddrV6) -> SockAddr {
#[cfg(windows)]
let u = unsafe {
let mut u = mem::zeroed::<SOCKADDR_IN6_LH_u>();
*u.sin6_scope_id_mut() = addr.scope_id();
u
};
let sockaddr_in6 = sockaddr_in6 {
sin6_family: AF_INET6 as sa_family_t,
sin6_port: addr.port().to_be(),
sin6_addr: crate::sys::to_in6_addr(addr.ip()),
sin6_flowinfo: addr.flowinfo(),
#[cfg(unix)]
sin6_scope_id: addr.scope_id(),
#[cfg(windows)]
u,
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "haiku",
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"
))]
sin6_len: 0,
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
__sin6_src_id: 0,
};
let mut storage = MaybeUninit::<sockaddr_storage>::zeroed();
// Safety: A `sockaddr_in6` is memory compatible with a `sockaddr_storage`
unsafe { (storage.as_mut_ptr() as *mut sockaddr_in6).write(sockaddr_in6) };
SockAddr {
storage: unsafe { storage.assume_init() },
len: mem::size_of::<sockaddr_in6>() as socklen_t,
}
}
}
impl fmt::Debug for SockAddr {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut f = fmt.debug_struct("SockAddr");
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "haiku",
target_os = "hermit",
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "vxworks",
))]
f.field("ss_len", &self.storage.ss_len);
f.field("ss_family", &self.storage.ss_family)
.field("len", &self.len)
.finish()
}
}
#[test]
fn ipv4() {
use std::net::Ipv4Addr;
let std = SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 9876);
let addr = SockAddr::from(std);
assert_eq!(addr.family(), AF_INET as sa_family_t);
assert_eq!(addr.len(), size_of::<sockaddr_in>() as socklen_t);
assert_eq!(addr.as_socket(), Some(SocketAddr::V4(std)));
assert_eq!(addr.as_socket_ipv4(), Some(std));
assert!(addr.as_socket_ipv6().is_none());
let addr = SockAddr::from(SocketAddr::from(std));
assert_eq!(addr.family(), AF_INET as sa_family_t);
assert_eq!(addr.len(), size_of::<sockaddr_in>() as socklen_t);
assert_eq!(addr.as_socket(), Some(SocketAddr::V4(std)));
assert_eq!(addr.as_socket_ipv4(), Some(std));
assert!(addr.as_socket_ipv6().is_none());
}
#[test]
fn ipv6() {
use std::net::Ipv6Addr;
let std = SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9876, 11, 12);
let addr = SockAddr::from(std);
assert_eq!(addr.family(), AF_INET6 as sa_family_t);
assert_eq!(addr.len(), size_of::<sockaddr_in6>() as socklen_t);
assert_eq!(addr.as_socket(), Some(SocketAddr::V6(std)));
assert!(addr.as_socket_ipv4().is_none());
assert_eq!(addr.as_socket_ipv6(), Some(std));
let addr = SockAddr::from(SocketAddr::from(std));
assert_eq!(addr.family(), AF_INET6 as sa_family_t);
assert_eq!(addr.len(), size_of::<sockaddr_in6>() as socklen_t);
assert_eq!(addr.as_socket(), Some(SocketAddr::V6(std)));
assert!(addr.as_socket_ipv4().is_none());
assert_eq!(addr.as_socket_ipv6(), Some(std));
}

1781
zeroidc/vendor/socket2/src/socket.rs vendored Normal file

File diff suppressed because it is too large Load Diff

147
zeroidc/vendor/socket2/src/sockref.rs vendored Normal file
View File

@@ -0,0 +1,147 @@
use std::fmt;
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ops::Deref;
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, FromRawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, FromRawSocket};
use crate::Socket;
/// A reference to a [`Socket`] that can be used to configure socket types other
/// than the `Socket` type itself.
///
/// This allows for example a [`TcpStream`], found in the standard library, to
/// be configured using all the additional methods found in the [`Socket`] API.
///
/// `SockRef` can be created from any socket type that implements [`AsRawFd`]
/// (Unix) or [`AsRawSocket`] (Windows) using the [`From`] implementation, but
/// the caller must ensure the file descriptor/socket is a valid.
///
/// [`TcpStream`]: std::net::TcpStream
// Don't use intra-doc links because they won't build on every platform.
/// [`AsRawFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.AsRawFd.html
/// [`AsRawSocket`]: https://doc.rust-lang.org/stable/std/os/windows/io/trait.AsRawSocket.html
///
/// # Examples
///
/// Below is an example of converting a [`TcpStream`] into a [`SockRef`].
///
/// ```
/// use std::net::{TcpStream, SocketAddr};
///
/// use socket2::SockRef;
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// // Create `TcpStream` from the standard library.
/// let address: SocketAddr = "127.0.0.1:1234".parse()?;
/// # let b1 = std::sync::Arc::new(std::sync::Barrier::new(2));
/// # let b2 = b1.clone();
/// # let handle = std::thread::spawn(move || {
/// # let listener = std::net::TcpListener::bind(address).unwrap();
/// # b2.wait();
/// # let (stream, _) = listener.accept().unwrap();
/// # std::thread::sleep(std::time::Duration::from_millis(10));
/// # drop(stream);
/// # });
/// # b1.wait();
/// let stream = TcpStream::connect(address)?;
///
/// // Create a `SockRef`erence to the stream.
/// let socket_ref = SockRef::from(&stream);
/// // Use `Socket::set_nodelay` on the stream.
/// socket_ref.set_nodelay(true)?;
/// drop(socket_ref);
///
/// assert_eq!(stream.nodelay()?, true);
/// # handle.join().unwrap();
/// # Ok(())
/// # }
/// ```
///
/// Below is an example of **incorrect usage** of `SockRef::from`, which is
/// currently possible (but not intended and will be fixed in future versions).
///
/// ```compile_fail
/// use socket2::SockRef;
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// /// THIS USAGE IS NOT VALID!
/// let socket_ref = SockRef::from(&123);
/// // The above line is overseen possibility when using `SockRef::from`, it
/// // uses the `RawFd` (on Unix), which is a type alias for `c_int`/`i32`,
/// // which implements `AsRawFd`. However it may be clear that this usage is
/// // invalid as it doesn't guarantee that `123` is a valid file descriptor.
///
/// // Using `Socket::set_nodelay` now will call it on a file descriptor we
/// // don't own! We don't even not if the file descriptor is valid or a socket.
/// socket_ref.set_nodelay(true)?;
/// drop(socket_ref);
/// # Ok(())
/// # }
/// # DO_NOT_COMPILE
/// ```
pub struct SockRef<'s> {
/// Because this is a reference we don't own the `Socket`, however `Socket`
/// closes itself when dropped, so we use `ManuallyDrop` to prevent it from
/// closing itself.
socket: ManuallyDrop<Socket>,
/// Because we don't own the socket we need to ensure the socket remains
/// open while we have a "reference" to it, the lifetime `'s` ensures this.
_lifetime: PhantomData<&'s Socket>,
}
impl<'s> Deref for SockRef<'s> {
type Target = Socket;
fn deref(&self) -> &Self::Target {
&self.socket
}
}
/// On Windows, a corresponding `From<&impl AsRawSocket>` implementation exists.
#[cfg(unix)]
#[cfg_attr(docsrs, doc(cfg(unix)))]
impl<'s, S> From<&'s S> for SockRef<'s>
where
S: AsRawFd,
{
/// The caller must ensure `S` is actually a socket.
fn from(socket: &'s S) -> Self {
let fd = socket.as_raw_fd();
assert!(fd >= 0);
SockRef {
socket: ManuallyDrop::new(unsafe { Socket::from_raw_fd(fd) }),
_lifetime: PhantomData,
}
}
}
/// On Unix, a corresponding `From<&impl AsRawFd>` implementation exists.
#[cfg(windows)]
#[cfg_attr(docsrs, doc(cfg(windows)))]
impl<'s, S> From<&'s S> for SockRef<'s>
where
S: AsRawSocket,
{
/// See the `From<&impl AsRawFd>` implementation.
fn from(socket: &'s S) -> Self {
let socket = socket.as_raw_socket();
assert!(socket != winapi::um::winsock2::INVALID_SOCKET as _);
SockRef {
socket: ManuallyDrop::new(unsafe { Socket::from_raw_socket(socket) }),
_lifetime: PhantomData,
}
}
}
impl fmt::Debug for SockRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SockRef")
.field("raw", &self.socket.as_raw())
.field("local_addr", &self.socket.local_addr().ok())
.field("peer_addr", &self.socket.peer_addr().ok())
.finish()
}
}

2053
zeroidc/vendor/socket2/src/sys/unix.rs vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,848 @@
// Copyright 2015 The Rust Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::cmp::min;
use std::io::{self, IoSlice};
use std::marker::PhantomData;
use std::mem::{self, size_of, MaybeUninit};
use std::net::{self, Ipv4Addr, Ipv6Addr, Shutdown};
use std::os::windows::prelude::*;
use std::sync::Once;
use std::time::{Duration, Instant};
use std::{ptr, slice};
use winapi::ctypes::c_long;
use winapi::shared::in6addr::*;
use winapi::shared::inaddr::*;
use winapi::shared::minwindef::DWORD;
use winapi::shared::minwindef::ULONG;
use winapi::shared::mstcpip::{tcp_keepalive, SIO_KEEPALIVE_VALS};
use winapi::shared::ntdef::HANDLE;
use winapi::shared::ws2def;
use winapi::shared::ws2def::WSABUF;
use winapi::um::handleapi::SetHandleInformation;
use winapi::um::processthreadsapi::GetCurrentProcessId;
use winapi::um::winbase::{self, INFINITE};
use winapi::um::winsock2::{
self as sock, u_long, POLLERR, POLLHUP, POLLRDNORM, POLLWRNORM, SD_BOTH, SD_RECEIVE, SD_SEND,
WSAPOLLFD,
};
use crate::{RecvFlags, SockAddr, TcpKeepalive, Type};
pub(crate) use winapi::ctypes::c_int;
/// Fake MSG_TRUNC flag for the [`RecvFlags`] struct.
///
/// The flag is enabled when a `WSARecv[From]` call returns `WSAEMSGSIZE`. The
/// value of the flag is defined by us.
pub(crate) const MSG_TRUNC: c_int = 0x01;
// Used in `Domain`.
pub(crate) use winapi::shared::ws2def::{AF_INET, AF_INET6};
// Used in `Type`.
pub(crate) use winapi::shared::ws2def::{SOCK_DGRAM, SOCK_STREAM};
#[cfg(feature = "all")]
pub(crate) use winapi::shared::ws2def::{SOCK_RAW, SOCK_SEQPACKET};
// Used in `Protocol`.
pub(crate) const IPPROTO_ICMP: c_int = winapi::shared::ws2def::IPPROTO_ICMP as c_int;
pub(crate) const IPPROTO_ICMPV6: c_int = winapi::shared::ws2def::IPPROTO_ICMPV6 as c_int;
pub(crate) const IPPROTO_TCP: c_int = winapi::shared::ws2def::IPPROTO_TCP as c_int;
pub(crate) const IPPROTO_UDP: c_int = winapi::shared::ws2def::IPPROTO_UDP as c_int;
// Used in `SockAddr`.
pub(crate) use winapi::shared::ws2def::{
ADDRESS_FAMILY as sa_family_t, SOCKADDR as sockaddr, SOCKADDR_IN as sockaddr_in,
SOCKADDR_STORAGE as sockaddr_storage,
};
pub(crate) use winapi::shared::ws2ipdef::SOCKADDR_IN6_LH as sockaddr_in6;
pub(crate) use winapi::um::ws2tcpip::socklen_t;
// Used in `Socket`.
pub(crate) use winapi::shared::ws2def::{
IPPROTO_IP, SOL_SOCKET, SO_BROADCAST, SO_ERROR, SO_KEEPALIVE, SO_LINGER, SO_OOBINLINE,
SO_RCVBUF, SO_RCVTIMEO, SO_REUSEADDR, SO_SNDBUF, SO_SNDTIMEO, SO_TYPE, TCP_NODELAY,
};
#[cfg(feature = "all")]
pub(crate) use winapi::shared::ws2ipdef::IP_HDRINCL;
pub(crate) use winapi::shared::ws2ipdef::{
IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MREQ as Ipv6Mreq, IPV6_MULTICAST_HOPS,
IPV6_MULTICAST_IF, IPV6_MULTICAST_LOOP, IPV6_UNICAST_HOPS, IPV6_V6ONLY, IP_ADD_MEMBERSHIP,
IP_DROP_MEMBERSHIP, IP_MREQ as IpMreq, IP_MULTICAST_IF, IP_MULTICAST_LOOP, IP_MULTICAST_TTL,
IP_TOS, IP_TTL,
};
pub(crate) use winapi::um::winsock2::{linger, MSG_OOB, MSG_PEEK};
pub(crate) const IPPROTO_IPV6: c_int = winapi::shared::ws2def::IPPROTO_IPV6 as c_int;
/// Type used in set/getsockopt to retrieve the `TCP_NODELAY` option.
///
/// NOTE: <https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt>
/// documents that options such as `TCP_NODELAY` and `SO_KEEPALIVE` expect a
/// `BOOL` (alias for `c_int`, 4 bytes), however in practice this turns out to
/// be false (or misleading) as a `BOOLEAN` (`c_uchar`, 1 byte) is returned by
/// `getsockopt`.
pub(crate) type Bool = winapi::shared::ntdef::BOOLEAN;
/// Maximum size of a buffer passed to system call like `recv` and `send`.
const MAX_BUF_LEN: usize = <c_int>::max_value() as usize;
/// Helper macro to execute a system call that returns an `io::Result`.
macro_rules! syscall {
($fn: ident ( $($arg: expr),* $(,)* ), $err_test: path, $err_value: expr) => {{
#[allow(unused_unsafe)]
let res = unsafe { sock::$fn($($arg, )*) };
if $err_test(&res, &$err_value) {
Err(io::Error::last_os_error())
} else {
Ok(res)
}
}};
}
impl_debug!(
crate::Domain,
ws2def::AF_INET,
ws2def::AF_INET6,
ws2def::AF_UNIX,
ws2def::AF_UNSPEC, // = 0.
);
/// Windows only API.
impl Type {
/// Our custom flag to set `WSA_FLAG_NO_HANDLE_INHERIT` on socket creation.
/// Trying to mimic `Type::cloexec` on windows.
const NO_INHERIT: c_int = 1 << ((size_of::<c_int>() * 8) - 1); // Last bit.
/// Set `WSA_FLAG_NO_HANDLE_INHERIT` on the socket.
#[cfg(feature = "all")]
#[cfg_attr(docsrs, doc(cfg(all(windows, feature = "all"))))]
pub const fn no_inherit(self) -> Type {
self._no_inherit()
}
pub(crate) const fn _no_inherit(self) -> Type {
Type(self.0 | Type::NO_INHERIT)
}
}
impl_debug!(
crate::Type,
ws2def::SOCK_STREAM,
ws2def::SOCK_DGRAM,
ws2def::SOCK_RAW,
ws2def::SOCK_RDM,
ws2def::SOCK_SEQPACKET,
);
impl_debug!(
crate::Protocol,
self::IPPROTO_ICMP,
self::IPPROTO_ICMPV6,
self::IPPROTO_TCP,
self::IPPROTO_UDP,
);
impl std::fmt::Debug for RecvFlags {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RecvFlags")
.field("is_truncated", &self.is_truncated())
.finish()
}
}
#[repr(transparent)]
pub struct MaybeUninitSlice<'a> {
vec: WSABUF,
_lifetime: PhantomData<&'a mut [MaybeUninit<u8>]>,
}
unsafe impl<'a> Send for MaybeUninitSlice<'a> {}
unsafe impl<'a> Sync for MaybeUninitSlice<'a> {}
impl<'a> MaybeUninitSlice<'a> {
pub fn new(buf: &'a mut [MaybeUninit<u8>]) -> MaybeUninitSlice<'a> {
assert!(buf.len() <= ULONG::MAX as usize);
MaybeUninitSlice {
vec: WSABUF {
len: buf.len() as ULONG,
buf: buf.as_mut_ptr().cast(),
},
_lifetime: PhantomData,
}
}
pub fn as_slice(&self) -> &[MaybeUninit<u8>] {
unsafe { slice::from_raw_parts(self.vec.buf.cast(), self.vec.len as usize) }
}
pub fn as_mut_slice(&mut self) -> &mut [MaybeUninit<u8>] {
unsafe { slice::from_raw_parts_mut(self.vec.buf.cast(), self.vec.len as usize) }
}
}
fn init() {
static INIT: Once = Once::new();
INIT.call_once(|| {
// Initialize winsock through the standard library by just creating a
// dummy socket. Whether this is successful or not we drop the result as
// libstd will be sure to have initialized winsock.
let _ = net::UdpSocket::bind("127.0.0.1:34254");
});
}
pub(crate) type Socket = sock::SOCKET;
pub(crate) unsafe fn socket_from_raw(socket: Socket) -> crate::socket::Inner {
crate::socket::Inner::from_raw_socket(socket as RawSocket)
}
pub(crate) fn socket_as_raw(socket: &crate::socket::Inner) -> Socket {
socket.as_raw_socket() as Socket
}
pub(crate) fn socket_into_raw(socket: crate::socket::Inner) -> Socket {
socket.into_raw_socket() as Socket
}
pub(crate) fn socket(family: c_int, mut ty: c_int, protocol: c_int) -> io::Result<Socket> {
init();
// Check if we set our custom flag.
let flags = if ty & Type::NO_INHERIT != 0 {
ty = ty & !Type::NO_INHERIT;
sock::WSA_FLAG_NO_HANDLE_INHERIT
} else {
0
};
syscall!(
WSASocketW(
family,
ty,
protocol,
ptr::null_mut(),
0,
sock::WSA_FLAG_OVERLAPPED | flags,
),
PartialEq::eq,
sock::INVALID_SOCKET
)
}
pub(crate) fn bind(socket: Socket, addr: &SockAddr) -> io::Result<()> {
syscall!(bind(socket, addr.as_ptr(), addr.len()), PartialEq::ne, 0).map(|_| ())
}
pub(crate) fn connect(socket: Socket, addr: &SockAddr) -> io::Result<()> {
syscall!(connect(socket, addr.as_ptr(), addr.len()), PartialEq::ne, 0).map(|_| ())
}
pub(crate) fn poll_connect(socket: &crate::Socket, timeout: Duration) -> io::Result<()> {
let start = Instant::now();
let mut fd_array = WSAPOLLFD {
fd: socket.as_raw(),
events: POLLRDNORM | POLLWRNORM,
revents: 0,
};
loop {
let elapsed = start.elapsed();
if elapsed >= timeout {
return Err(io::ErrorKind::TimedOut.into());
}
let timeout = (timeout - elapsed).as_millis();
let timeout = clamp(timeout, 1, c_int::max_value() as u128) as c_int;
match syscall!(
WSAPoll(&mut fd_array, 1, timeout),
PartialEq::eq,
sock::SOCKET_ERROR
) {
Ok(0) => return Err(io::ErrorKind::TimedOut.into()),
Ok(_) => {
// Error or hang up indicates an error (or failure to connect).
if (fd_array.revents & POLLERR) != 0 || (fd_array.revents & POLLHUP) != 0 {
match socket.take_error() {
Ok(Some(err)) => return Err(err),
Ok(None) => {
return Err(io::Error::new(
io::ErrorKind::Other,
"no error set after POLLHUP",
))
}
Err(err) => return Err(err),
}
}
return Ok(());
}
// Got interrupted, try again.
Err(ref err) if err.kind() == io::ErrorKind::Interrupted => continue,
Err(err) => return Err(err),
}
}
}
// TODO: use clamp from std lib, stable since 1.50.
fn clamp<T>(value: T, min: T, max: T) -> T
where
T: Ord,
{
if value <= min {
min
} else if value >= max {
max
} else {
value
}
}
pub(crate) fn listen(socket: Socket, backlog: c_int) -> io::Result<()> {
syscall!(listen(socket, backlog), PartialEq::ne, 0).map(|_| ())
}
pub(crate) fn accept(socket: Socket) -> io::Result<(Socket, SockAddr)> {
// Safety: `accept` initialises the `SockAddr` for us.
unsafe {
SockAddr::init(|storage, len| {
syscall!(
accept(socket, storage.cast(), len),
PartialEq::eq,
sock::INVALID_SOCKET
)
})
}
}
pub(crate) fn getsockname(socket: Socket) -> io::Result<SockAddr> {
// Safety: `getsockname` initialises the `SockAddr` for us.
unsafe {
SockAddr::init(|storage, len| {
syscall!(
getsockname(socket, storage.cast(), len),
PartialEq::eq,
sock::SOCKET_ERROR
)
})
}
.map(|(_, addr)| addr)
}
pub(crate) fn getpeername(socket: Socket) -> io::Result<SockAddr> {
// Safety: `getpeername` initialises the `SockAddr` for us.
unsafe {
SockAddr::init(|storage, len| {
syscall!(
getpeername(socket, storage.cast(), len),
PartialEq::eq,
sock::SOCKET_ERROR
)
})
}
.map(|(_, addr)| addr)
}
pub(crate) fn try_clone(socket: Socket) -> io::Result<Socket> {
let mut info: MaybeUninit<sock::WSAPROTOCOL_INFOW> = MaybeUninit::uninit();
syscall!(
WSADuplicateSocketW(socket, GetCurrentProcessId(), info.as_mut_ptr()),
PartialEq::eq,
sock::SOCKET_ERROR
)?;
// Safety: `WSADuplicateSocketW` intialised `info` for us.
let mut info = unsafe { info.assume_init() };
syscall!(
WSASocketW(
info.iAddressFamily,
info.iSocketType,
info.iProtocol,
&mut info,
0,
sock::WSA_FLAG_OVERLAPPED | sock::WSA_FLAG_NO_HANDLE_INHERIT,
),
PartialEq::eq,
sock::INVALID_SOCKET
)
}
pub(crate) fn set_nonblocking(socket: Socket, nonblocking: bool) -> io::Result<()> {
let mut nonblocking = nonblocking as u_long;
ioctlsocket(socket, sock::FIONBIO, &mut nonblocking)
}
pub(crate) fn shutdown(socket: Socket, how: Shutdown) -> io::Result<()> {
let how = match how {
Shutdown::Write => SD_SEND,
Shutdown::Read => SD_RECEIVE,
Shutdown::Both => SD_BOTH,
};
syscall!(shutdown(socket, how), PartialEq::eq, sock::SOCKET_ERROR).map(|_| ())
}
pub(crate) fn recv(socket: Socket, buf: &mut [MaybeUninit<u8>], flags: c_int) -> io::Result<usize> {
let res = syscall!(
recv(
socket,
buf.as_mut_ptr().cast(),
min(buf.len(), MAX_BUF_LEN) as c_int,
flags,
),
PartialEq::eq,
sock::SOCKET_ERROR
);
match res {
Ok(n) => Ok(n as usize),
Err(ref err) if err.raw_os_error() == Some(sock::WSAESHUTDOWN as i32) => Ok(0),
Err(err) => Err(err),
}
}
pub(crate) fn recv_vectored(
socket: Socket,
bufs: &mut [crate::MaybeUninitSlice<'_>],
flags: c_int,
) -> io::Result<(usize, RecvFlags)> {
let mut nread = 0;
let mut flags = flags as DWORD;
let res = syscall!(
WSARecv(
socket,
bufs.as_mut_ptr().cast(),
min(bufs.len(), DWORD::max_value() as usize) as DWORD,
&mut nread,
&mut flags,
ptr::null_mut(),
None,
),
PartialEq::eq,
sock::SOCKET_ERROR
);
match res {
Ok(_) => Ok((nread as usize, RecvFlags(0))),
Err(ref err) if err.raw_os_error() == Some(sock::WSAESHUTDOWN as i32) => {
Ok((0, RecvFlags(0)))
}
Err(ref err) if err.raw_os_error() == Some(sock::WSAEMSGSIZE as i32) => {
Ok((nread as usize, RecvFlags(MSG_TRUNC)))
}
Err(err) => Err(err),
}
}
pub(crate) fn recv_from(
socket: Socket,
buf: &mut [MaybeUninit<u8>],
flags: c_int,
) -> io::Result<(usize, SockAddr)> {
// Safety: `recvfrom` initialises the `SockAddr` for us.
unsafe {
SockAddr::init(|storage, addrlen| {
let res = syscall!(
recvfrom(
socket,
buf.as_mut_ptr().cast(),
min(buf.len(), MAX_BUF_LEN) as c_int,
flags,
storage.cast(),
addrlen,
),
PartialEq::eq,
sock::SOCKET_ERROR
);
match res {
Ok(n) => Ok(n as usize),
Err(ref err) if err.raw_os_error() == Some(sock::WSAESHUTDOWN as i32) => Ok(0),
Err(err) => Err(err),
}
})
}
}
pub(crate) fn recv_from_vectored(
socket: Socket,
bufs: &mut [crate::MaybeUninitSlice<'_>],
flags: c_int,
) -> io::Result<(usize, RecvFlags, SockAddr)> {
// Safety: `recvfrom` initialises the `SockAddr` for us.
unsafe {
SockAddr::init(|storage, addrlen| {
let mut nread = 0;
let mut flags = flags as DWORD;
let res = syscall!(
WSARecvFrom(
socket,
bufs.as_mut_ptr().cast(),
min(bufs.len(), DWORD::max_value() as usize) as DWORD,
&mut nread,
&mut flags,
storage.cast(),
addrlen,
ptr::null_mut(),
None,
),
PartialEq::eq,
sock::SOCKET_ERROR
);
match res {
Ok(_) => Ok((nread as usize, RecvFlags(0))),
Err(ref err) if err.raw_os_error() == Some(sock::WSAESHUTDOWN as i32) => {
Ok((nread as usize, RecvFlags(0)))
}
Err(ref err) if err.raw_os_error() == Some(sock::WSAEMSGSIZE as i32) => {
Ok((nread as usize, RecvFlags(MSG_TRUNC)))
}
Err(err) => Err(err),
}
})
}
.map(|((n, recv_flags), addr)| (n, recv_flags, addr))
}
pub(crate) fn send(socket: Socket, buf: &[u8], flags: c_int) -> io::Result<usize> {
syscall!(
send(
socket,
buf.as_ptr().cast(),
min(buf.len(), MAX_BUF_LEN) as c_int,
flags,
),
PartialEq::eq,
sock::SOCKET_ERROR
)
.map(|n| n as usize)
}
pub(crate) fn send_vectored(
socket: Socket,
bufs: &[IoSlice<'_>],
flags: c_int,
) -> io::Result<usize> {
let mut nsent = 0;
syscall!(
WSASend(
socket,
// FIXME: From the `WSASend` docs [1]:
// > For a Winsock application, once the WSASend function is called,
// > the system owns these buffers and the application may not
// > access them.
//
// So what we're doing is actually UB as `bufs` needs to be `&mut
// [IoSlice<'_>]`.
//
// Tracking issue: https://github.com/rust-lang/socket2-rs/issues/129.
//
// NOTE: `send_to_vectored` has the same problem.
//
// [1] https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasend
bufs.as_ptr() as *mut _,
min(bufs.len(), DWORD::max_value() as usize) as DWORD,
&mut nsent,
flags as DWORD,
std::ptr::null_mut(),
None,
),
PartialEq::eq,
sock::SOCKET_ERROR
)
.map(|_| nsent as usize)
}
pub(crate) fn send_to(
socket: Socket,
buf: &[u8],
addr: &SockAddr,
flags: c_int,
) -> io::Result<usize> {
syscall!(
sendto(
socket,
buf.as_ptr().cast(),
min(buf.len(), MAX_BUF_LEN) as c_int,
flags,
addr.as_ptr(),
addr.len(),
),
PartialEq::eq,
sock::SOCKET_ERROR
)
.map(|n| n as usize)
}
pub(crate) fn send_to_vectored(
socket: Socket,
bufs: &[IoSlice<'_>],
addr: &SockAddr,
flags: c_int,
) -> io::Result<usize> {
let mut nsent = 0;
syscall!(
WSASendTo(
socket,
// FIXME: Same problem as in `send_vectored`.
bufs.as_ptr() as *mut _,
bufs.len().min(DWORD::MAX as usize) as DWORD,
&mut nsent,
flags as DWORD,
addr.as_ptr(),
addr.len(),
ptr::null_mut(),
None,
),
PartialEq::eq,
sock::SOCKET_ERROR
)
.map(|_| nsent as usize)
}
/// Wrapper around `getsockopt` to deal with platform specific timeouts.
pub(crate) fn timeout_opt(fd: Socket, lvl: c_int, name: c_int) -> io::Result<Option<Duration>> {
unsafe { getsockopt(fd, lvl, name).map(from_ms) }
}
fn from_ms(duration: DWORD) -> Option<Duration> {
if duration == 0 {
None
} else {
let secs = duration / 1000;
let nsec = (duration % 1000) * 1000000;
Some(Duration::new(secs as u64, nsec as u32))
}
}
/// Wrapper around `setsockopt` to deal with platform specific timeouts.
pub(crate) fn set_timeout_opt(
fd: Socket,
level: c_int,
optname: c_int,
duration: Option<Duration>,
) -> io::Result<()> {
let duration = into_ms(duration);
unsafe { setsockopt(fd, level, optname, duration) }
}
fn into_ms(duration: Option<Duration>) -> DWORD {
// Note that a duration is a (u64, u32) (seconds, nanoseconds) pair, and the
// timeouts in windows APIs are typically u32 milliseconds. To translate, we
// have two pieces to take care of:
//
// * Nanosecond precision is rounded up
// * Greater than u32::MAX milliseconds (50 days) is rounded up to
// INFINITE (never time out).
duration
.map(|duration| min(duration.as_millis(), INFINITE as u128) as DWORD)
.unwrap_or(0)
}
pub(crate) fn set_tcp_keepalive(socket: Socket, keepalive: &TcpKeepalive) -> io::Result<()> {
let mut keepalive = tcp_keepalive {
onoff: 1,
keepalivetime: into_ms(keepalive.time),
keepaliveinterval: into_ms(keepalive.interval),
};
let mut out = 0;
syscall!(
WSAIoctl(
socket,
SIO_KEEPALIVE_VALS,
&mut keepalive as *mut _ as *mut _,
size_of::<tcp_keepalive>() as _,
ptr::null_mut(),
0,
&mut out,
ptr::null_mut(),
None,
),
PartialEq::eq,
sock::SOCKET_ERROR
)
.map(|_| ())
}
/// Caller must ensure `T` is the correct type for `level` and `optname`.
pub(crate) unsafe fn getsockopt<T>(socket: Socket, level: c_int, optname: c_int) -> io::Result<T> {
let mut optval: MaybeUninit<T> = MaybeUninit::uninit();
let mut optlen = mem::size_of::<T>() as c_int;
syscall!(
getsockopt(
socket,
level,
optname,
optval.as_mut_ptr().cast(),
&mut optlen,
),
PartialEq::eq,
sock::SOCKET_ERROR
)
.map(|_| {
debug_assert_eq!(optlen as usize, mem::size_of::<T>());
// Safety: `getsockopt` initialised `optval` for us.
optval.assume_init()
})
}
/// Caller must ensure `T` is the correct type for `level` and `optname`.
pub(crate) unsafe fn setsockopt<T>(
socket: Socket,
level: c_int,
optname: c_int,
optval: T,
) -> io::Result<()> {
syscall!(
setsockopt(
socket,
level,
optname,
(&optval as *const T).cast(),
mem::size_of::<T>() as c_int,
),
PartialEq::eq,
sock::SOCKET_ERROR
)
.map(|_| ())
}
fn ioctlsocket(socket: Socket, cmd: c_long, payload: &mut u_long) -> io::Result<()> {
syscall!(
ioctlsocket(socket, cmd, payload),
PartialEq::eq,
sock::SOCKET_ERROR
)
.map(|_| ())
}
pub(crate) fn to_in_addr(addr: &Ipv4Addr) -> IN_ADDR {
let mut s_un: in_addr_S_un = unsafe { mem::zeroed() };
// `S_un` is stored as BE on all machines, and the array is in BE order. So
// the native endian conversion method is used so that it's never swapped.
unsafe { *(s_un.S_addr_mut()) = u32::from_ne_bytes(addr.octets()) };
IN_ADDR { S_un: s_un }
}
pub(crate) fn from_in_addr(in_addr: IN_ADDR) -> Ipv4Addr {
Ipv4Addr::from(unsafe { *in_addr.S_un.S_addr() }.to_ne_bytes())
}
pub(crate) fn to_in6_addr(addr: &Ipv6Addr) -> in6_addr {
let mut ret_addr: in6_addr_u = unsafe { mem::zeroed() };
unsafe { *(ret_addr.Byte_mut()) = addr.octets() };
let mut ret: in6_addr = unsafe { mem::zeroed() };
ret.u = ret_addr;
ret
}
pub(crate) fn from_in6_addr(addr: in6_addr) -> Ipv6Addr {
Ipv6Addr::from(*unsafe { addr.u.Byte() })
}
pub(crate) fn to_mreqn(
multiaddr: &Ipv4Addr,
interface: &crate::socket::InterfaceIndexOrAddress,
) -> IpMreq {
IpMreq {
imr_multiaddr: to_in_addr(multiaddr),
// Per https://docs.microsoft.com/en-us/windows/win32/api/ws2ipdef/ns-ws2ipdef-ip_mreq#members:
//
// imr_interface
//
// The local IPv4 address of the interface or the interface index on
// which the multicast group should be joined or dropped. This value is
// in network byte order. If this member specifies an IPv4 address of
// 0.0.0.0, the default IPv4 multicast interface is used.
//
// To use an interface index of 1 would be the same as an IP address of
// 0.0.0.1.
imr_interface: match interface {
crate::socket::InterfaceIndexOrAddress::Index(interface) => {
to_in_addr(&(*interface).into())
}
crate::socket::InterfaceIndexOrAddress::Address(interface) => to_in_addr(interface),
},
}
}
/// Windows only API.
impl crate::Socket {
/// Sets `HANDLE_FLAG_INHERIT` using `SetHandleInformation`.
#[cfg(feature = "all")]
#[cfg_attr(docsrs, doc(cfg(all(windows, feature = "all"))))]
pub fn set_no_inherit(&self, no_inherit: bool) -> io::Result<()> {
self._set_no_inherit(no_inherit)
}
pub(crate) fn _set_no_inherit(&self, no_inherit: bool) -> io::Result<()> {
// NOTE: can't use `syscall!` because it expects the function in the
// `sock::` path.
let res = unsafe {
SetHandleInformation(
self.as_raw() as HANDLE,
winbase::HANDLE_FLAG_INHERIT,
!no_inherit as _,
)
};
if res == 0 {
// Zero means error.
Err(io::Error::last_os_error())
} else {
Ok(())
}
}
}
impl AsRawSocket for crate::Socket {
fn as_raw_socket(&self) -> RawSocket {
self.as_raw() as RawSocket
}
}
impl IntoRawSocket for crate::Socket {
fn into_raw_socket(self) -> RawSocket {
self.into_raw() as RawSocket
}
}
impl FromRawSocket for crate::Socket {
unsafe fn from_raw_socket(socket: RawSocket) -> crate::Socket {
crate::Socket::from_raw(socket as Socket)
}
}
#[test]
fn in_addr_convertion() {
let ip = Ipv4Addr::new(127, 0, 0, 1);
let raw = to_in_addr(&ip);
assert_eq!(unsafe { *raw.S_un.S_addr() }, 127 << 0 | 1 << 24);
assert_eq!(from_in_addr(raw), ip);
let ip = Ipv4Addr::new(127, 34, 4, 12);
let raw = to_in_addr(&ip);
assert_eq!(
unsafe { *raw.S_un.S_addr() },
127 << 0 | 34 << 8 | 4 << 16 | 12 << 24
);
assert_eq!(from_in_addr(raw), ip);
}
#[test]
fn in6_addr_convertion() {
let ip = Ipv6Addr::new(0x2000, 1, 2, 3, 4, 5, 6, 7);
let raw = to_in6_addr(&ip);
let want = [
0x2000u16.to_be(),
1u16.to_be(),
2u16.to_be(),
3u16.to_be(),
4u16.to_be(),
5u16.to_be(),
6u16.to_be(),
7u16.to_be(),
];
assert_eq!(unsafe { *raw.u.Word() }, want);
assert_eq!(from_in6_addr(raw), ip);
}