Skip to content

Commit

Permalink
Add wasm32-wasip2 target support
Browse files Browse the repository at this point in the history
  • Loading branch information
nickrum committed Nov 13, 2024
1 parent c78061f commit a705f3f
Show file tree
Hide file tree
Showing 7 changed files with 692 additions and 115 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ targets = ["aarch64-apple-ios", "aarch64-linux-android", "x86_64-apple-darwin",
[package.metadata.playground]
features = ["all"]

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

[target.'cfg(windows)'.dependencies.windows-sys]
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

0 comments on commit a705f3f

Please sign in to comment.