mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Rollup merge of #129638 - nickrum:wasip2-net, r=alexcrichton
Hook up std::net to wasi-libc on wasm32-wasip2 target One of the improvements of the `wasm32-wasip2` target over `wasm32-wasip1` is better support for networking. Right now, p2 is just re-using the `std::net` implementation from p1. This PR adds a new net module for p2 that makes use of net from `sys_common` and calls wasi-libc functions directly. There are currently a few limitations: - Duplicating a socket is not supported by WASIp2 (directly returns an error) - Peeking is not yet implemented in wasi-libc (we could let wasi-libc handle this, but I opted to directly return an error instead) - Vectored reads/writes are not supported by WASIp2 (the necessary functions are available in wasi-libc, but they call WASIp1 functions which do not support sockets, so I opted to directly return an error instead) - Getting/setting `TCP_NODELAY` is faked in wasi-libc (uses the fake implementation instead of returning an error) - Getting/setting `SO_LINGER` is not supported by WASIp2 (directly returns an error) - Setting `SO_REUSEADDR` is faked in wasi-libc (since this is done from `sys_common`, the fake implementation is used instead of returning an error) - Getting/setting `IPV6_V6ONLY` is not supported by WASIp2 and will always be set for IPv6 sockets (since this is done from `sys_common`, wasi-libc will return an error) - UDP broadcast/multicast is not supported by WASIp2 (since this is configured from `sys_common`, wasi-libc will return appropriate errors) - The `MSG_NOSIGNAL` send flag is a no-op because there are no signals in WASIp2 (since explicitly setting this flag would require a change to `sys_common` and the result would be exactly the same, I opted to not set it) Do those decisions make sense? While working on this PR, I noticed that there is a `std::os::wasi::net::TcpListenerExt` trait that adds a `sock_accept()` method to `std::net::TcpListener`. Now that WASIp2 supports standard accept, would it make sense to remove this? cc `@alexcrichton`
This commit is contained in:
commit
b70654199a
@ -1018,6 +1018,7 @@ mod test_extract_if {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
|
||||
fn drop_panic_leak() {
|
||||
static PREDS: AtomicUsize = AtomicUsize::new(0);
|
||||
static DROPS: AtomicUsize = AtomicUsize::new(0);
|
||||
@ -1047,6 +1048,7 @@ mod test_extract_if {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
|
||||
fn pred_panic_leak() {
|
||||
static PREDS: AtomicUsize = AtomicUsize::new(0);
|
||||
static DROPS: AtomicUsize = AtomicUsize::new(0);
|
||||
@ -1076,6 +1078,7 @@ mod test_extract_if {
|
||||
|
||||
// Same as above, but attempt to use the iterator again after the panic in the predicate
|
||||
#[test]
|
||||
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
|
||||
fn pred_panic_reuse() {
|
||||
static PREDS: AtomicUsize = AtomicUsize::new(0);
|
||||
static DROPS: AtomicUsize = AtomicUsize::new(0);
|
||||
|
@ -429,6 +429,7 @@ fn test_extract_if() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
|
||||
fn test_extract_if_drop_panic_leak() {
|
||||
static PREDS: AtomicU32 = AtomicU32::new(0);
|
||||
static DROPS: AtomicU32 = AtomicU32::new(0);
|
||||
@ -459,6 +460,7 @@ fn test_extract_if_drop_panic_leak() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
|
||||
fn test_extract_if_pred_panic_leak() {
|
||||
static PREDS: AtomicU32 = AtomicU32::new(0);
|
||||
static DROPS: AtomicU32 = AtomicU32::new(0);
|
||||
|
2
library/std/src/env/tests.rs
vendored
2
library/std/src/env/tests.rs
vendored
@ -1,7 +1,7 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi", target_env = "sgx"), ignore)]
|
||||
fn test_self_exe_path() {
|
||||
let path = current_exe();
|
||||
assert!(path.is_ok());
|
||||
|
@ -8,7 +8,15 @@
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx", target_os = "xous"))))]
|
||||
#[cfg(all(
|
||||
test,
|
||||
not(any(
|
||||
target_os = "emscripten",
|
||||
target_os = "wasi",
|
||||
target_env = "sgx",
|
||||
target_os = "xous"
|
||||
))
|
||||
))]
|
||||
mod tests;
|
||||
|
||||
use crate::ffi::OsString;
|
||||
|
@ -164,6 +164,7 @@ fn test_buffered_reader_stream_position() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
|
||||
fn test_buffered_reader_stream_position_panic() {
|
||||
let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
|
||||
let mut reader = BufReader::with_capacity(4, io::Cursor::new(inner));
|
||||
@ -487,7 +488,7 @@ fn dont_panic_in_drop_on_panicked_flush() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
fn panic_in_write_doesnt_flush_in_drop() {
|
||||
static WRITES: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
|
@ -25,7 +25,7 @@ fn stderrlock_unwind_safe() {
|
||||
fn assert_unwind_safe<T: UnwindSafe + RefUnwindSafe>() {}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
fn panic_doesnt_poison() {
|
||||
thread::spawn(|| {
|
||||
let _a = stdin();
|
||||
@ -48,17 +48,17 @@ fn panic_doesnt_poison() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
fn test_lock_stderr() {
|
||||
test_lock(stderr, || stderr().lock());
|
||||
}
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
fn test_lock_stdin() {
|
||||
test_lock(stdin, || stdin().lock());
|
||||
}
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
fn test_lock_stdout() {
|
||||
test_lock(stdout, || stdout().lock());
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Tests for this module
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", all(target_os = "wasi", target_env = "p1")))))]
|
||||
mod tests;
|
||||
|
||||
#[stable(feature = "ip_addr", since = "1.7.0")]
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Tests for this module
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", all(target_os = "wasi", target_env = "p1")))))]
|
||||
mod tests;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -1,6 +1,13 @@
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_os = "xous"))))]
|
||||
#[cfg(all(
|
||||
test,
|
||||
not(any(
|
||||
target_os = "emscripten",
|
||||
all(target_os = "wasi", target_env = "p1"),
|
||||
target_os = "xous"
|
||||
))
|
||||
))]
|
||||
mod tests;
|
||||
|
||||
use crate::fmt;
|
||||
|
@ -57,6 +57,7 @@ fn connect_timeout_error() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn listen_localhost() {
|
||||
let socket_addr = next_test_ip4();
|
||||
let listener = t!(TcpListener::bind(&socket_addr));
|
||||
@ -73,6 +74,7 @@ fn listen_localhost() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn connect_loopback() {
|
||||
each_ip(&mut |addr| {
|
||||
let acceptor = t!(TcpListener::bind(&addr));
|
||||
@ -94,6 +96,7 @@ fn connect_loopback() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn smoke_test() {
|
||||
each_ip(&mut |addr| {
|
||||
let acceptor = t!(TcpListener::bind(&addr));
|
||||
@ -114,6 +117,7 @@ fn smoke_test() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn read_eof() {
|
||||
each_ip(&mut |addr| {
|
||||
let acceptor = t!(TcpListener::bind(&addr));
|
||||
@ -133,6 +137,7 @@ fn read_eof() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn write_close() {
|
||||
each_ip(&mut |addr| {
|
||||
let acceptor = t!(TcpListener::bind(&addr));
|
||||
@ -161,6 +166,7 @@ fn write_close() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn multiple_connect_serial() {
|
||||
each_ip(&mut |addr| {
|
||||
let max = 10;
|
||||
@ -183,6 +189,7 @@ fn multiple_connect_serial() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn multiple_connect_interleaved_greedy_schedule() {
|
||||
const MAX: usize = 10;
|
||||
each_ip(&mut |addr| {
|
||||
@ -220,6 +227,7 @@ fn multiple_connect_interleaved_greedy_schedule() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn multiple_connect_interleaved_lazy_schedule() {
|
||||
const MAX: usize = 10;
|
||||
each_ip(&mut |addr| {
|
||||
@ -255,6 +263,7 @@ fn multiple_connect_interleaved_lazy_schedule() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn socket_and_peer_name() {
|
||||
each_ip(&mut |addr| {
|
||||
let listener = t!(TcpListener::bind(&addr));
|
||||
@ -270,6 +279,7 @@ fn socket_and_peer_name() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn partial_read() {
|
||||
each_ip(&mut |addr| {
|
||||
let (tx, rx) = channel();
|
||||
@ -291,6 +301,7 @@ fn partial_read() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn read_buf() {
|
||||
each_ip(&mut |addr| {
|
||||
let srv = t!(TcpListener::bind(&addr));
|
||||
@ -389,6 +400,7 @@ fn double_bind() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn tcp_clone_smoke() {
|
||||
each_ip(&mut |addr| {
|
||||
let acceptor = t!(TcpListener::bind(&addr));
|
||||
@ -420,6 +432,7 @@ fn tcp_clone_smoke() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn tcp_clone_two_read() {
|
||||
each_ip(&mut |addr| {
|
||||
let acceptor = t!(TcpListener::bind(&addr));
|
||||
@ -454,6 +467,7 @@ fn tcp_clone_two_read() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn tcp_clone_two_write() {
|
||||
each_ip(&mut |addr| {
|
||||
let acceptor = t!(TcpListener::bind(&addr));
|
||||
@ -483,6 +497,7 @@ fn tcp_clone_two_write() {
|
||||
#[test]
|
||||
// FIXME: https://github.com/fortanix/rust-sgx/issues/110
|
||||
#[cfg_attr(target_env = "sgx", ignore)]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn shutdown_smoke() {
|
||||
each_ip(&mut |addr| {
|
||||
let a = t!(TcpListener::bind(&addr));
|
||||
@ -505,6 +520,7 @@ fn shutdown_smoke() {
|
||||
#[test]
|
||||
// FIXME: https://github.com/fortanix/rust-sgx/issues/110
|
||||
#[cfg_attr(target_env = "sgx", ignore)]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn close_readwrite_smoke() {
|
||||
each_ip(&mut |addr| {
|
||||
let a = t!(TcpListener::bind(&addr));
|
||||
@ -547,6 +563,7 @@ fn close_readwrite_smoke() {
|
||||
#[cfg_attr(target_env = "sgx", ignore)]
|
||||
// On windows, shutdown will not wake up blocking I/O operations.
|
||||
#[cfg_attr(windows, ignore)]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn close_read_wakes_up() {
|
||||
each_ip(&mut |addr| {
|
||||
let listener = t!(TcpListener::bind(&addr));
|
||||
@ -574,6 +591,7 @@ fn close_read_wakes_up() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn clone_while_reading() {
|
||||
each_ip(&mut |addr| {
|
||||
let accept = t!(TcpListener::bind(&addr));
|
||||
@ -614,6 +632,7 @@ fn clone_while_reading() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn clone_accept_smoke() {
|
||||
each_ip(&mut |addr| {
|
||||
let a = t!(TcpListener::bind(&addr));
|
||||
@ -632,6 +651,7 @@ fn clone_accept_smoke() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn clone_accept_concurrent() {
|
||||
each_ip(&mut |addr| {
|
||||
let a = t!(TcpListener::bind(&addr));
|
||||
@ -670,10 +690,10 @@ fn debug() {
|
||||
addr.to_string()
|
||||
}
|
||||
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
use crate::os::fd::AsRawFd;
|
||||
#[cfg(target_env = "sgx")]
|
||||
use crate::os::fortanix_sgx::io::AsRawFd;
|
||||
#[cfg(unix)]
|
||||
use crate::os::unix::io::AsRawFd;
|
||||
#[cfg(not(windows))]
|
||||
fn render_inner(addr: &dyn AsRawFd) -> impl fmt::Debug {
|
||||
addr.as_raw_fd()
|
||||
@ -714,6 +734,7 @@ fn debug() {
|
||||
ignore
|
||||
)]
|
||||
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // timeout not supported
|
||||
#[test]
|
||||
fn timeouts() {
|
||||
let addr = next_test_ip4();
|
||||
@ -742,6 +763,7 @@ fn timeouts() {
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // timeout not supported
|
||||
fn test_read_timeout() {
|
||||
let addr = next_test_ip4();
|
||||
let listener = t!(TcpListener::bind(&addr));
|
||||
@ -763,6 +785,7 @@ fn test_read_timeout() {
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // timeout not supported
|
||||
fn test_read_with_timeout() {
|
||||
let addr = next_test_ip4();
|
||||
let listener = t!(TcpListener::bind(&addr));
|
||||
@ -810,6 +833,7 @@ fn test_timeout_zero_duration() {
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_env = "sgx", ignore)]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // linger not supported
|
||||
fn linger() {
|
||||
let addr = next_test_ip4();
|
||||
let _listener = t!(TcpListener::bind(&addr));
|
||||
@ -879,6 +903,7 @@ fn set_nonblocking() {
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn peek() {
|
||||
each_ip(&mut |addr| {
|
||||
let (txdone, rxdone) = channel();
|
||||
|
@ -1,4 +1,12 @@
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx", target_os = "xous"))))]
|
||||
#[cfg(all(
|
||||
test,
|
||||
not(any(
|
||||
target_os = "emscripten",
|
||||
all(target_os = "wasi", target_env = "p1"),
|
||||
target_env = "sgx",
|
||||
target_os = "xous"
|
||||
))
|
||||
))]
|
||||
mod tests;
|
||||
|
||||
use crate::fmt;
|
||||
|
@ -27,6 +27,7 @@ fn bind_error() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn socket_smoke_test_ip4() {
|
||||
each_ip(&mut |server_ip, client_ip| {
|
||||
let (tx1, rx1) = channel();
|
||||
@ -69,6 +70,7 @@ fn socket_peer() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn udp_clone_smoke() {
|
||||
each_ip(&mut |addr1, addr2| {
|
||||
let sock1 = t!(UdpSocket::bind(&addr1));
|
||||
@ -98,6 +100,7 @@ fn udp_clone_smoke() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn udp_clone_two_read() {
|
||||
each_ip(&mut |addr1, addr2| {
|
||||
let sock1 = t!(UdpSocket::bind(&addr1));
|
||||
@ -130,6 +133,7 @@ fn udp_clone_two_read() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // no threads
|
||||
fn udp_clone_two_write() {
|
||||
each_ip(&mut |addr1, addr2| {
|
||||
let sock1 = t!(UdpSocket::bind(&addr1));
|
||||
@ -183,6 +187,7 @@ fn debug() {
|
||||
any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks", target_os = "nto"),
|
||||
ignore
|
||||
)]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // timeout not supported
|
||||
#[test]
|
||||
fn timeouts() {
|
||||
let addr = next_test_ip4();
|
||||
@ -208,6 +213,7 @@ fn timeouts() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // timeout not supported
|
||||
fn test_read_timeout() {
|
||||
let addr = next_test_ip4();
|
||||
|
||||
@ -232,6 +238,7 @@ fn test_read_timeout() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // timeout not supported
|
||||
fn test_read_with_timeout() {
|
||||
let addr = next_test_ip4();
|
||||
|
||||
@ -291,6 +298,7 @@ fn connect_send_recv() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // peek not supported
|
||||
fn connect_send_peek_recv() {
|
||||
each_ip(&mut |addr, _| {
|
||||
let socket = t!(UdpSocket::bind(&addr));
|
||||
@ -313,6 +321,7 @@ fn connect_send_peek_recv() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "wasi", ignore)] // peek_from not supported
|
||||
fn peek_from() {
|
||||
each_ip(&mut |addr, _| {
|
||||
let socket = t!(UdpSocket::bind(&addr));
|
||||
|
@ -139,7 +139,7 @@ fn test_pathbuf_leak() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
pub fn test_decompositions_unix() {
|
||||
t!("",
|
||||
iter: [],
|
||||
@ -1201,7 +1201,10 @@ pub fn test_push() {
|
||||
});
|
||||
);
|
||||
|
||||
if cfg!(unix) || cfg!(all(target_env = "sgx", target_vendor = "fortanix")) {
|
||||
if cfg!(unix)
|
||||
|| cfg!(target_os = "wasi")
|
||||
|| cfg!(all(target_env = "sgx", target_vendor = "fortanix"))
|
||||
{
|
||||
tp!("", "foo", "foo");
|
||||
tp!("foo", "bar", "foo/bar");
|
||||
tp!("foo/", "bar", "foo/bar");
|
||||
@ -1358,7 +1361,10 @@ pub fn test_set_file_name() {
|
||||
tfn!("foo", "bar", "bar");
|
||||
tfn!("foo", "", "");
|
||||
tfn!("", "foo", "foo");
|
||||
if cfg!(unix) || cfg!(all(target_env = "sgx", target_vendor = "fortanix")) {
|
||||
if cfg!(unix)
|
||||
|| cfg!(target_os = "wasi")
|
||||
|| cfg!(all(target_env = "sgx", target_vendor = "fortanix"))
|
||||
{
|
||||
tfn!(".", "foo", "./foo");
|
||||
tfn!("foo/", "bar", "bar");
|
||||
tfn!("foo/.", "bar", "bar");
|
||||
@ -1758,7 +1764,7 @@ fn test_components_debug() {
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
#[test]
|
||||
fn test_iter_debug() {
|
||||
let path = Path::new("/tmp");
|
||||
@ -1859,7 +1865,7 @@ fn test_ord() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
fn test_unix_absolute() {
|
||||
use crate::path::absolute;
|
||||
|
||||
|
@ -148,7 +148,15 @@
|
||||
#![stable(feature = "process", since = "1.0.0")]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx", target_os = "xous"))))]
|
||||
#[cfg(all(
|
||||
test,
|
||||
not(any(
|
||||
target_os = "emscripten",
|
||||
target_os = "wasi",
|
||||
target_env = "sgx",
|
||||
target_os = "xous"
|
||||
))
|
||||
))]
|
||||
mod tests;
|
||||
|
||||
use crate::convert::Infallible;
|
||||
|
@ -3,7 +3,7 @@ use crate::sync::{Arc, Barrier};
|
||||
use crate::thread;
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
fn test_barrier() {
|
||||
const N: usize = 10;
|
||||
|
||||
|
@ -12,7 +12,7 @@ fn smoke() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
fn notify_one() {
|
||||
let m = Arc::new(Mutex::new(()));
|
||||
let m2 = m.clone();
|
||||
@ -29,7 +29,7 @@ fn notify_one() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
fn notify_all() {
|
||||
const N: usize = 10;
|
||||
|
||||
@ -66,7 +66,7 @@ fn notify_all() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
fn wait_while() {
|
||||
let pair = Arc::new((Mutex::new(false), Condvar::new()));
|
||||
let pair2 = pair.clone();
|
||||
@ -87,7 +87,7 @@ fn wait_while() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // condvar wait not supported
|
||||
fn wait_timeout_wait() {
|
||||
let m = Arc::new(Mutex::new(()));
|
||||
let c = Arc::new(Condvar::new());
|
||||
@ -106,7 +106,7 @@ fn wait_timeout_wait() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // condvar wait not supported
|
||||
fn wait_timeout_while_wait() {
|
||||
let m = Arc::new(Mutex::new(()));
|
||||
let c = Arc::new(Condvar::new());
|
||||
@ -118,7 +118,7 @@ fn wait_timeout_while_wait() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // condvar wait not supported
|
||||
fn wait_timeout_while_instant_satisfy() {
|
||||
let m = Arc::new(Mutex::new(()));
|
||||
let c = Arc::new(Condvar::new());
|
||||
@ -130,7 +130,7 @@ fn wait_timeout_while_instant_satisfy() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
fn wait_timeout_while_wake() {
|
||||
let pair = Arc::new((Mutex::new(false), Condvar::new()));
|
||||
let pair_copy = pair.clone();
|
||||
@ -153,7 +153,7 @@ fn wait_timeout_while_wake() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
fn wait_timeout_wake() {
|
||||
let m = Arc::new(Mutex::new(()));
|
||||
let c = Arc::new(Condvar::new());
|
||||
|
@ -34,6 +34,7 @@ fn lazy_default() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
|
||||
fn lazy_poisoning() {
|
||||
let x: LazyCell<String> = LazyCell::new(|| panic!("kaboom"));
|
||||
for _ in 0..2 {
|
||||
@ -43,7 +44,7 @@ fn lazy_poisoning() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
fn sync_lazy_new() {
|
||||
static CALLED: AtomicUsize = AtomicUsize::new(0);
|
||||
static SYNC_LAZY: LazyLock<i32> = LazyLock::new(|| {
|
||||
@ -90,7 +91,7 @@ fn sync_lazy_default() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
fn static_sync_lazy() {
|
||||
static XS: LazyLock<Vec<i32>> = LazyLock::new(|| {
|
||||
let mut xs = Vec::new();
|
||||
@ -123,6 +124,7 @@ fn static_sync_lazy_via_fn() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
|
||||
fn sync_lazy_poisoning() {
|
||||
let x: LazyLock<String> = LazyLock::new(|| panic!("kaboom"));
|
||||
for _ in 0..2 {
|
||||
|
@ -137,10 +137,10 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))]
|
||||
mod tests;
|
||||
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))]
|
||||
mod sync_tests;
|
||||
|
||||
// MPSC channels are built as a wrapper around MPMC channels, which
|
||||
|
@ -1,4 +1,4 @@
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))]
|
||||
mod tests;
|
||||
|
||||
use crate::cell::UnsafeCell;
|
||||
|
@ -3,7 +3,7 @@
|
||||
//! This primitive is meant to be used to run one-time initialization. An
|
||||
//! example use case would be for initializing an FFI library.
|
||||
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))]
|
||||
mod tests;
|
||||
|
||||
use crate::fmt;
|
||||
|
@ -9,7 +9,7 @@ fn spawn_and_wait<R: Send + 'static>(f: impl FnOnce() -> R + Send + 'static) ->
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
fn sync_once_cell() {
|
||||
static ONCE_CELL: OnceLock<i32> = OnceLock::new();
|
||||
|
||||
@ -43,7 +43,7 @@ fn sync_once_cell_get_unchecked() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
fn sync_once_cell_drop() {
|
||||
static DROP_CNT: AtomicUsize = AtomicUsize::new(0);
|
||||
struct Dropper;
|
||||
@ -81,6 +81,7 @@ fn clone() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
|
||||
fn get_or_try_init() {
|
||||
let cell: OnceLock<String> = OnceLock::new();
|
||||
assert!(cell.get().is_none());
|
||||
@ -154,7 +155,7 @@ fn eval_once_macro() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
fn sync_once_cell_does_not_leak_partially_constructed_boxes() {
|
||||
static ONCE_CELL: OnceLock<String> = OnceLock::new();
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))]
|
||||
mod tests;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))]
|
||||
mod tests;
|
||||
|
||||
use crate::cell::UnsafeCell;
|
||||
|
@ -20,7 +20,6 @@ pub mod futex;
|
||||
#[path = "../wasi/io.rs"]
|
||||
pub mod io;
|
||||
|
||||
#[path = "../wasi/net.rs"]
|
||||
pub mod net;
|
||||
#[path = "../wasi/os.rs"]
|
||||
pub mod os;
|
||||
|
379
library/std/src/sys/pal/wasip2/net.rs
Normal file
379
library/std/src/sys/pal/wasip2/net.rs
Normal file
@ -0,0 +1,379 @@
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
use libc::{c_int, c_void, size_t};
|
||||
|
||||
use super::fd::WasiFd;
|
||||
use crate::ffi::CStr;
|
||||
use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut};
|
||||
use crate::net::{Shutdown, SocketAddr};
|
||||
use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use crate::sys::unsupported;
|
||||
use crate::sys_common::net::{TcpListener, getsockopt, setsockopt, sockaddr_to_addr};
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
use crate::time::{Duration, Instant};
|
||||
use crate::{cmp, mem, str};
|
||||
|
||||
pub extern crate libc as netc;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type wrlen_t = size_t;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait IsMinusOne {
|
||||
fn is_minus_one(&self) -> bool;
|
||||
}
|
||||
|
||||
macro_rules! impl_is_minus_one {
|
||||
($($t:ident)*) => ($(impl IsMinusOne for $t {
|
||||
fn is_minus_one(&self) -> bool {
|
||||
*self == -1
|
||||
}
|
||||
})*)
|
||||
}
|
||||
|
||||
impl_is_minus_one! { i8 i16 i32 i64 isize }
|
||||
|
||||
pub fn cvt<T: IsMinusOne>(t: T) -> crate::io::Result<T> {
|
||||
if t.is_minus_one() { Err(crate::io::Error::last_os_error()) } else { Ok(t) }
|
||||
}
|
||||
|
||||
pub fn cvt_r<T, F>(mut f: F) -> crate::io::Result<T>
|
||||
where
|
||||
T: IsMinusOne,
|
||||
F: FnMut() -> T,
|
||||
{
|
||||
loop {
|
||||
match cvt(f()) {
|
||||
Err(ref e) if e.is_interrupted() => {}
|
||||
other => return other,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cvt_gai(err: c_int) -> io::Result<()> {
|
||||
if err == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if err == netc::EAI_SYSTEM {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
let detail = unsafe {
|
||||
str::from_utf8(CStr::from_ptr(netc::gai_strerror(err)).to_bytes()).unwrap().to_owned()
|
||||
};
|
||||
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::Uncategorized,
|
||||
&format!("failed to lookup address information: {detail}")[..],
|
||||
))
|
||||
}
|
||||
|
||||
pub fn init() {}
|
||||
|
||||
pub struct Socket(WasiFd);
|
||||
|
||||
impl Socket {
|
||||
pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> {
|
||||
let fam = match *addr {
|
||||
SocketAddr::V4(..) => netc::AF_INET,
|
||||
SocketAddr::V6(..) => netc::AF_INET6,
|
||||
};
|
||||
Socket::new_raw(fam, ty)
|
||||
}
|
||||
|
||||
pub fn new_raw(fam: c_int, ty: c_int) -> io::Result<Socket> {
|
||||
let fd = cvt(unsafe { netc::socket(fam, ty, 0) })?;
|
||||
Ok(unsafe { Self::from_raw_fd(fd) })
|
||||
}
|
||||
|
||||
pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
|
||||
let (addr, len) = addr.into_inner();
|
||||
cvt_r(|| unsafe { netc::connect(self.as_raw_fd(), addr.as_ptr(), len) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
|
||||
self.set_nonblocking(true)?;
|
||||
let r = self.connect(addr);
|
||||
self.set_nonblocking(false)?;
|
||||
|
||||
match r {
|
||||
Ok(_) => return Ok(()),
|
||||
// there's no ErrorKind for EINPROGRESS
|
||||
Err(ref e) if e.raw_os_error() == Some(netc::EINPROGRESS) => {}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
|
||||
let mut pollfd = netc::pollfd { fd: self.as_raw_fd(), events: netc::POLLOUT, revents: 0 };
|
||||
|
||||
if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
|
||||
return Err(io::Error::ZERO_TIMEOUT);
|
||||
}
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
loop {
|
||||
let elapsed = start.elapsed();
|
||||
if elapsed >= timeout {
|
||||
return Err(io::const_io_error!(io::ErrorKind::TimedOut, "connection timed out"));
|
||||
}
|
||||
|
||||
let timeout = timeout - elapsed;
|
||||
let mut timeout = timeout
|
||||
.as_secs()
|
||||
.saturating_mul(1_000)
|
||||
.saturating_add(timeout.subsec_nanos() as u64 / 1_000_000);
|
||||
if timeout == 0 {
|
||||
timeout = 1;
|
||||
}
|
||||
|
||||
let timeout = cmp::min(timeout, c_int::MAX as u64) as c_int;
|
||||
|
||||
match unsafe { netc::poll(&mut pollfd, 1, timeout) } {
|
||||
-1 => {
|
||||
let err = io::Error::last_os_error();
|
||||
if !err.is_interrupted() {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
0 => {}
|
||||
_ => {
|
||||
// WASI poll does not return POLLHUP or POLLERR in revents. Check if the
|
||||
// connnection actually succeeded and return ok only when the socket is
|
||||
// ready and no errors were found.
|
||||
if let Some(e) = self.take_error()? {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn accept(
|
||||
&self,
|
||||
storage: *mut netc::sockaddr,
|
||||
len: *mut netc::socklen_t,
|
||||
) -> io::Result<Socket> {
|
||||
let fd = cvt_r(|| unsafe { netc::accept(self.as_raw_fd(), storage, len) })?;
|
||||
Ok(unsafe { Self::from_raw_fd(fd) })
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<Socket> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
fn recv_with_flags(&self, mut buf: BorrowedCursor<'_>, flags: c_int) -> io::Result<()> {
|
||||
let ret = cvt(unsafe {
|
||||
netc::recv(
|
||||
self.as_raw_fd(),
|
||||
buf.as_mut().as_mut_ptr() as *mut c_void,
|
||||
buf.capacity(),
|
||||
flags,
|
||||
)
|
||||
})?;
|
||||
unsafe {
|
||||
buf.advance_unchecked(ret as usize);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let mut buf = BorrowedBuf::from(buf);
|
||||
self.recv_with_flags(buf.unfilled(), 0)?;
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let mut buf = BorrowedBuf::from(buf);
|
||||
self.recv_with_flags(buf.unfilled(), netc::MSG_PEEK)?;
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
self.recv_with_flags(buf, 0)
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
io::default_read_vectored(|b| self.read(b), bufs)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn recv_from_with_flags(
|
||||
&self,
|
||||
buf: &mut [u8],
|
||||
flags: c_int,
|
||||
) -> io::Result<(usize, SocketAddr)> {
|
||||
let mut storage: netc::sockaddr_storage = unsafe { mem::zeroed() };
|
||||
let mut addrlen = mem::size_of_val(&storage) as netc::socklen_t;
|
||||
|
||||
let n = cvt(unsafe {
|
||||
netc::recvfrom(
|
||||
self.as_raw_fd(),
|
||||
buf.as_mut_ptr() as *mut c_void,
|
||||
buf.len(),
|
||||
flags,
|
||||
core::ptr::addr_of_mut!(storage) as *mut _,
|
||||
&mut addrlen,
|
||||
)
|
||||
})?;
|
||||
Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?))
|
||||
}
|
||||
|
||||
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
||||
self.recv_from_with_flags(buf, 0)
|
||||
}
|
||||
|
||||
pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
||||
self.recv_from_with_flags(buf, netc::MSG_PEEK)
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
|
||||
let ret = cvt(unsafe {
|
||||
netc::send(self.as_raw(), buf.as_ptr() as *const c_void, len, netc::MSG_NOSIGNAL)
|
||||
})?;
|
||||
Ok(ret as usize)
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
io::default_write_vectored(|b| self.write(b), bufs)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn set_timeout(&self, dur: Option<Duration>, kind: c_int) -> io::Result<()> {
|
||||
let timeout = match dur {
|
||||
Some(dur) => {
|
||||
if dur.as_secs() == 0 && dur.subsec_nanos() == 0 {
|
||||
return Err(io::Error::ZERO_TIMEOUT);
|
||||
}
|
||||
|
||||
let secs = dur.as_secs().try_into().unwrap_or(netc::time_t::MAX);
|
||||
let mut timeout = netc::timeval {
|
||||
tv_sec: secs,
|
||||
tv_usec: dur.subsec_micros() as netc::suseconds_t,
|
||||
};
|
||||
if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
|
||||
timeout.tv_usec = 1;
|
||||
}
|
||||
timeout
|
||||
}
|
||||
None => netc::timeval { tv_sec: 0, tv_usec: 0 },
|
||||
};
|
||||
setsockopt(self, netc::SOL_SOCKET, kind, timeout)
|
||||
}
|
||||
|
||||
pub fn timeout(&self, kind: c_int) -> io::Result<Option<Duration>> {
|
||||
let raw: netc::timeval = getsockopt(self, netc::SOL_SOCKET, kind)?;
|
||||
if raw.tv_sec == 0 && raw.tv_usec == 0 {
|
||||
Ok(None)
|
||||
} else {
|
||||
let sec = raw.tv_sec as u64;
|
||||
let nsec = (raw.tv_usec as u32) * 1000;
|
||||
Ok(Some(Duration::new(sec, nsec)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
|
||||
let how = match how {
|
||||
Shutdown::Write => netc::SHUT_WR,
|
||||
Shutdown::Read => netc::SHUT_RD,
|
||||
Shutdown::Both => netc::SHUT_RDWR,
|
||||
};
|
||||
cvt(unsafe { netc::shutdown(self.as_raw_fd(), how) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_linger(&self, _linger: Option<Duration>) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn linger(&self) -> io::Result<Option<Duration>> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
|
||||
setsockopt(self, netc::IPPROTO_TCP, netc::TCP_NODELAY, nodelay as c_int)
|
||||
}
|
||||
|
||||
pub fn nodelay(&self) -> io::Result<bool> {
|
||||
let raw: c_int = getsockopt(self, netc::IPPROTO_TCP, netc::TCP_NODELAY)?;
|
||||
Ok(raw != 0)
|
||||
}
|
||||
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
|
||||
let mut nonblocking = nonblocking as c_int;
|
||||
cvt(unsafe { netc::ioctl(self.as_raw_fd(), netc::FIONBIO, &mut nonblocking) }).map(drop)
|
||||
}
|
||||
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||
let raw: c_int = getsockopt(self, netc::SOL_SOCKET, netc::SO_ERROR)?;
|
||||
if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) }
|
||||
}
|
||||
|
||||
// This is used by sys_common code to abstract over Windows and Unix.
|
||||
pub fn as_raw(&self) -> RawFd {
|
||||
self.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<WasiFd> for Socket {
|
||||
#[inline]
|
||||
fn as_inner(&self) -> &WasiFd {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<WasiFd> for Socket {
|
||||
fn into_inner(self) -> WasiFd {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<WasiFd> for Socket {
|
||||
fn from_inner(inner: WasiFd) -> Socket {
|
||||
Socket(inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for Socket {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.0.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for Socket {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.0.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for Socket {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.0.into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for Socket {
|
||||
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
|
||||
unsafe { Self(FromRawFd::from_raw_fd(raw_fd)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<Socket> for TcpListener {
|
||||
#[inline]
|
||||
fn as_inner(&self) -> &Socket {
|
||||
&self.socket()
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
pub const DEFAULT_BUF_SIZE: usize = if cfg!(target_os = "espidf") { 512 } else { 8 * 1024 };
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(dead_code)] // not used on emscripten
|
||||
#[allow(dead_code)] // not used on emscripten and wasi
|
||||
pub mod test {
|
||||
use rand::RngCore;
|
||||
|
||||
|
@ -32,7 +32,8 @@ cfg_if::cfg_if! {
|
||||
all(unix, not(target_os = "l4re")),
|
||||
windows,
|
||||
target_os = "hermit",
|
||||
target_os = "solid_asp3"
|
||||
target_os = "solid_asp3",
|
||||
all(target_os = "wasi", target_env = "p2")
|
||||
))] {
|
||||
pub mod net;
|
||||
} else {
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#![unstable(feature = "thread_local_internals", issue = "none")]
|
||||
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))]
|
||||
mod tests;
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -155,7 +155,7 @@
|
||||
// Under `test`, `__FastLocalKeyInner` seems unused.
|
||||
#![cfg_attr(test, allow(dead_code))]
|
||||
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))]
|
||||
mod tests;
|
||||
|
||||
use crate::any::Any;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#![cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx"))))]
|
||||
#![cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi", target_env = "sgx"))))]
|
||||
|
||||
//! Note that this test changes the current directory so
|
||||
//! should not be in the same process as other tests.
|
||||
|
@ -5,7 +5,7 @@ use std::{env, fs, process, str};
|
||||
mod common;
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore)] // Process spawning not supported by Miri
|
||||
#[cfg_attr(any(miri, target_os = "wasi"), ignore)] // Process spawning not supported by Miri and wasi
|
||||
fn issue_15149() {
|
||||
// If we're the parent, copy our own binary to a new directory.
|
||||
let my_path = env::current_exe().unwrap();
|
||||
|
@ -4,7 +4,7 @@ use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
#[cfg_attr(miri, ignore)] // Miri does not like the thread leak
|
||||
fn sleep_very_long() {
|
||||
let finished = Arc::new(Mutex::new(false));
|
||||
|
@ -1370,7 +1370,7 @@ Executed at: {executed_at}"#,
|
||||
}
|
||||
|
||||
if target.starts_with("wasm") && target.contains("wasi") {
|
||||
self.default_wasi_runner()
|
||||
self.default_wasi_runner(target)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -1379,7 +1379,7 @@ Executed at: {executed_at}"#,
|
||||
/// When a `runner` configuration is not provided and a WASI-looking target
|
||||
/// is being tested this is consulted to prove the environment to see if
|
||||
/// there's a runtime already lying around that seems reasonable to use.
|
||||
fn default_wasi_runner(&self) -> Option<String> {
|
||||
fn default_wasi_runner(&self, target: TargetSelection) -> Option<String> {
|
||||
let mut finder = crate::core::sanity::Finder::new();
|
||||
|
||||
// Look for Wasmtime, and for its default options be sure to disable
|
||||
@ -1395,6 +1395,11 @@ Executed at: {executed_at}"#,
|
||||
// inherit the entire environment rather than just this single
|
||||
// environment variable.
|
||||
path.push_str(" --env RUSTC_BOOTSTRAP");
|
||||
|
||||
if target.contains("wasip2") {
|
||||
path.push_str(" --wasi inherit-network --wasi allow-ip-name-lookup");
|
||||
}
|
||||
|
||||
return Some(path);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user