From 77e8646e8c03ef994353e714c5cdf88a5b3a40c5 Mon Sep 17 00:00:00 2001 From: Erik Chi Date: Sat, 21 Oct 2023 12:33:22 -0400 Subject: [PATCH 1/6] make the library code safer -- no panics etc --- crates/water/src/runtime/core.rs | 4 ++-- crates/water/src/runtime/stream.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/water/src/runtime/core.rs b/crates/water/src/runtime/core.rs index 4dc653f..3cc81d3 100644 --- a/crates/water/src/runtime/core.rs +++ b/crates/water/src/runtime/core.rs @@ -54,7 +54,7 @@ impl H2O { // store.data_mut().preview1_ctx = Some(WasiCtxBuilder::new().inherit_stdio().preopened_dir(path, ".")?.build()); store.data_mut().preview1_ctx = Some(WasiCtxBuilder::new().inherit_stdio().build()); - wasmtime_wasi::add_to_linker(&mut linker, |h: &mut Host| h.preview1_ctx.as_mut().unwrap())?; + wasmtime_wasi::add_to_linker(&mut linker, |h: &mut Host| h.preview1_ctx.as_mut().context("Failed to retrieve preview1_ctx from Host")?)?; // initializing stuff for multithreading #[cfg(feature = "multithread")] @@ -65,7 +65,7 @@ impl H2O { )?)); wasmtime_wasi_threads::add_to_linker(&mut linker, &store, &module, |h: &mut Host| { - h.wasi_threads.as_ref().unwrap() + h.wasi_threads.as_ref().context("Failed to get ref of wasi_threads from Host")? })?; } diff --git a/crates/water/src/runtime/stream.rs b/crates/water/src/runtime/stream.rs index b0d151c..b382a06 100644 --- a/crates/water/src/runtime/stream.rs +++ b/crates/water/src/runtime/stream.rs @@ -168,7 +168,7 @@ impl WATERStream { std::mem::forget(water_io); // forget the water_io, so that it won't be closed - let ctx = core.store.data_mut().preview1_ctx.as_mut().unwrap(); + let ctx = core.store.data_mut().preview1_ctx.as_mut().context("Failed to retrieve preview1_ctx from Host")?; let water_io_fd = ctx.push_file(Box::new(water_io_file), FileAccessMode::all())?; let water_bridging = match core.instance.get_func(&mut core.store, WATER_BRIDGING_FN) { From e9b037103c76ce2e81cff5a3eab713d9cdd37eb0 Mon Sep 17 00:00:00 2001 From: Erik Chi Date: Sun, 22 Oct 2023 15:37:28 -0400 Subject: [PATCH 2/6] match testing branch updates --- .github/workflows/rust.yml | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 46371a6..16222df 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -33,7 +33,7 @@ jobs: run: cargo clippy --workspace --all-targets --verbose --all-features build: - name: Test and Build + name: Test and Build WASM needs: format # needs: [format, lint] strategy: @@ -45,7 +45,31 @@ jobs: steps: - uses: actions/checkout@v3 + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + + # Build for WATER host + - name: Build WATER Host crate + run: cargo build + working-directory: crates/water + + # install wasm32-wasi target + - name: Add wasm32-wasi target + run: rustup target add wasm32-wasi + + # Build for wasm32-wasi target + - name: Build wasm32-wasi Target + run: | + for member in crates/wasm/ examples/water_bins/ss_client_wasm_v1/ examples/water_bins/echo_client/; do + cargo build --verbose --manifest-path $member/Cargo.toml --target wasm32-wasi + done + env: + RUSTFLAGS: --cfg tokio_unstable + - name: Test run: cargo test --verbose --workspace --all-features - - name: Build - run: cargo build --verbose From f6980c2d831361e6a54dab3b94ddf39edb201bad Mon Sep 17 00:00:00 2001 From: Jack Wampler Date: Fri, 20 Oct 2023 12:00:33 -0600 Subject: [PATCH 3/6] update: match all commits from testing branch --- Cargo.toml | 2 +- README.md | 11 +++ crates/{water_wasm => wasm}/Cargo.toml | 0 crates/{water_wasm => wasm}/src/config.rs | 0 .../{water_wasm => wasm}/src/connections.rs | 0 crates/{water_wasm => wasm}/src/decoder.rs | 0 crates/{water_wasm => wasm}/src/dialer.rs | 0 crates/{water_wasm => wasm}/src/encoder.rs | 0 crates/{water_wasm => wasm}/src/lib.rs | 0 crates/{water_wasm => wasm}/src/listener.rs | 0 crates/{water_wasm => wasm}/src/net/mod.rs | 0 crates/{water_wasm => wasm}/src/net/tls.rs | 0 crates/{water_wasm => wasm}/src/v1/README.md | 0 .../src/v1/async_listener_v1.rs | 0 .../{water_wasm => wasm}/src/v1/config_v1.rs | 0 crates/{water_wasm => wasm}/src/v1/dial_v1.rs | 0 crates/{water_wasm => wasm}/src/v1/mod.rs | 0 crates/{water_wasm => wasm}/src/version.rs | 0 examples/clients/cli/Cargo.toml | 2 +- examples/water_bins/echo_client/Cargo.toml | 2 +- .../water_bins/ss_client_wasm_v1/Cargo.toml | 2 +- tests/Cargo.toml | 18 ++++ tests/{ => benches}/benchmarking_v0.rs | 90 +++++++++++-------- tests/{SS_testing.rs => tests/ss_testing.rs} | 61 +++++++------ 24 files changed, 114 insertions(+), 74 deletions(-) rename crates/{water_wasm => wasm}/Cargo.toml (100%) rename crates/{water_wasm => wasm}/src/config.rs (100%) rename crates/{water_wasm => wasm}/src/connections.rs (100%) rename crates/{water_wasm => wasm}/src/decoder.rs (100%) rename crates/{water_wasm => wasm}/src/dialer.rs (100%) rename crates/{water_wasm => wasm}/src/encoder.rs (100%) rename crates/{water_wasm => wasm}/src/lib.rs (100%) rename crates/{water_wasm => wasm}/src/listener.rs (100%) rename crates/{water_wasm => wasm}/src/net/mod.rs (100%) rename crates/{water_wasm => wasm}/src/net/tls.rs (100%) rename crates/{water_wasm => wasm}/src/v1/README.md (100%) rename crates/{water_wasm => wasm}/src/v1/async_listener_v1.rs (100%) rename crates/{water_wasm => wasm}/src/v1/config_v1.rs (100%) rename crates/{water_wasm => wasm}/src/v1/dial_v1.rs (100%) rename crates/{water_wasm => wasm}/src/v1/mod.rs (100%) rename crates/{water_wasm => wasm}/src/version.rs (100%) create mode 100644 tests/Cargo.toml rename tests/{ => benches}/benchmarking_v0.rs (88%) rename tests/{SS_testing.rs => tests/ss_testing.rs} (83%) diff --git a/Cargo.toml b/Cargo.toml index 74085b6..f3c178f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] -members = ["crates/*", "examples/water_bins/*", "examples/clients/*"] +members = ["crates/*", "examples/water_bins/*", "examples/clients/*", "tests"] # exclude = ["crates/foo", "path/to/other"] default-members = ["crates/*"] resolver="2" diff --git a/README.md b/README.md index 59e6b9b..b6dd5d8 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,17 @@ nc 127.0.0.1 9005 ``` you should see `> CONNECTED` in the terminal of running WASM, then you can connect a bunch like this and input anything to see how it echos. + +## Running tests + +```sh +# runs ALL tests +cargo test --workspace --verbose + +# run tests for a single crate +cargo test -p --verbose +``` + ## TODOs - [ ] wasm_config sharing implementation - [ ] Generalize Host export TCP listener helper function diff --git a/crates/water_wasm/Cargo.toml b/crates/wasm/Cargo.toml similarity index 100% rename from crates/water_wasm/Cargo.toml rename to crates/wasm/Cargo.toml diff --git a/crates/water_wasm/src/config.rs b/crates/wasm/src/config.rs similarity index 100% rename from crates/water_wasm/src/config.rs rename to crates/wasm/src/config.rs diff --git a/crates/water_wasm/src/connections.rs b/crates/wasm/src/connections.rs similarity index 100% rename from crates/water_wasm/src/connections.rs rename to crates/wasm/src/connections.rs diff --git a/crates/water_wasm/src/decoder.rs b/crates/wasm/src/decoder.rs similarity index 100% rename from crates/water_wasm/src/decoder.rs rename to crates/wasm/src/decoder.rs diff --git a/crates/water_wasm/src/dialer.rs b/crates/wasm/src/dialer.rs similarity index 100% rename from crates/water_wasm/src/dialer.rs rename to crates/wasm/src/dialer.rs diff --git a/crates/water_wasm/src/encoder.rs b/crates/wasm/src/encoder.rs similarity index 100% rename from crates/water_wasm/src/encoder.rs rename to crates/wasm/src/encoder.rs diff --git a/crates/water_wasm/src/lib.rs b/crates/wasm/src/lib.rs similarity index 100% rename from crates/water_wasm/src/lib.rs rename to crates/wasm/src/lib.rs diff --git a/crates/water_wasm/src/listener.rs b/crates/wasm/src/listener.rs similarity index 100% rename from crates/water_wasm/src/listener.rs rename to crates/wasm/src/listener.rs diff --git a/crates/water_wasm/src/net/mod.rs b/crates/wasm/src/net/mod.rs similarity index 100% rename from crates/water_wasm/src/net/mod.rs rename to crates/wasm/src/net/mod.rs diff --git a/crates/water_wasm/src/net/tls.rs b/crates/wasm/src/net/tls.rs similarity index 100% rename from crates/water_wasm/src/net/tls.rs rename to crates/wasm/src/net/tls.rs diff --git a/crates/water_wasm/src/v1/README.md b/crates/wasm/src/v1/README.md similarity index 100% rename from crates/water_wasm/src/v1/README.md rename to crates/wasm/src/v1/README.md diff --git a/crates/water_wasm/src/v1/async_listener_v1.rs b/crates/wasm/src/v1/async_listener_v1.rs similarity index 100% rename from crates/water_wasm/src/v1/async_listener_v1.rs rename to crates/wasm/src/v1/async_listener_v1.rs diff --git a/crates/water_wasm/src/v1/config_v1.rs b/crates/wasm/src/v1/config_v1.rs similarity index 100% rename from crates/water_wasm/src/v1/config_v1.rs rename to crates/wasm/src/v1/config_v1.rs diff --git a/crates/water_wasm/src/v1/dial_v1.rs b/crates/wasm/src/v1/dial_v1.rs similarity index 100% rename from crates/water_wasm/src/v1/dial_v1.rs rename to crates/wasm/src/v1/dial_v1.rs diff --git a/crates/water_wasm/src/v1/mod.rs b/crates/wasm/src/v1/mod.rs similarity index 100% rename from crates/water_wasm/src/v1/mod.rs rename to crates/wasm/src/v1/mod.rs diff --git a/crates/water_wasm/src/version.rs b/crates/wasm/src/version.rs similarity index 100% rename from crates/water_wasm/src/version.rs rename to crates/wasm/src/version.rs diff --git a/examples/clients/cli/Cargo.toml b/examples/clients/cli/Cargo.toml index 3f1213f..c7835f3 100644 --- a/examples/clients/cli/Cargo.toml +++ b/examples/clients/cli/Cargo.toml @@ -1,5 +1,5 @@ [package] -name="cli" +name="cli-dev" version = "0.1.0" authors.workspace = true description.workspace = true diff --git a/examples/water_bins/echo_client/Cargo.toml b/examples/water_bins/echo_client/Cargo.toml index 90e1094..a1c1556 100644 --- a/examples/water_bins/echo_client/Cargo.toml +++ b/examples/water_bins/echo_client/Cargo.toml @@ -28,4 +28,4 @@ url = { version = "2.2.2", features = ["serde"] } libc = "0.2.147" # water wasm lib import -water-wasm = { path = "../../../crates/water_wasm/", version = "0.1.0" } +water-wasm = { path = "../../../crates/wasm/", version = "0.1.0" } diff --git a/examples/water_bins/ss_client_wasm_v1/Cargo.toml b/examples/water_bins/ss_client_wasm_v1/Cargo.toml index 8f450a4..5416684 100644 --- a/examples/water_bins/ss_client_wasm_v1/Cargo.toml +++ b/examples/water_bins/ss_client_wasm_v1/Cargo.toml @@ -38,4 +38,4 @@ futures = "0.3.28" pin-project = "1.1.2" # water wasm lib import -water-wasm = { path = "../../../crates/water_wasm/", version = "0.1.0" } +water-wasm = { path = "../../../crates/wasm/", version = "0.1.0" } diff --git a/tests/Cargo.toml b/tests/Cargo.toml new file mode 100644 index 0000000..d4031a5 --- /dev/null +++ b/tests/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "tests" +version = "0.1.0" +authors.workspace = true +description.workspace = true +edition.workspace = true +publish = false + + +[dev-dependencies] +water-wasm = { path = "../crates/wasm" } +water = { path = "../crates/water" } + +tracing = "0.1" +tracing-subscriber = "0.3.17" +rand = "0.8" +pprof = { version = "0.11.1", features = ["flamegraph", "protobuf-codec", "prost-codec"] } +anyhow = "1.0.7" diff --git a/tests/benchmarking_v0.rs b/tests/benches/benchmarking_v0.rs similarity index 88% rename from tests/benchmarking_v0.rs rename to tests/benches/benchmarking_v0.rs index 75f2b40..6708174 100644 --- a/tests/benchmarking_v0.rs +++ b/tests/benches/benchmarking_v0.rs @@ -1,28 +1,26 @@ // use cap_std::net::TcpStream; use water::*; -use rand; use pprof::protos::Message; -use std::net::{TcpListener, TcpStream}; +// use std::net::{TcpListener, TcpStream}; +use std::net::TcpListener; use std::thread; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::Arc; +// use std::sync::atomic::{AtomicBool, Ordering}; +// use std::sync::Arc; -use tracing_subscriber; use tracing::Level; use std::time::Instant; use tracing::info; -use std::io::{Read, Write, ErrorKind}; -use std::thread::sleep; -use std::time::Duration; +use std::io::{Read, Write}; +// use std::io::{Read, Write, ErrorKind}; +// use std::thread::sleep; +// use std::time::Duration; #[test] fn benchmarking_v0_echo() -> Result<(), anyhow::Error> { - tracing_subscriber::fmt() - .with_max_level(Level::INFO) - .init(); + tracing_subscriber::fmt().with_max_level(Level::INFO).init(); thread::spawn(move || { let listener = TcpListener::bind("127.0.0.1:8080").unwrap(); @@ -39,7 +37,7 @@ fn benchmarking_v0_echo() -> Result<(), anyhow::Error> { if n == 0 { break; // Connection was closed. } - + // Echo data back to client. if let Err(e) = stream.write_all(&buf[..n]) { eprintln!("Error writing to client: {:?}", e); @@ -68,20 +66,28 @@ fn benchmarking_v0_echo() -> Result<(), anyhow::Error> { // --------- start to dial the listener --------- let dial_handle = std::thread::spawn(|| -> Result<(), anyhow::Error> { // Measure initialization time - let conf = config::WATERConfig::init(String::from("./tests/test_wasm/proxy.wasm"), String::from("_dial"), String::from("./tests/test_data/config.json"), 0, true)?; + let conf = config::WATERConfig::init( + String::from("./tests/test_wasm/proxy.wasm"), + String::from("_dial"), + String::from("./tests/test_data/config.json"), + 0, + true, + )?; let mut water_client = runtime::WATERClient::new(conf)?; water_client.connect("", 0)?; // let mut water_client = TcpStream::connect(("127.0.0.1", 8088))?; - + // Not measuring the profiler guard initialization since it's unrelated to the read/write ops let guard = pprof::ProfilerGuard::new(100).unwrap(); let single_data_size = 1024; // Bytes per iteration let total_iterations = 1; - - let random_data: Vec = (0..single_data_size).map(|_| rand::random::()).collect(); - + + let random_data: Vec = (0..single_data_size) + .map(|_| rand::random::()) + .collect(); + let start = Instant::now(); for _ in 0..total_iterations { water_client.write(&random_data)?; @@ -94,14 +100,18 @@ fn benchmarking_v0_echo() -> Result<(), anyhow::Error> { let total_data_size_mb = (total_iterations * single_data_size) as f64; let avg_bandwidth = total_data_size_mb / elapsed_time / 1024.0 / 1024.0; - info!("avg bandwidth: {:.2} MB/s (N={})", avg_bandwidth, total_iterations); - - + info!( + "avg bandwidth: {:.2} MB/s (N={})", + avg_bandwidth, total_iterations + ); + let single_data_size = 1024; // Bytes per iteration let total_iterations = 100; - - let random_data: Vec = (0..single_data_size).map(|_| rand::random::()).collect(); - + + let random_data: Vec = (0..single_data_size) + .map(|_| rand::random::()) + .collect(); + let start = Instant::now(); for _ in 0..total_iterations { water_client.write(&random_data)?; @@ -114,14 +124,17 @@ fn benchmarking_v0_echo() -> Result<(), anyhow::Error> { let total_data_size_mb = (total_iterations * single_data_size) as f64; let avg_bandwidth = total_data_size_mb / elapsed_time / 1024.0 / 1024.0; - info!("avg bandwidth: {:.2} MB/s (N={})", avg_bandwidth, total_iterations); - + info!( + "avg bandwidth: {:.2} MB/s (N={})", + avg_bandwidth, total_iterations + ); + // ================== test more iterations ================== // let single_data_size = 1024; // Bytes per iteration // let total_iterations = 10000; - + // let random_data: Vec = (0..single_data_size).map(|_| rand::random::()).collect(); - + // let start = Instant::now(); // for _ in 0..total_iterations { // water_client.write(&random_data)?; @@ -135,13 +148,12 @@ fn benchmarking_v0_echo() -> Result<(), anyhow::Error> { // let avg_bandwidth = total_data_size_mb / elapsed_time / 1024.0 / 1024.0; // info!("avg bandwidth: {:.2} MB/s (N={})", avg_bandwidth, total_iterations); - - + // let single_data_size = 1024; // Bytes per iteration // let total_iterations = 43294; - + // let random_data: Vec = (0..single_data_size).map(|_| rand::random::()).collect(); - + // let start = Instant::now(); // for _ in 0..total_iterations { // water_client.write(&random_data)?; @@ -155,19 +167,19 @@ fn benchmarking_v0_echo() -> Result<(), anyhow::Error> { // let avg_bandwidth = total_data_size_mb / elapsed_time / 1024.0 / 1024.0; // info!("avg bandwidth: {:.2} MB/s (N={})", avg_bandwidth, total_iterations); - + // Stop and report profiler data if let Ok(report) = guard.report().build() { // println!("{:?}", report); // report.flamegraph(std::io::stdout())?; - let mut file = std::fs::File::create("flamegraph.svg")?; + let file = std::fs::File::create("flamegraph.svg")?; report.flamegraph(file)?; - + // let mut file = std::fs::File::create("profile.pb")?; // report.pprof(file)?; let mut file = std::fs::File::create("profile.pb").unwrap(); let profile = report.pprof().unwrap(); - + let mut content = Vec::new(); // profile.encode(&mut content).unwrap(); profile.write_to_vec(&mut content).unwrap(); @@ -197,7 +209,7 @@ fn benchmarking_v0_echo() -> Result<(), anyhow::Error> { // // water_client.execute(); // // Ok(()) - + // let tcp = std::net::TcpListener::bind(("127.0.0.1", 8088)).unwrap(); // loop { @@ -257,9 +269,9 @@ fn benchmarking_v0_echo() -> Result<(), anyhow::Error> { // // keep reading from stdin and call read and write function from water_client.stream // let mut buf = String::new(); // std::io::stdin().read_line(&mut buf)?; - + // water_client.write(buf.as_bytes())?; - + // let mut buf = vec![0; 1024]; // water_client.read(&mut buf)?; @@ -267,4 +279,4 @@ fn benchmarking_v0_echo() -> Result<(), anyhow::Error> { // } // Ok(()) -// } \ No newline at end of file +// } diff --git a/tests/SS_testing.rs b/tests/tests/ss_testing.rs similarity index 83% rename from tests/SS_testing.rs rename to tests/tests/ss_testing.rs index d67d53a..69ee561 100644 --- a/tests/SS_testing.rs +++ b/tests/tests/ss_testing.rs @@ -1,33 +1,33 @@ // use cap_std::net::TcpStream; use water::*; -use rand; +// use rand; -use pprof::protos::Message; -use std::net::{TcpListener, TcpStream}; -use std::thread; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::Arc; +// use pprof::protos::Message; +// use std::net::{TcpListener, TcpStream}; +// use std::thread; +// use std::sync::atomic::{AtomicBool, Ordering}; +// use std::sync::Arc; -use tracing_subscriber; use tracing::Level; -use std::time::Instant; -use tracing::info; +// use std::time::Instant; +// use tracing::info; -use std::io::{Read, Write, ErrorKind}; -use std::thread::sleep; -use std::time::Duration; +// use std::io::{Read, Write, ErrorKind}; +// use std::thread::sleep; +// use std::time::Duration; #[test] fn wasm_managed_shadowsocks_async() { - tracing_subscriber::fmt() - .with_max_level(Level::INFO) - .init(); - let conf = config::WATERConfig::init(String::from("./tests/test_wasm/ss_client_wasm.wasm"), - String::from("ss_client_execute"), - String::from("./tests/test_data/config.json"), - 2, - true).unwrap(); + tracing_subscriber::fmt().with_max_level(Level::INFO).init(); + let conf = config::WATERConfig::init( + String::from("./test_wasm/ss_client_wasm.wasm"), + String::from("ss_client_execute"), + String::from("./test_data/config.json"), + 2, + true, + ) + .unwrap(); let mut water_client = runtime::WATERClient::new(conf).unwrap(); water_client.execute().unwrap(); @@ -69,15 +69,15 @@ fn wasm_managed_shadowsocks_async() { // water_client.connect("", 0)?; // // let mut water_client = TcpStream::connect(("127.0.0.1", 8088))?; - + // // Not measuring the profiler guard initialization since it's unrelated to the read/write ops // let guard = pprof::ProfilerGuard::new(100).unwrap(); // let single_data_size = 1024; // Bytes per iteration // let total_iterations = 1; - + // let random_data: Vec = (0..single_data_size).map(|_| rand::random::()).collect(); - + // let start = Instant::now(); // for _ in 0..total_iterations { // water_client.write(&random_data)?; @@ -91,13 +91,12 @@ fn wasm_managed_shadowsocks_async() { // let avg_bandwidth = total_data_size_mb / elapsed_time / 1024.0 / 1024.0; // info!("avg bandwidth: {:.2} MB/s (N={})", avg_bandwidth, total_iterations); - - + // let single_data_size = 1024; // Bytes per iteration // let total_iterations = 100; - + // let random_data: Vec = (0..single_data_size).map(|_| rand::random::()).collect(); - + // let start = Instant::now(); // for _ in 0..total_iterations { // water_client.write(&random_data)?; @@ -111,19 +110,19 @@ fn wasm_managed_shadowsocks_async() { // let avg_bandwidth = total_data_size_mb / elapsed_time / 1024.0 / 1024.0; // info!("avg bandwidth: {:.2} MB/s (N={})", avg_bandwidth, total_iterations); - + // // Stop and report profiler data // if let Ok(report) = guard.report().build() { // // println!("{:?}", report); // // report.flamegraph(std::io::stdout())?; // let mut file = std::fs::File::create("flamegraph.svg")?; // report.flamegraph(file)?; - + // // let mut file = std::fs::File::create("profile.pb")?; // // report.pprof(file)?; // let mut file = std::fs::File::create("profile.pb").unwrap(); // let profile = report.pprof().unwrap(); - + // let mut content = Vec::new(); // // profile.encode(&mut content).unwrap(); // profile.write_to_vec(&mut content).unwrap(); @@ -139,4 +138,4 @@ fn wasm_managed_shadowsocks_async() { // // should_stop.store(true, Ordering::Relaxed); // Ok(()) -// } \ No newline at end of file +// } From 8cd863fbcf0b94e941dd7adc9b7c9cdaa78a35df Mon Sep 17 00:00:00 2001 From: Erik Chi Date: Sun, 22 Oct 2023 18:37:26 -0400 Subject: [PATCH 4/6] fix: fmt --- crates/water/src/runtime/core.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/water/src/runtime/core.rs b/crates/water/src/runtime/core.rs index eeaabbb..204b3c7 100644 --- a/crates/water/src/runtime/core.rs +++ b/crates/water/src/runtime/core.rs @@ -54,7 +54,11 @@ impl H2O { // store.data_mut().preview1_ctx = Some(WasiCtxBuilder::new().inherit_stdio().preopened_dir(path, ".")?.build()); store.data_mut().preview1_ctx = Some(WasiCtxBuilder::new().inherit_stdio().build()); - wasmtime_wasi::add_to_linker(&mut linker, |h: &mut Host| h.preview1_ctx.as_mut().context("Failed to retrieve preview1_ctx from Host")?)?; + wasmtime_wasi::add_to_linker(&mut linker, |h: &mut Host| { + h.preview1_ctx + .as_mut() + .context("Failed to retrieve preview1_ctx from Host")? + })?; // initializing stuff for multithreading #[cfg(feature = "multithread")] @@ -65,7 +69,9 @@ impl H2O { )?)); wasmtime_wasi_threads::add_to_linker(&mut linker, &store, &module, |h: &mut Host| { - h.wasi_threads.as_ref().context("Failed to get ref of wasi_threads from Host")? + h.wasi_threads + .as_ref() + .context("Failed to get ref of wasi_threads from Host")? })?; } From ff39af23d01978fab769845026d17da34cb1f96e Mon Sep 17 00:00:00 2001 From: Erik Chi Date: Mon, 23 Oct 2023 12:37:25 -0400 Subject: [PATCH 5/6] fix: remove all unsafe unwrap from Host lib --- crates/water/src/runtime/core.rs | 33 +++++++++++---- crates/water/src/runtime/listener.rs | 10 ++++- crates/water/src/runtime/stream.rs | 1 - crates/water/src/runtime/v0/funcs.rs | 41 ++++++++++++++----- crates/water/src/runtime/v1/funcs.rs | 40 ++++++++++++++---- .../water/src/runtime/version_common/funcs.rs | 5 ++- 6 files changed, 97 insertions(+), 33 deletions(-) diff --git a/crates/water/src/runtime/core.rs b/crates/water/src/runtime/core.rs index 204b3c7..eb5839f 100644 --- a/crates/water/src/runtime/core.rs +++ b/crates/water/src/runtime/core.rs @@ -54,11 +54,11 @@ impl H2O { // store.data_mut().preview1_ctx = Some(WasiCtxBuilder::new().inherit_stdio().preopened_dir(path, ".")?.build()); store.data_mut().preview1_ctx = Some(WasiCtxBuilder::new().inherit_stdio().build()); - wasmtime_wasi::add_to_linker(&mut linker, |h: &mut Host| { - h.preview1_ctx - .as_mut() - .context("Failed to retrieve preview1_ctx from Host")? - })?; + if store.data().preview1_ctx.is_none() { + return Err(anyhow::anyhow!("Failed to retrieve preview1_ctx from Host")); + } + + wasmtime_wasi::add_to_linker(&mut linker, |h: &mut Host| h.preview1_ctx.as_mut().unwrap())?; // initializing stuff for multithreading #[cfg(feature = "multithread")] @@ -94,7 +94,12 @@ impl H2O { let instance = linker.instantiate(&mut store, &module)?; Ok(H2O { - version: version.unwrap(), + version: match version { + Some(v) => v, + None => { + return Err(anyhow::anyhow!("Version is None")); + } + }, engine, linker, @@ -144,8 +149,13 @@ impl H2O { // Obtain the directory path and file name from config_wasm let full_path = Path::new(&config.config_wasm); - let parent_dir = full_path.parent().unwrap(); // Assumes config_wasm has a parent directory - let file_name = full_path.file_name().unwrap().to_str().unwrap(); // Assumes file_name is valid UTF-8 + let parent_dir = full_path + .parent() + .ok_or_else(|| anyhow::anyhow!("config_wasm does not have a parent directory"))?; // Assumes config_wasm has a parent directory + let file_name = full_path + .file_name() + .and_then(|os_str| os_str.to_str()) + .ok_or_else(|| anyhow::anyhow!("file_name is not valid UTF-8"))?; // Assumes file_name is valid UTF-8 // Open the parent directory let dir = Dir::open_ambient_dir(parent_dir, ambient_authority())?; @@ -154,7 +164,12 @@ impl H2O { let wasi_file = wasmtime_wasi::sync::file::File::from_cap_std(wasi_file); - let ctx = self.store.data_mut().preview1_ctx.as_mut().unwrap(); + let ctx = self + .store + .data_mut() + .preview1_ctx + .as_mut() + .ok_or(anyhow::anyhow!("preview1_ctx in Store is None"))?; let config_fd = ctx.push_file(Box::new(wasi_file), FileAccessMode::all())? as i32; let params = vec![Val::I32(config_fd); config_fn.ty(&self.store).params().len()]; diff --git a/crates/water/src/runtime/listener.rs b/crates/water/src/runtime/listener.rs index 9964134..e4b10be 100644 --- a/crates/water/src/runtime/listener.rs +++ b/crates/water/src/runtime/listener.rs @@ -118,7 +118,8 @@ impl WATERListener { .core .instance .get_func(&mut self.core.store, &conf.entry_fn) - .unwrap(); + .context(format!("Failed to get function {}", &conf.entry_fn))?; + match fnc.call(&mut self.core.store, &[], &mut []) { Ok(_) => {} Err(e) => { @@ -153,7 +154,12 @@ impl WATERListener { std::mem::forget(water_writer); std::mem::forget(water_reader); - let ctx = core.store.data_mut().preview1_ctx.as_mut().unwrap(); + let ctx = core + .store + .data_mut() + .preview1_ctx + .as_mut() + .ok_or(anyhow::anyhow!("preview1_ctx in Store is None"))?; let water_reader_fd = ctx.push_file(Box::new(wasi_water_reader), FileAccessMode::all())?; let water_writer_fd = ctx.push_file(Box::new(wasi_water_writer), FileAccessMode::all())?; diff --git a/crates/water/src/runtime/stream.rs b/crates/water/src/runtime/stream.rs index e6c6709..cfb1f71 100644 --- a/crates/water/src/runtime/stream.rs +++ b/crates/water/src/runtime/stream.rs @@ -124,7 +124,6 @@ impl WATERStream { info!("[HOST] WATERStream connecting..."); // TODO: add addr:port sharing with WASM, for now WASM is using config.json's remote_addr:port - // let fnc = self.core.instance.get_func(&mut self.core.store, &conf.entry_fn).unwrap(); let fnc = match self.core.instance.get_func(&mut self.core.store, DIAL_FN) { Some(func) => func, None => { diff --git a/crates/water/src/runtime/v0/funcs.rs b/crates/water/src/runtime/v0/funcs.rs index 462d4ba..b54480a 100644 --- a/crates/water/src/runtime/v0/funcs.rs +++ b/crates/water/src/runtime/v0/funcs.rs @@ -1,10 +1,12 @@ +use anyhow::Ok; + use crate::config::wasm_shared_config::StreamConfig; use crate::runtime::*; use std::convert::TryInto; use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; // TODO: rename this to dial_v1, since it has the ability to let WASM choose ip:port -pub fn export_tcp_connect(linker: &mut Linker) { +pub fn export_tcp_connect(linker: &mut Linker) -> Result<(), anyhow::Error> { linker .func_wrap( "env", @@ -48,22 +50,33 @@ pub fn export_tcp_connect(linker: &mut Linker) { addr => std::net::TcpStream::connect(addr), } .map(TcpStream::from_std) - .context("failed to connect to endpoint") + .context(format!( + "Failed to connect to {}:{} in Host exported dial", + host, port + )) .unwrap(); // Connecting Tcp let socket_file: Box = wasmtime_wasi::net::Socket::from(tcp).into(); // Get the WasiCtx of the caller(WASM), then insert_file into it - let ctx: &mut WasiCtx = caller.data_mut().preview1_ctx.as_mut().unwrap(); - ctx.push_file(socket_file, FileAccessMode::all()).unwrap() as i32 + let ctx: &mut WasiCtx = caller + .data_mut() + .preview1_ctx + .as_mut() + .context("preview1_ctx in Store is None") + .unwrap(); + ctx.push_file(socket_file, FileAccessMode::all()) + .context("Failed to push file into WASM") + .unwrap() as i32 }, ) - .unwrap(); + .context("Failed to export Dial function to WASM")?; + Ok(()) } // TODO: rename this to dial_v1, since it has the ability to let WASM listen on a TcpListener -pub fn export_tcplistener_create(linker: &mut Linker) { +pub fn export_tcplistener_create(linker: &mut Linker) -> Result<(), anyhow::Error> { linker .func_wrap( "env", @@ -89,7 +102,7 @@ pub fn export_tcplistener_create(linker: &mut Linker) { name: config.name.clone().try_into().unwrap(), port: config.port as u16, addr: config.addr.clone(), - }); // TODO: add addr here + }); // Get the pair here addr:port let (addr, port) = match listener_file { @@ -108,11 +121,19 @@ pub fn export_tcplistener_create(linker: &mut Linker) { let socket_file: Box = wasmtime_wasi::net::Socket::from(tcp).into(); // Get the WasiCtx of the caller(WASM), then insert_file into it - let ctx: &mut WasiCtx = caller.data_mut().preview1_ctx.as_mut().unwrap(); - ctx.push_file(socket_file, FileAccessMode::all()).unwrap() as i32 + let ctx: &mut WasiCtx = caller + .data_mut() + .preview1_ctx + .as_mut() + .context("preview1_ctx in Store is None") + .unwrap(); + ctx.push_file(socket_file, FileAccessMode::all()) + .context("Failed to push file into WASM") + .unwrap() as i32 }, ) - .unwrap(); + .context("Failed to export TcpListener create function to WASM")?; + Ok(()) } // Generically link dial functions diff --git a/crates/water/src/runtime/v1/funcs.rs b/crates/water/src/runtime/v1/funcs.rs index a791094..b54480a 100644 --- a/crates/water/src/runtime/v1/funcs.rs +++ b/crates/water/src/runtime/v1/funcs.rs @@ -1,10 +1,12 @@ +use anyhow::Ok; + use crate::config::wasm_shared_config::StreamConfig; use crate::runtime::*; use std::convert::TryInto; use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; // TODO: rename this to dial_v1, since it has the ability to let WASM choose ip:port -pub fn export_tcp_connect(linker: &mut Linker) { +pub fn export_tcp_connect(linker: &mut Linker) -> Result<(), anyhow::Error> { linker .func_wrap( "env", @@ -48,22 +50,33 @@ pub fn export_tcp_connect(linker: &mut Linker) { addr => std::net::TcpStream::connect(addr), } .map(TcpStream::from_std) - .context("failed to connect to endpoint") + .context(format!( + "Failed to connect to {}:{} in Host exported dial", + host, port + )) .unwrap(); // Connecting Tcp let socket_file: Box = wasmtime_wasi::net::Socket::from(tcp).into(); // Get the WasiCtx of the caller(WASM), then insert_file into it - let ctx: &mut WasiCtx = caller.data_mut().preview1_ctx.as_mut().unwrap(); - ctx.push_file(socket_file, FileAccessMode::all()).unwrap() as i32 + let ctx: &mut WasiCtx = caller + .data_mut() + .preview1_ctx + .as_mut() + .context("preview1_ctx in Store is None") + .unwrap(); + ctx.push_file(socket_file, FileAccessMode::all()) + .context("Failed to push file into WASM") + .unwrap() as i32 }, ) - .unwrap(); + .context("Failed to export Dial function to WASM")?; + Ok(()) } // TODO: rename this to dial_v1, since it has the ability to let WASM listen on a TcpListener -pub fn export_tcplistener_create(linker: &mut Linker) { +pub fn export_tcplistener_create(linker: &mut Linker) -> Result<(), anyhow::Error> { linker .func_wrap( "env", @@ -104,14 +117,23 @@ pub fn export_tcplistener_create(linker: &mut Linker) { // Creating Tcp Listener let tcp = std::net::TcpListener::bind((addr.as_str(), port)).unwrap(); let tcp = TcpListener::from_std(tcp); + // tcp.set_nonblocking(true); let socket_file: Box = wasmtime_wasi::net::Socket::from(tcp).into(); // Get the WasiCtx of the caller(WASM), then insert_file into it - let ctx: &mut WasiCtx = caller.data_mut().preview1_ctx.as_mut().unwrap(); - ctx.push_file(socket_file, FileAccessMode::all()).unwrap() as i32 + let ctx: &mut WasiCtx = caller + .data_mut() + .preview1_ctx + .as_mut() + .context("preview1_ctx in Store is None") + .unwrap(); + ctx.push_file(socket_file, FileAccessMode::all()) + .context("Failed to push file into WASM") + .unwrap() as i32 }, ) - .unwrap(); + .context("Failed to export TcpListener create function to WASM")?; + Ok(()) } // Generically link dial functions diff --git a/crates/water/src/runtime/version_common/funcs.rs b/crates/water/src/runtime/version_common/funcs.rs index 9296e67..98a2029 100644 --- a/crates/water/src/runtime/version_common/funcs.rs +++ b/crates/water/src/runtime/version_common/funcs.rs @@ -1,7 +1,7 @@ use crate::runtime::*; // exportint a function for WASM to get CONFIG file -pub fn export_config(linker: &mut Linker, config_file: String) { +pub fn export_config(linker: &mut Linker, config_file: String) -> Result<(), anyhow::Error> { linker .func_wrap( "env", @@ -22,5 +22,6 @@ pub fn export_config(linker: &mut Linker, config_file: String) { .expect("Error with pushing file") as i32 }, ) - .unwrap(); + .context("Failed to export config function to WASM")?; + Ok(()) } From 97d68e7aca951c763bcd3578215bbb7c5118b4d2 Mon Sep 17 00:00:00 2001 From: Erik Chi Date: Mon, 23 Oct 2023 13:40:02 -0400 Subject: [PATCH 6/6] fix: clippy --- crates/water/src/runtime/core.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/water/src/runtime/core.rs b/crates/water/src/runtime/core.rs index eb5839f..a7630f7 100644 --- a/crates/water/src/runtime/core.rs +++ b/crates/water/src/runtime/core.rs @@ -78,18 +78,18 @@ impl H2O { // export functions -- version dependent -- has to be done before instantiate match &version { Some(Version::V0) => { - v0::funcs::export_tcp_connect(&mut linker); - v0::funcs::export_tcplistener_create(&mut linker); + v0::funcs::export_tcp_connect(&mut linker)?; + v0::funcs::export_tcplistener_create(&mut linker)?; } Some(Version::V1) => { - v1::funcs::export_tcp_connect(&mut linker); - v1::funcs::export_tcplistener_create(&mut linker); + v1::funcs::export_tcp_connect(&mut linker)?; + v1::funcs::export_tcplistener_create(&mut linker)?; } _ => {} // add export funcs for other versions here } // export functions -- version independent - version_common::funcs::export_config(&mut linker, conf.config_wasm.clone()); + version_common::funcs::export_config(&mut linker, conf.config_wasm.clone())?; let instance = linker.instantiate(&mut store, &module)?;