Skip to content

Commit

Permalink
Implement the tcp interface of wasi-sockets. (#6837)
Browse files Browse the repository at this point in the history
* Implement the `tcp` interface of wasi-sockets.

Implement the `tcp`, `tcp-create-socket`, and `network` interfaces of
wasi-sockets.

* Minor cleanups.

* Update to the latest upstream wasi-sockets.

* Address review feedback.

* Handle zero-length reads and writes, and other cleanups.

* Fix compilation on macOS.

* Fix compilation on Windows.

* Update all the copies of wasi-socket wit files.

* Sync up more wit files.

* Fix the errno code for non-blocking `connect` on Windows.

prtest:full

* Tolerate `NOTCONN` errors when cleaning up with `shutdown`.

* Simplify the polling mechanism.

This requires an updated tokio for `Interest::ERROR`.

* Downgrade to tokio 1.29.1 for now.

* Move `tcp_state` out of the `Arc`.

* `accept` doesn't need a write lock.

* Remove `tcp_state`'s `RwLock`.
  • Loading branch information
sunfishcode authored Aug 22, 2023
1 parent 819fad0 commit 2f6e977
Show file tree
Hide file tree
Showing 39 changed files with 1,827 additions and 252 deletions.
64 changes: 43 additions & 21 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ members = [
"crates/jit-icache-coherence",
"crates/test-programs/wasi-tests",
"crates/test-programs/wasi-http-tests",
"crates/test-programs/wasi-sockets-tests",
"crates/test-programs/command-tests",
"crates/test-programs/reactor-tests",
"crates/wmemcheck",
Expand Down Expand Up @@ -191,13 +192,14 @@ target-lexicon = { version = "0.12.3", default-features = false, features = ["st
cap-std = "2.0.0"
cap-rand = { version = "2.0.0", features = ["small_rng"] }
cap-fs-ext = "2.0.0"
cap-net-ext = "2.0.0"
cap-time-ext = "2.0.0"
cap-tempfile = "2.0.0"
fs-set-times = "0.20.0"
system-interface = { version = "0.26.0", features = ["cap_std_impls"] }
io-lifetimes = { version = "2.0.2", default-features = false }
io-extras = "0.18.0"
rustix = "0.38.4"
rustix = "0.38.8"
is-terminal = "0.4.0"
# wit-bindgen:
wit-bindgen = { version = "0.9.0", default-features = false }
Expand Down
10 changes: 10 additions & 0 deletions crates/test-programs/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ fn build_and_generate_tests() {
println!("cargo:rerun-if-changed=./wasi-tests");
println!("cargo:rerun-if-changed=./command-tests");
println!("cargo:rerun-if-changed=./reactor-tests");
println!("cargo:rerun-if-changed=./wasi-sockets-tests");
if BUILD_WASI_HTTP_TESTS {
println!("cargo:rerun-if-changed=./wasi-http-tests");
} else {
Expand All @@ -43,6 +44,7 @@ fn build_and_generate_tests() {
.arg("--package=wasi-tests")
.arg("--package=command-tests")
.arg("--package=reactor-tests")
.arg("--package=wasi-sockets-tests")
.env("CARGO_TARGET_DIR", &out_dir)
.env("CARGO_PROFILE_DEV_DEBUG", "1")
.env_remove("CARGO_ENCODED_RUSTFLAGS");
Expand All @@ -64,6 +66,14 @@ fn build_and_generate_tests() {

components_rs(&meta, "command-tests", "bin", &command_adapter, &out_dir);
components_rs(&meta, "reactor-tests", "cdylib", &reactor_adapter, &out_dir);

components_rs(
&meta,
"wasi-sockets-tests",
"bin",
&command_adapter,
&out_dir,
);
}

// Creates an `${out_dir}/${package}_modules.rs` file that exposes a `get_module(&str) -> Module`,
Expand Down
93 changes: 93 additions & 0 deletions crates/test-programs/tests/wasi-sockets.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#![cfg(all(feature = "test_programs", not(skip_wasi_sockets_tests)))]
use cap_std::ambient_authority;
use wasmtime::component::Linker;
use wasmtime::{Config, Engine, Store};
use wasmtime_wasi::preview2::{self, command::Command, Table, WasiCtx, WasiCtxBuilder, WasiView};

lazy_static::lazy_static! {
static ref ENGINE: Engine = {
let mut config = Config::new();
config.wasm_backtrace_details(wasmtime::WasmBacktraceDetails::Enable);
config.wasm_component_model(true);
config.async_support(true);

let engine = Engine::new(&config).unwrap();
engine
};
}
// uses ENGINE, creates a fn get_component(&str) -> Component
include!(concat!(
env!("OUT_DIR"),
"/wasi_sockets_tests_components.rs"
));

struct SocketsCtx {
table: Table,
wasi: WasiCtx,
}

impl WasiView for SocketsCtx {
fn table(&self) -> &Table {
&self.table
}
fn table_mut(&mut self) -> &mut Table {
&mut self.table
}
fn ctx(&self) -> &WasiCtx {
&self.wasi
}
fn ctx_mut(&mut self) -> &mut WasiCtx {
&mut self.wasi
}
}

async fn run(name: &str) -> anyhow::Result<()> {
let component = get_component(name);
let mut linker = Linker::new(&ENGINE);

preview2::bindings::io::streams::add_to_linker(&mut linker, |x| x)?;
preview2::bindings::poll::poll::add_to_linker(&mut linker, |x| x)?;
preview2::bindings::cli::exit::add_to_linker(&mut linker, |x| x)?;
preview2::bindings::cli::stdin::add_to_linker(&mut linker, |x| x)?;
preview2::bindings::cli::stdout::add_to_linker(&mut linker, |x| x)?;
preview2::bindings::cli::stderr::add_to_linker(&mut linker, |x| x)?;
preview2::bindings::cli::terminal_input::add_to_linker(&mut linker, |x| x)?;
preview2::bindings::cli::terminal_output::add_to_linker(&mut linker, |x| x)?;
preview2::bindings::cli::terminal_stdin::add_to_linker(&mut linker, |x| x)?;
preview2::bindings::cli::terminal_stdout::add_to_linker(&mut linker, |x| x)?;
preview2::bindings::cli::terminal_stderr::add_to_linker(&mut linker, |x| x)?;
preview2::bindings::cli::environment::add_to_linker(&mut linker, |x| x)?;
preview2::bindings::filesystem::types::add_to_linker(&mut linker, |x| x)?;
preview2::bindings::filesystem::preopens::add_to_linker(&mut linker, |x| x)?;
preview2::bindings::sockets::tcp::add_to_linker(&mut linker, |x| x)?;
preview2::bindings::sockets::tcp_create_socket::add_to_linker(&mut linker, |x| x)?;
preview2::bindings::sockets::network::add_to_linker(&mut linker, |x| x)?;
preview2::bindings::sockets::instance_network::add_to_linker(&mut linker, |x| x)?;

// Create our wasi context.
let mut table = Table::new();
let wasi = WasiCtxBuilder::new()
.inherit_stdio()
.inherit_network(ambient_authority())
.arg(name)
.build(&mut table)?;

let mut store = Store::new(&ENGINE, SocketsCtx { table, wasi });

let (command, _instance) = Command::instantiate_async(&mut store, &component, &linker).await?;
command
.wasi_cli_run()
.call_run(&mut store)
.await?
.map_err(|()| anyhow::anyhow!("command returned with failing exit status"))
}

#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn tcp_v4() {
run("tcp_v4").await.unwrap();
}

#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn tcp_v6() {
run("tcp_v6").await.unwrap();
}
10 changes: 10 additions & 0 deletions crates/test-programs/wasi-sockets-tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "wasi-sockets-tests"
version = "0.0.0"
readme = "README.md"
edition = "2021"
publish = false

[dependencies]
anyhow = { workspace = true }
wit-bindgen = { workspace = true, default-features = false, features = ["macros"] }
Loading

0 comments on commit 2f6e977

Please sign in to comment.