Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add wasm32-wasip2 target support #532

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ jobs:
- i686-unknown-hurd-gnu
- i686-unknown-linux-gnu
- sparcv9-sun-solaris
- wasm32-wasip2
- x86_64-apple-darwin
- x86_64-apple-ios
- x86_64-pc-solaris
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ targets = ["aarch64-apple-ios", "aarch64-linux-android", "x86_64-apple-darwin",
[package.metadata.playground]
features = ["all"]

[target."cfg(unix)".dependencies]
libc = "0.2.150"
[target.'cfg(any(unix, target_os = "wasi"))'.dependencies]
libc = "0.2.162"

[target.'cfg(windows)'.dependencies.windows-sys]
version = "0.52"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ feature flag.

# Minimum Supported Rust Version (MSRV)

Socket2 uses 1.63.0 as MSRV.
Socket2 uses 1.63.0 (1.66.0 for wasm32-wasip2) as MSRV.

# License

Expand Down
73 changes: 49 additions & 24 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,18 @@
// Disallow warnings in examples.
#![doc(test(attr(deny(warnings))))]

#[cfg(not(target_os = "wasi"))]
use std::fmt;
#[cfg(not(target_os = "redox"))]
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
use std::io::IoSlice;
#[cfg(not(target_os = "redox"))]
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
use std::marker::PhantomData;
#[cfg(not(target_os = "redox"))]
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
use std::mem;
#[cfg(not(target_os = "wasi"))]
use std::mem::MaybeUninit;
use std::net::SocketAddr;
#[cfg(not(target_os = "wasi"))]
use std::ops::{Deref, DerefMut};
use std::time::Duration;

Expand Down Expand Up @@ -107,7 +110,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 @@ -176,9 +179,10 @@ mod sockref;

#[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, all(target_os = "wasi", target_env = "p2"))))]
compile_error!("Socket2 doesn't support the compile target");

use sys::c_int;
Expand Down Expand Up @@ -216,6 +220,7 @@ impl Domain {
pub const IPV6: Domain = Domain(sys::AF_INET6);

/// Domain for Unix socket communication, corresponding to `AF_UNIX`.
#[cfg(not(target_os = "wasi"))]
pub const UNIX: Domain = Domain(sys::AF_UNIX);

/// Returns the correct domain for `address`.
Expand Down Expand Up @@ -270,15 +275,24 @@ impl Type {
pub const DCCP: Type = Type(sys::SOCK_DCCP);

/// Type corresponding to `SOCK_SEQPACKET`.
#[cfg(all(feature = "all", not(target_os = "espidf")))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "all", not(target_os = "espidf")))))]
#[cfg(all(feature = "all", not(any(target_os = "espidf", target_os = "wasi"))))]
#[cfg_attr(
docsrs,
doc(cfg(all(feature = "all", not(any(target_os = "espidf", target_os = "wasi")))))
)]
pub const SEQPACKET: Type = Type(sys::SOCK_SEQPACKET);

/// Type corresponding to `SOCK_RAW`.
#[cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))]
#[cfg(all(
feature = "all",
not(any(target_os = "redox", target_os = "espidf", target_os = "wasi"))
))]
#[cfg_attr(
docsrs,
doc(cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf")))))
doc(cfg(all(
feature = "all",
not(any(target_os = "redox", target_os = "espidf", target_os = "wasi"))
)))
)]
pub const RAW: Type = Type(sys::SOCK_RAW);
}
Expand Down Expand Up @@ -306,18 +320,20 @@ impl From<Type> for c_int {
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);

#[cfg(not(target_os = "wasi"))]
/// Protocol corresponding to `ICMPv4`.
pub const ICMPV4: Protocol = Protocol(sys::IPPROTO_ICMP);

#[cfg(not(target_os = "wasi"))]
/// Protocol corresponding to `ICMPv6`.
pub const ICMPV6: Protocol = Protocol(sys::IPPROTO_ICMPV6);

#[cfg(target_os = "linux")]
/// Protocol corresponding to `MPTCP`.
pub const MPTCP: Protocol = Protocol(sys::IPPROTO_MPTCP);
Expand Down Expand Up @@ -363,12 +379,12 @@ impl From<Protocol> for c_int {
/// 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"))))]
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
#[cfg_attr(docsrs, doc(cfg(not(any(target_os = "redox", target_os = "wasi")))))]
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct RecvFlags(c_int);

#[cfg(not(target_os = "redox"))]
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
impl RecvFlags {
/// Check if the message contains a truncated datagram.
///
Expand All @@ -386,15 +402,18 @@ impl RecvFlags {
/// A version of [`IoSliceMut`] that allows the buffer to be uninitialised.
///
/// [`IoSliceMut`]: std::io::IoSliceMut
#[cfg(not(target_os = "wasi"))]
#[repr(transparent)]
pub struct MaybeUninitSlice<'a>(sys::MaybeUninitSlice<'a>);

#[cfg(not(target_os = "wasi"))]
impl<'a> fmt::Debug for MaybeUninitSlice<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.0.as_slice(), fmt)
}
}

#[cfg(not(target_os = "wasi"))]
impl<'a> MaybeUninitSlice<'a> {
/// Creates a new `MaybeUninitSlice` wrapping a byte slice.
///
Expand All @@ -406,6 +425,7 @@ impl<'a> MaybeUninitSlice<'a> {
}
}

#[cfg(not(target_os = "wasi"))]
impl<'a> Deref for MaybeUninitSlice<'a> {
type Target = [MaybeUninit<u8>];

Expand All @@ -414,6 +434,7 @@ impl<'a> Deref for MaybeUninitSlice<'a> {
}
}

#[cfg(not(target_os = "wasi"))]
impl<'a> DerefMut for MaybeUninitSlice<'a> {
fn deref_mut(&mut self) -> &mut [MaybeUninit<u8>] {
self.0.as_mut_slice()
Expand Down Expand Up @@ -520,6 +541,7 @@ impl TcpKeepalive {
target_os = "macos",
target_os = "netbsd",
target_os = "tvos",
target_os = "wasi",
target_os = "watchos",
target_os = "windows",
))]
Expand All @@ -537,6 +559,7 @@ impl TcpKeepalive {
target_os = "macos",
target_os = "netbsd",
target_os = "tvos",
target_os = "wasi",
target_os = "watchos",
target_os = "windows",
)))
Expand Down Expand Up @@ -566,6 +589,7 @@ impl TcpKeepalive {
target_os = "macos",
target_os = "netbsd",
target_os = "tvos",
target_os = "wasi",
target_os = "watchos",
)
))]
Expand All @@ -585,6 +609,7 @@ impl TcpKeepalive {
target_os = "macos",
target_os = "netbsd",
target_os = "tvos",
target_os = "wasi",
target_os = "watchos",
)
)))
Expand All @@ -601,14 +626,14 @@ impl TcpKeepalive {
///
/// This wraps `msghdr` on Unix and `WSAMSG` on Windows. Also see [`MsgHdrMut`]
/// for the variant used by `recvmsg(2)`.
#[cfg(not(target_os = "redox"))]
#[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(target_os = "redox"))]
#[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)]
Expand Down Expand Up @@ -658,7 +683,7 @@ impl<'addr, 'bufs, 'control> MsgHdr<'addr, 'bufs, 'control> {
}
}

#[cfg(not(target_os = "redox"))]
#[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)
Expand All @@ -669,7 +694,7 @@ impl<'name, 'bufs, 'control> fmt::Debug for MsgHdr<'name, 'bufs, 'control> {
///
/// This wraps `msghdr` on Unix and `WSAMSG` on Windows. Also see [`MsgHdr`] for
/// the variant used by `sendmsg(2)`.
#[cfg(not(target_os = "redox"))]
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
pub struct MsgHdrMut<'addr, 'bufs, 'control> {
inner: sys::msghdr,
#[allow(clippy::type_complexity)]
Expand All @@ -680,7 +705,7 @@ pub struct MsgHdrMut<'addr, 'bufs, 'control> {
)>,
}

#[cfg(not(target_os = "redox"))]
#[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)]
Expand Down Expand Up @@ -735,7 +760,7 @@ impl<'addr, 'bufs, 'control> MsgHdrMut<'addr, 'bufs, 'control> {
}
}

#[cfg(not(target_os = "redox"))]
#[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)
Expand Down
18 changes: 14 additions & 4 deletions src/sockaddr.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
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};

#[cfg(windows)]
use windows_sys::Win32::Networking::WinSock::SOCKADDR_IN6_0;

#[cfg(not(target_os = "wasi"))]
use crate::sys::AF_UNIX;
use crate::sys::{
c_int, sa_family_t, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_storage, socklen_t, AF_INET,
AF_INET6, AF_UNIX,
AF_INET6,
};
use crate::Domain;

Expand Down Expand Up @@ -146,6 +149,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 @@ -201,6 +205,7 @@ impl SockAddr {

/// Returns true if this address is of a unix socket (for local interprocess communication),
/// i.e. it is from the `AF_UNIX` family, false otherwise.
#[cfg(not(target_os = "wasi"))]
pub fn is_unix(&self) -> bool {
self.storage.ss_family == AF_UNIX as sa_family_t
}
Expand All @@ -225,7 +230,7 @@ impl SockAddr {
ip,
port,
addr.sin6_flowinfo,
#[cfg(unix)]
#[cfg(any(unix, target_os = "wasi"))]
addr.sin6_scope_id,
#[cfg(windows)]
unsafe {
Expand Down Expand Up @@ -282,7 +287,10 @@ impl From<SocketAddrV4> for SockAddr {
storage.sin_family = AF_INET as sa_family_t;
storage.sin_port = addr.port().to_be();
storage.sin_addr = crate::sys::to_in_addr(addr.ip());
storage.sin_zero = Default::default();
#[cfg(not(target_os = "wasi"))]
{
storage.sin_zero = Default::default();
}
mem::size_of::<sockaddr_in>() as socklen_t
};
#[cfg(any(
Expand Down Expand Up @@ -317,7 +325,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, target_os = "wasi"))]
{
storage.sin6_scope_id = addr.scope_id();
}
Expand Down Expand Up @@ -401,6 +409,7 @@ mod tests {
let addr = SockAddr::from(std);
assert!(addr.is_ipv4());
assert!(!addr.is_ipv6());
#[cfg(not(target_os = "wasi"))]
assert!(!addr.is_unix());
assert_eq!(addr.family(), AF_INET as sa_family_t);
assert_eq!(addr.domain(), Domain::IPV4);
Expand Down Expand Up @@ -429,6 +438,7 @@ mod tests {
let addr = SockAddr::from(std);
assert!(addr.is_ipv6());
assert!(!addr.is_ipv4());
#[cfg(not(target_os = "wasi"))]
assert!(!addr.is_unix());
assert_eq!(addr.family(), AF_INET6 as sa_family_t);
assert_eq!(addr.domain(), Domain::IPV6);
Expand Down
Loading
Loading