From 78e7b89791b41342841eadb6785f48423fa420d2 Mon Sep 17 00:00:00 2001 From: Nicola Krumschmidt Date: Fri, 30 Aug 2024 00:05:55 +0200 Subject: [PATCH] Add wasm32-wasip2 definitions necessary for std::net support --- libc-test/build.rs | 18 ++++ libc-test/semver/wasi-p2.txt | 59 +++++++++++++ src/{wasi.rs => wasi/mod.rs} | 7 ++ src/wasi/p2.rs | 161 +++++++++++++++++++++++++++++++++++ 4 files changed, 245 insertions(+) create mode 100644 libc-test/semver/wasi-p2.txt rename src/{wasi.rs => wasi/mod.rs} (99%) create mode 100644 src/wasi/p2.rs diff --git a/libc-test/build.rs b/libc-test/build.rs index 88b37451150be..812b25f8f3220 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -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); @@ -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", @@ -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), @@ -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, diff --git a/libc-test/semver/wasi-p2.txt b/libc-test/semver/wasi-p2.txt new file mode 100644 index 0000000000000..bb79dfd0dc1e8 --- /dev/null +++ b/libc-test/semver/wasi-p2.txt @@ -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 diff --git a/src/wasi.rs b/src/wasi/mod.rs similarity index 99% rename from src/wasi.rs rename to src/wasi/mod.rs index 4e894d2d1f403..5caf72a1cf9aa 100644 --- a/src/wasi.rs +++ b/src/wasi/mod.rs @@ -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::*; + } +} diff --git a/src/wasi/p2.rs b/src/wasi/p2.rs new file mode 100644 index 0000000000000..3e8eb95fcd1a5 --- /dev/null +++ b/src/wasi/p2.rs @@ -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; +}