Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
fea2cb4
Add support for SO_REUSEPORT_LB
jpds May 21, 2023
5ca3960
Add IPv6 versions of bind_device_by_index
pinkisemils Mar 22, 2023
51377a0
Add MsgHdr type
Thomasdezeeuw Jun 2, 2023
56806e8
Use MsgHdr in send(_to)_vectored
Thomasdezeeuw Jun 2, 2023
0cd03cc
Add Socket::sendmsg
Thomasdezeeuw Jun 2, 2023
457d326
Simplify two cfg attributes
Thomasdezeeuw Jun 2, 2023
49b844f
Don't use MsgHdr for recvmsg
Thomasdezeeuw Jun 3, 2023
0e2f962
Add MsgHdrMut type
Thomasdezeeuw Jun 3, 2023
2ff147e
Use proper truncation in set_msghdr_iov
Thomasdezeeuw Jun 3, 2023
008603d
Use MsgHdrMut in recvmsg
Thomasdezeeuw Jun 3, 2023
fc41670
Add Socket::recvmsg
Thomasdezeeuw Jun 7, 2023
54e7215
Support MSRV 1.63
Thomasdezeeuw Jun 7, 2023
9ce984d
Add support for IPPROTO_DIVERT
jonsen Jun 13, 2023
48e3894
Implemented full networking for WebAssembly (WASIX)
john-sharratt May 26, 2022
54d0188
Fixed a bug with the socket types
john-sharratt Jul 13, 2023
e5a4d26
Support for the ESP-IDF framework
jasta Jul 15, 2023
baa8f2b
Fix Clippy warning
Thomasdezeeuw Jul 14, 2023
77e3bb9
Small fix for ESP-IDF platform support
jasta Jul 31, 2023
b5d6c18
Merge remote-tracking branch 'upstream/master' into merge-upstream
Arshia001 Aug 22, 2023
8671124
Clean it up
Arshia001 Aug 23, 2023
bf480a5
Fix CI
Arshia001 Aug 23, 2023
bbdf714
Add WASIX to CI
Arshia001 Aug 23, 2023
27e89ba
Filter out the tests that don't work on WASIX
Arshia001 Aug 25, 2023
410884b
Fix 1.72 lints
Arshia001 Aug 25, 2023
d9bef4b
Fix "all" feature tests
Arshia001 Aug 25, 2023
521d445
Use normal libc for unix, libc-wasix for wasix
Arshia001 Aug 28, 2023
b8f1419
Fix feature=all tests
Arshia001 Aug 31, 2023
4bd0d7e
Install cargo-wasix from prebuilt binaries
Arshia001 Aug 31, 2023
675a53d
Fix a comment in Cargo.toml
Arshia001 Aug 31, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,21 @@ jobs:
- uses: taiki-e/install-action@cargo-hack
- name: Run tests
run: cargo hack test --feature-powerset && cargo hack test --feature-powerset --release
Test-Wasix:
name: Test (wasix)
runs-on: ubuntu-latest
env:
CARGO_TARGET_WASM32_WASMER_WASI_RUNNER: wasmer run --env RUST_BACKTRACE=1 --net
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
- uses: taiki-e/install-action@cargo-hack
- uses: wasmerio/setup-wasmer@v2
- name: Install cargo-wasix
run: curl --proto '=https' --tlsv1.2 -LsSf https://github.com/wasix-org/cargo-wasix/releases/latest/download/cargo-wasix-installer.sh | sh
- run: cargo wasix download-toolchain
- name: Run tests
run: cargo +wasix hack test --feature-powerset --target wasm32-wasmer-wasi -- -- --nocapture && cargo +wasix hack test --feature-powerset --release --target wasm32-wasmer-wasi -- -- --nocapture
Rustfmt:
name: Rustfmt
runs-on: ubuntu-latest
Expand All @@ -65,6 +80,18 @@ jobs:
- uses: taiki-e/install-action@cargo-hack
- name: Run check
run: cargo hack check --feature-powerset --all-targets --examples --bins --tests --target ${{ matrix.target }}
Check-Wasix:
name: Check (wasix)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
- uses: taiki-e/install-action@cargo-hack
- name: Install cargo-wasix
run: curl --proto '=https' --tlsv1.2 -LsSf https://github.com/wasix-org/cargo-wasix/releases/latest/download/cargo-wasix-installer.sh | sh
- run: cargo wasix download-toolchain
- name: Run check
run: cargo +wasix hack check --feature-powerset --all-targets --examples --bins --tests --target wasm32-wasmer-wasi
Clippy:
name: Clippy
runs-on: ubuntu-latest
Expand Down
9 changes: 7 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,13 @@ targets = ["aarch64-apple-ios", "aarch64-linux-android", "x86_64-apple-darwin",
[package.metadata.playground]
features = ["all"]

[target."cfg(unix)".dependencies]
libc = "0.2.141"
[target.'cfg(unix)'.dependencies]
libc = "0.2.147"

# Temporary, must be updated to point to the official libc package as soon
# as WASIX-related changes are merged in.
[target.'cfg(target_os = "wasi")'.dependencies]
libc-wasix = "0.2.147"

[target.'cfg(windows)'.dependencies.windows-sys]
version = "0.48"
Expand Down
173 changes: 167 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@
#![doc(test(attr(deny(warnings))))]

use std::fmt;
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
use std::io::IoSlice;
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
use std::marker::PhantomData;
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
use std::mem;
use std::mem::MaybeUninit;
use std::net::SocketAddr;
use std::ops::{Deref, DerefMut};
Expand Down Expand Up @@ -101,7 +107,7 @@ macro_rules! from {
($from: ty, $for: ty) => {
impl From<$from> for $for {
fn from(socket: $from) -> $for {
#[cfg(unix)]
#[cfg(any(unix, target_os = "wasi"))]
unsafe {
<$for>::from_raw_fd(socket.into_raw_fd())
}
Expand Down Expand Up @@ -168,11 +174,15 @@ mod sockaddr;
mod socket;
mod sockref;

#[cfg(target_os = "wasi")]
extern crate libc_wasix as libc;

#[cfg_attr(unix, path = "sys/unix.rs")]
#[cfg_attr(windows, path = "sys/windows.rs")]
#[cfg_attr(target_os = "wasi", path = "sys/wasi.rs")]
mod sys;

#[cfg(not(any(windows, unix)))]
#[cfg(not(any(windows, unix, target_os = "wasi")))]
compile_error!("Socket2 doesn't support the compile target");

use sys::c_int;
Expand Down Expand Up @@ -264,13 +274,16 @@ impl Type {
pub const DCCP: Type = Type(sys::SOCK_DCCP);

/// Type corresponding to `SOCK_SEQPACKET`.
#[cfg(feature = "all")]
#[cfg_attr(docsrs, doc(cfg(feature = "all")))]
#[cfg(all(feature = "all", not(target_os = "espidf")))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "all", not(target_os = "espidf")))))]
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")))))]
#[cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))]
#[cfg_attr(
docsrs,
doc(cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf")))))
)]
pub const RAW: Type = Type(sys::SOCK_RAW);
}

Expand Down Expand Up @@ -333,6 +346,10 @@ impl Protocol {
)
))]
pub const UDPLITE: Protocol = Protocol(sys::IPPROTO_UDPLITE);

/// Protocol corresponding to `DIVERT`.
#[cfg(all(feature = "all", any(target_os = "freebsd", target_os = "openbsd")))]
pub const DIVERT: Protocol = Protocol(sys::IPPROTO_DIVERT);
}

impl From<c_int> for Protocol {
Expand Down Expand Up @@ -364,6 +381,7 @@ impl RecvFlags {
///
/// On Unix this corresponds to the `MSG_TRUNC` flag.
/// On Windows this corresponds to the `WSAEMSGSIZE` error code.
#[cfg(not(target_os = "espidf"))]
pub const fn is_truncated(self) -> bool {
self.0 & sys::MSG_TRUNC != 0
}
Expand Down Expand Up @@ -418,6 +436,7 @@ pub struct TcpKeepalive {
target_os = "redox",
target_os = "solaris",
target_os = "nto",
target_os = "espidf",
)))]
interval: Option<Duration>,
#[cfg(not(any(
Expand All @@ -426,6 +445,7 @@ pub struct TcpKeepalive {
target_os = "solaris",
target_os = "windows",
target_os = "nto",
target_os = "espidf",
)))]
retries: Option<u32>,
}
Expand All @@ -440,6 +460,7 @@ impl TcpKeepalive {
target_os = "redox",
target_os = "solaris",
target_os = "nto",
target_os = "espidf",
)))]
interval: None,
#[cfg(not(any(
Expand All @@ -448,6 +469,7 @@ impl TcpKeepalive {
target_os = "solaris",
target_os = "windows",
target_os = "nto",
target_os = "espidf",
)))]
retries: None,
}
Expand Down Expand Up @@ -490,6 +512,7 @@ impl TcpKeepalive {
target_os = "netbsd",
target_os = "tvos",
target_os = "watchos",
target_os = "wasi",
target_os = "windows",
))]
#[cfg_attr(
Expand All @@ -507,6 +530,7 @@ impl TcpKeepalive {
target_os = "tvos",
target_os = "watchos",
target_os = "windows",
target_os = "wasi",
)))
)]
pub const fn with_interval(self, interval: Duration) -> Self {
Expand All @@ -531,6 +555,7 @@ impl TcpKeepalive {
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "wasi",
target_os = "netbsd",
target_os = "tvos",
target_os = "watchos",
Expand All @@ -549,6 +574,7 @@ impl TcpKeepalive {
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "wasi",
target_os = "netbsd",
target_os = "tvos",
target_os = "watchos",
Expand All @@ -562,3 +588,138 @@ impl TcpKeepalive {
}
}
}

/// Configuration of a `sendmsg(2)` system call.
///
/// This wraps `msghdr` on Unix and `WSAMSG` on Windows. Also see [`MsgHdrMut`]
/// for the variant used by `recvmsg(2)`.
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
pub struct MsgHdr<'addr, 'bufs, 'control> {
inner: sys::msghdr,
#[allow(clippy::type_complexity)]
_lifetimes: PhantomData<(&'addr SockAddr, &'bufs IoSlice<'bufs>, &'control [u8])>,
}

#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
impl<'addr, 'bufs, 'control> MsgHdr<'addr, 'bufs, 'control> {
/// Create a new `MsgHdr` with all empty/zero fields.
#[allow(clippy::new_without_default)]
pub fn new() -> MsgHdr<'addr, 'bufs, 'control> {
// SAFETY: all zero is valid for `msghdr` and `WSAMSG`.
MsgHdr {
inner: unsafe { mem::zeroed() },
_lifetimes: PhantomData,
}
}

/// Set the address (name) of the message.
///
/// Corresponds to setting `msg_name` and `msg_namelen` on Unix and `name`
/// and `namelen` on Windows.
pub fn with_addr(mut self, addr: &'addr SockAddr) -> Self {
sys::set_msghdr_name(&mut self.inner, addr);
self
}

/// Set the buffer(s) of the message.
///
/// Corresponds to setting `msg_iov` and `msg_iovlen` on Unix and `lpBuffers`
/// and `dwBufferCount` on Windows.
pub fn with_buffers(mut self, bufs: &'bufs [IoSlice<'_>]) -> Self {
let ptr = bufs.as_ptr() as *mut _;
sys::set_msghdr_iov(&mut self.inner, ptr, bufs.len());
self
}

/// Set the control buffer of the message.
///
/// Corresponds to setting `msg_control` and `msg_controllen` on Unix and
/// `Control` on Windows.
pub fn with_control(mut self, buf: &'control [u8]) -> Self {
let ptr = buf.as_ptr() as *mut _;
sys::set_msghdr_control(&mut self.inner, ptr, buf.len());
self
}

/// Set the flags of the message.
///
/// Corresponds to setting `msg_flags` on Unix and `dwFlags` on Windows.
pub fn with_flags(mut self, flags: sys::c_int) -> Self {
sys::set_msghdr_flags(&mut self.inner, flags);
self
}
}

#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
impl<'name, 'bufs, 'control> fmt::Debug for MsgHdr<'name, 'bufs, 'control> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
"MsgHdr".fmt(fmt)
}
}

/// Configuration of a `recvmsg(2)` system call.
///
/// This wraps `msghdr` on Unix and `WSAMSG` on Windows. Also see [`MsgHdr`] for
/// the variant used by `sendmsg(2)`.
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
pub struct MsgHdrMut<'addr, 'bufs, 'control> {
inner: sys::msghdr,
#[allow(clippy::type_complexity)]
_lifetimes: PhantomData<(
&'addr mut SockAddr,
&'bufs mut MaybeUninitSlice<'bufs>,
&'control mut [u8],
)>,
}

#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
impl<'addr, 'bufs, 'control> MsgHdrMut<'addr, 'bufs, 'control> {
/// Create a new `MsgHdrMut` with all empty/zero fields.
#[allow(clippy::new_without_default)]
pub fn new() -> MsgHdrMut<'addr, 'bufs, 'control> {
// SAFETY: all zero is valid for `msghdr` and `WSAMSG`.
MsgHdrMut {
inner: unsafe { mem::zeroed() },
_lifetimes: PhantomData,
}
}

/// Set the mutable address (name) of the message.
///
/// Corresponds to setting `msg_name` and `msg_namelen` on Unix and `name`
/// and `namelen` on Windows.
pub fn with_addr(mut self, addr: &'addr mut SockAddr) -> Self {
sys::set_msghdr_name(&mut self.inner, addr);
self
}

/// Set the mutable buffer(s) of the message.
///
/// Corresponds to setting `msg_iov` and `msg_iovlen` on Unix and `lpBuffers`
/// and `dwBufferCount` on Windows.
pub fn with_buffers(mut self, bufs: &'bufs mut [MaybeUninitSlice<'_>]) -> Self {
sys::set_msghdr_iov(&mut self.inner, bufs.as_mut_ptr().cast(), bufs.len());
self
}

/// Set the mutable control buffer of the message.
///
/// Corresponds to setting `msg_control` and `msg_controllen` on Unix and
/// `Control` on Windows.
pub fn with_control(mut self, buf: &'control mut [MaybeUninit<u8>]) -> Self {
sys::set_msghdr_control(&mut self.inner, buf.as_mut_ptr().cast(), buf.len());
self
}

/// Returns the flags of the message.
pub fn flags(&self) -> RecvFlags {
sys::msghdr_flags(&self.inner)
}
}

#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
impl<'name, 'bufs, 'control> fmt::Debug for MsgHdrMut<'name, 'bufs, 'control> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
"MsgHdrMut".fmt(fmt)
}
}
8 changes: 5 additions & 3 deletions src/sockaddr.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::hash::Hash;
use std::mem::{self, size_of, MaybeUninit};
use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
#[cfg(not(target_os = "wasi"))]
use std::path::Path;
use std::{fmt, io, ptr};

Expand Down Expand Up @@ -146,6 +147,7 @@ impl SockAddr {
/// Constructs a `SockAddr` with the family `AF_UNIX` and the provided path.
///
/// Returns an error if the path is longer than `SUN_LEN`.
#[cfg(not(target_os = "wasi"))]
pub fn unix<P>(path: P) -> io::Result<SockAddr>
where
P: AsRef<Path>,
Expand Down Expand Up @@ -206,7 +208,7 @@ impl SockAddr {
}

/// Returns a raw pointer to the address storage.
#[cfg(all(unix, not(target_os = "redox")))]
#[cfg(target_os = "wasi")]
pub(crate) const fn as_storage_ptr(&self) -> *const sockaddr_storage {
&self.storage
}
Expand All @@ -231,7 +233,7 @@ impl SockAddr {
ip,
port,
addr.sin6_flowinfo,
#[cfg(unix)]
#[cfg(any(unix, all(target_os = "wasi", target_vendor = "wasmer")))]
addr.sin6_scope_id,
#[cfg(windows)]
unsafe {
Expand Down Expand Up @@ -305,7 +307,7 @@ impl From<SocketAddrV6> for SockAddr {
storage.sin6_port = addr.port().to_be();
storage.sin6_addr = crate::sys::to_in6_addr(addr.ip());
storage.sin6_flowinfo = addr.flowinfo();
#[cfg(unix)]
#[cfg(any(unix, all(target_os = "wasi", target_vendor = "wasmer")))]
{
storage.sin6_scope_id = addr.scope_id();
}
Expand Down
Loading