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:
1
zeroidc/vendor/socket2/.cargo-checksum.json
vendored
Normal file
1
zeroidc/vendor/socket2/.cargo-checksum.json
vendored
Normal 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
39
zeroidc/vendor/socket2/Cargo.toml
vendored
Normal 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
201
zeroidc/vendor/socket2/LICENSE-APACHE
vendored
Normal 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
25
zeroidc/vendor/socket2/LICENSE-MIT
vendored
Normal 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
84
zeroidc/vendor/socket2/README.md
vendored
Normal 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
442
zeroidc/vendor/socket2/src/lib.rs
vendored
Normal 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
348
zeroidc/vendor/socket2/src/sockaddr.rs
vendored
Normal 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
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
147
zeroidc/vendor/socket2/src/sockref.rs
vendored
Normal 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
2053
zeroidc/vendor/socket2/src/sys/unix.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
848
zeroidc/vendor/socket2/src/sys/windows.rs
vendored
Normal file
848
zeroidc/vendor/socket2/src/sys/windows.rs
vendored
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user