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 definitions necessary for std::net support #3892

Merged
merged 1 commit into from
Sep 3, 2024
Merged
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
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;
}