Skip to content

Commit

Permalink
Add wasm32-wasip2 definitions necessary for std::net support
Browse files Browse the repository at this point in the history
  • Loading branch information
nickrum committed Sep 3, 2024
1 parent cdf6896 commit 78e7b89
Show file tree
Hide file tree
Showing 4 changed files with 245 additions and 0 deletions.
18 changes: 18 additions & 0 deletions libc-test/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1455,6 +1455,7 @@ fn test_dragonflybsd(target: &str) {

fn test_wasi(target: &str) {
assert!(target.contains("wasi"));
let p2 = target.contains("wasip2");

let mut cfg = ctest_cfg();
cfg.define("_GNU_SOURCE", None);
Expand All @@ -1468,6 +1469,9 @@ fn test_wasi(target: &str) {
"limits.h",
"locale.h",
"malloc.h",
[p2]: "netdb.h",
[p2]: "netinet/in.h",
[p2]: "netinet/tcp.h",
"poll.h",
"sched.h",
"stdbool.h",
Expand Down Expand Up @@ -1499,6 +1503,12 @@ fn test_wasi(target: &str) {
// to omit them.
cfg.cfg("libc_ctest", None);

// `ctest2` has a hard-coded list of default cfgs which doesn't include
// wasip2, which is why it has to be set here manually.
if p2 {
cfg.cfg("target_env", Some("p2"));
}

cfg.type_name(move |ty, is_struct, is_union| match ty {
"FILE" | "fd_set" | "DIR" => ty.to_string(),
t if is_union => format!("union {}", t),
Expand All @@ -1521,6 +1531,14 @@ fn test_wasi(target: &str) {
// used here to generate a pointer to them in bindings so skip these tests.
cfg.skip_static(|c| c.starts_with("_CLOCK_"));

cfg.skip_const(|c| match c {
// These constants aren't yet defined in wasi-libc.
// Exposing them is being tracked by https://github.com/WebAssembly/wasi-libc/issues/531.
"SO_BROADCAST" | "SO_LINGER" => true,

_ => false,
});

cfg.skip_fn(|f| match f {
// This function doesn't actually exist in libc's header files
"__errno_location" => true,
Expand Down
59 changes: 59 additions & 0 deletions libc-test/semver/wasi-p2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
sa_family_t
in_port_t
in_addr_t
socklen_t
sockaddr
in_addr
sockaddr_in
in6_addr
sockaddr_in6
sockaddr_storage
addrinfo
ip_mreq
ipv6_mreq
SHUT_RD
SHUT_WR
SHUT_RDWR
MSG_NOSIGNAL
MSG_PEEK
SO_REUSEADDR
SO_ERROR
SO_BROADCAST
SO_LINGER
SO_RCVTIMEO
SO_SNDTIMEO
SOCK_DGRAM
SOCK_STREAM
SOL_SOCKET
AF_INET
AF_INET6
IPPROTO_IP
IPPROTO_TCP
IPPROTO_IPV6
IP_TTL
IP_MULTICAST_TTL
IP_MULTICAST_LOOP
IP_ADD_MEMBERSHIP
IP_DROP_MEMBERSHIP
IPV6_MULTICAST_LOOP
IPV6_JOIN_GROUP
IPV6_LEAVE_GROUP
IPV6_V6ONLY
IPV6_ADD_MEMBERSHIP
IPV6_DROP_MEMBERSHIP
TCP_NODELAY
EAI_SYSTEM
socket
connect
bind
listen
accept
getsockname
getpeername
sendto
recvfrom
getsockopt
setsockopt
getaddrinfo
freeaddrinfo
gai_strerror
7 changes: 7 additions & 0 deletions src/wasi.rs → src/wasi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -882,3 +882,10 @@ extern "C" {

pub fn __errno_location() -> *mut ::c_int;
}

cfg_if! {
if #[cfg(target_env = "p2")] {
mod p2;
pub use self::p2::*;
}
}
161 changes: 161 additions & 0 deletions src/wasi/p2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
pub type sa_family_t = ::c_ushort;
pub type in_port_t = ::c_ushort;
pub type in_addr_t = ::c_uint;

pub type socklen_t = ::c_uint;

s! {
#[repr(align(16))]
pub struct sockaddr {
pub sa_family: sa_family_t,
pub sa_data: [::c_char; 0],
}

pub struct in_addr {
pub s_addr: in_addr_t,
}

#[repr(align(16))]
pub struct sockaddr_in {
pub sin_family: sa_family_t,
pub sin_port: in_port_t,
pub sin_addr: in_addr,
}

#[repr(align(4))]
pub struct in6_addr {
pub s6_addr: [::c_uchar; 16],
}

#[repr(align(16))]
pub struct sockaddr_in6 {
pub sin6_family: sa_family_t,
pub sin6_port: in_port_t,
pub sin6_flowinfo: ::c_uint,
pub sin6_addr: in6_addr,
pub sin6_scope_id: ::c_uint,
}

#[repr(align(16))]
pub struct sockaddr_storage {
pub ss_family: sa_family_t,
pub __ss_data: [::c_char; 32],
}

pub struct addrinfo {
pub ai_flags: ::c_int,
pub ai_family: ::c_int,
pub ai_socktype: ::c_int,
pub ai_protocol: ::c_int,
pub ai_addrlen: socklen_t,
pub ai_addr: *mut sockaddr,
pub ai_canonname: *mut ::c_char,
pub ai_next: *mut addrinfo,
}

pub struct ip_mreq {
pub imr_multiaddr: in_addr,
pub imr_interface: in_addr,
}

pub struct ipv6_mreq {
pub ipv6mr_multiaddr: in6_addr,
pub ipv6mr_interface: ::c_uint,
}
}

pub const SHUT_RD: ::c_int = 1 << 0;
pub const SHUT_WR: ::c_int = 1 << 1;
pub const SHUT_RDWR: ::c_int = SHUT_RD | SHUT_WR;

pub const MSG_NOSIGNAL: ::c_int = 0x4000;
pub const MSG_PEEK: ::c_int = 0x0002;

pub const SO_REUSEADDR: ::c_int = 2;
pub const SO_ERROR: ::c_int = 4;
pub const SO_BROADCAST: ::c_int = 6;
pub const SO_LINGER: ::c_int = 13;
pub const SO_RCVTIMEO: ::c_int = 66;
pub const SO_SNDTIMEO: ::c_int = 67;

pub const SOCK_DGRAM: ::c_int = 5;
pub const SOCK_STREAM: ::c_int = 6;

pub const SOL_SOCKET: ::c_int = 0x7fffffff;

pub const AF_INET: ::c_int = 1;
pub const AF_INET6: ::c_int = 2;

pub const IPPROTO_IP: ::c_int = 0;
pub const IPPROTO_TCP: ::c_int = 6;
pub const IPPROTO_IPV6: ::c_int = 41;

pub const IP_TTL: ::c_int = 2;
pub const IP_MULTICAST_TTL: ::c_int = 33;
pub const IP_MULTICAST_LOOP: ::c_int = 34;
pub const IP_ADD_MEMBERSHIP: ::c_int = 35;
pub const IP_DROP_MEMBERSHIP: ::c_int = 36;

pub const IPV6_MULTICAST_LOOP: ::c_int = 19;
pub const IPV6_JOIN_GROUP: ::c_int = 20;
pub const IPV6_LEAVE_GROUP: ::c_int = 21;
pub const IPV6_V6ONLY: ::c_int = 26;

pub const IPV6_ADD_MEMBERSHIP: ::c_int = IPV6_JOIN_GROUP;
pub const IPV6_DROP_MEMBERSHIP: ::c_int = IPV6_LEAVE_GROUP;

pub const TCP_NODELAY: ::c_int = 1;

pub const EAI_SYSTEM: ::c_int = -11;

extern "C" {
pub fn socket(domain: ::c_int, type_: ::c_int, protocol: ::c_int) -> ::c_int;
pub fn connect(fd: ::c_int, name: *const sockaddr, addrlen: socklen_t) -> ::c_int;
pub fn bind(socket: ::c_int, addr: *const sockaddr, addrlen: socklen_t) -> ::c_int;
pub fn listen(socket: ::c_int, backlog: ::c_int) -> ::c_int;
pub fn accept(socket: ::c_int, addr: *mut sockaddr, addrlen: *mut socklen_t) -> ::c_int;

pub fn getsockname(socket: ::c_int, addr: *mut sockaddr, addrlen: *mut socklen_t) -> ::c_int;
pub fn getpeername(socket: ::c_int, addr: *mut sockaddr, addrlen: *mut socklen_t) -> ::c_int;

pub fn sendto(
socket: ::c_int,
buffer: *const ::c_void,
length: ::size_t,
flags: ::c_int,
addr: *const sockaddr,
addrlen: socklen_t,
) -> ::ssize_t;
pub fn recvfrom(
socket: ::c_int,
buffer: *mut ::c_void,
length: ::size_t,
flags: ::c_int,
addr: *mut sockaddr,
addrlen: *mut socklen_t,
) -> ::ssize_t;

pub fn getsockopt(
sockfd: ::c_int,
level: ::c_int,
optname: ::c_int,
optval: *mut ::c_void,
optlen: *mut socklen_t,
) -> ::c_int;
pub fn setsockopt(
sockfd: ::c_int,
level: ::c_int,
optname: ::c_int,
optval: *const ::c_void,
optlen: socklen_t,
) -> ::c_int;

pub fn getaddrinfo(
host: *const ::c_char,
serv: *const ::c_char,
hint: *const addrinfo,
res: *mut *mut addrinfo,
) -> ::c_int;
pub fn freeaddrinfo(p: *mut addrinfo);
pub fn gai_strerror(ecode: ::c_int) -> *const ::c_char;
}

0 comments on commit 78e7b89

Please sign in to comment.