From 5b91b61af91a051216497f54fd513b163d2d0fd3 Mon Sep 17 00:00:00 2001 From: Knarkzel Date: Sun, 22 Jan 2023 13:01:23 +0100 Subject: [PATCH 1/2] Add http example --- Cargo.lock | 17 +++++ Cargo.toml | 6 ++ examples/http_dynamic_size.rs | 122 ++++++++++++++++++++++++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 examples/http_dynamic_size.rs diff --git a/Cargo.lock b/Cargo.lock index fd01f093b65..51cdf093ca5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5230,6 +5230,22 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "ureq" +version = "2.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "338b31dd1314f68f3aabf3ed57ab922df95ffcd902476ca7ba3c4ce7b908c46d" +dependencies = [ + "base64", + "flate2", + "log", + "once_cell", + "rustls 0.20.7", + "url", + "webpki 0.22.0", + "webpki-roots 0.22.6", +] + [[package]] name = "url" version = "2.5.0" @@ -6596,6 +6612,7 @@ dependencies = [ "tokio", "tracing", "tracing-subscriber", + "ureq", "wasi-test-generator", "wasmer", "wasmer-cache", diff --git a/Cargo.toml b/Cargo.toml index 3019bed58a7..000d8016bb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -109,6 +109,7 @@ lazy_static = "1.4" serial_test = "0.5" compiler-test-derive = { path = "tests/lib/compiler-test-derive" } tempfile = "3.6.0" +ureq = "2.6" # For logging tests using the `RUST_LOG=debug` when testing test-log = { version = "0.2", default-features = false, features = ["trace"] } tracing = { version = "0.1", default-features = false, features = ["log"] } @@ -314,3 +315,8 @@ required-features = ["backend"] name = "features" path = "examples/features.rs" required-features = ["cranelift"] + +[[example]] +name = "http-dynamic-size" +path = "examples/http_dynamic_size.rs" +required-features = ["cranelift"] diff --git a/examples/http_dynamic_size.rs b/examples/http_dynamic_size.rs new file mode 100644 index 00000000000..fda8ec66f95 --- /dev/null +++ b/examples/http_dynamic_size.rs @@ -0,0 +1,122 @@ +use anyhow::Result; +use wasmer::{wat2wasm, imports, Instance, Module, Store, Memory, AsStoreRef, MemoryView, FunctionEnvMut, WasmPtr, FunctionEnv, Function}; + +// Utils +pub fn read_string(view: &MemoryView, start: u32, len: u32) -> Result { + Ok(WasmPtr::::new(start).read_utf8_string(view, len)?) +} + +// Environment +pub struct ExampleEnv { + memory: Option, +} + +impl ExampleEnv { + fn set_memory(&mut self, memory: Memory) { + self.memory = Some(memory); + } + + fn get_memory(&self) -> &Memory { + self.memory.as_ref().unwrap() + } + + fn view<'a>(&'a self, store: &'a impl AsStoreRef) -> MemoryView<'a> { + self.get_memory().view(store) + } +} + +fn http_get(mut ctx: FunctionEnvMut, url: u32, url_len: u32) -> u32 { + // Setup environment + let (response, memory_size) = { + // Read url from memory + let view = ctx.data().view(&ctx); + let memory_size = view.data_size() as usize; + let address = read_string(&view, url, url_len).unwrap(); + + // Get request + let response = ureq::get(&address).call().unwrap(); + let capacity = match response.header("Content-Length").map(|it| it.parse::()) { + Some(Ok(len)) => len, + _ => 1024, + }; + let mut buffer = Vec::with_capacity(capacity); + let mut reader = response.into_reader(); + reader.read_to_end(&mut buffer).unwrap(); + (buffer, memory_size) + }; + + // If the response is too big, grow memory + if 1114112 + response.len() > memory_size { + let delta = (1114112 + response.len() - memory_size) / wasmer::WASM_PAGE_SIZE + 1; + let memory = ctx.data().get_memory().clone(); + memory.grow(&mut ctx, delta as u32).unwrap(); + } + + // Write response as string [ptr, cap, len] to wasm memory and return pointer + let view = ctx.data().view(&ctx); + view.write(1114112, &u32::to_le_bytes(1114124)).unwrap(); + view.write(1114116, &u32::to_le_bytes(response.len() as u32)).unwrap(); + view.write(1114120, &u32::to_le_bytes(response.len() as u32)).unwrap(); + view.write(1114124, &response).unwrap(); + 1114112 +} + +fn main() -> Result<()> { + let wasm_bytes = wat2wasm( + br#" +(module + (type (;0;) (func (param i32 i32) (result i32))) + (type (;1;) (func (result i32))) + (type (;2;) (func)) + (import "env" "http_get" (func (;0;) (type 0))) + (func (;1;) (type 1) (result i32) + i32.const 1048576 + i32.const 45 + call 0 + i32.const 8 + i32.add + i32.load) + (func (;2;) (type 2)) + (func (;3;) (type 2) + call 2 + call 2) + (func (;4;) (type 1) (result i32) + call 1 + call 3) + (table (;0;) 1 1 funcref) + (memory (;0;) 17) + (global (;0;) (mut i32) (i32.const 1048576)) + (export "memory" (memory 0)) + (export "fetch" (func 4)) + (data (;0;) (i32.const 1048576) "https://postman-echo.com/bytes/5/mb?type=json")) +"#, + )?; + + // Load module + let mut store = Store::default(); + let module = Module::new(&store, wasm_bytes)?; + + // Add host functions + let function_env = FunctionEnv::new(&mut store, ExampleEnv { memory: None }); + let import_object = imports! { + // We use the default namespace "env". + "env" => { + // And call our function "http_get". + "http_get" => Function::new_typed_with_env(&mut store, &function_env, http_get), + } + }; + + // Create instance + let instance = Instance::new(&mut store, &module, &import_object)?; + let memory = instance.exports.get_memory("memory")?; + + // Give reference to memory + function_env.as_mut(&mut store).set_memory(memory.clone()); + + // Call function + let fetch = instance.exports.get_function("fetch")?; + let result = fetch.call(&mut store, &[])?; + println!("Response size: {result:?}"); + + Ok(()) +} From 6fe7c225b04c6dea6d593fa08c0b9888a8383ce5 Mon Sep 17 00:00:00 2001 From: "M.Amin Rayej" Date: Thu, 11 Jan 2024 02:51:07 +0330 Subject: [PATCH 2/2] update cargo lock and fix lint --- Cargo.lock | 112 ++++++++++++++++++++++++++-------- examples/http_dynamic_size.rs | 22 ++++--- 2 files changed, 103 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 51cdf093ca5..0a83ab16f54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -274,6 +274,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.21.5" @@ -2061,7 +2067,7 @@ dependencies = [ "atomic-polyfill", "hash32", "rustc_version 0.4.0", - "spin", + "spin 0.9.8", "stable_deref_trait", ] @@ -2190,7 +2196,7 @@ dependencies = [ "futures-util", "http", "hyper", - "rustls", + "rustls 0.21.10", "tokio", "tokio-rustls", ] @@ -3648,7 +3654,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ "async-compression", - "base64", + "base64 0.21.5", "bytes", "encoding_rs", "futures-core", @@ -3668,7 +3674,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls", + "rustls 0.21.10", "rustls-pemfile", "serde", "serde_json", @@ -3684,10 +3690,25 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots", + "webpki-roots 0.25.3", "winreg", ] +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted 0.7.1", + "web-sys", + "winapi", +] + [[package]] name = "ring" version = "0.17.7" @@ -3697,8 +3718,8 @@ dependencies = [ "cc", "getrandom", "libc", - "spin", - "untrusted", + "spin 0.9.8", + "untrusted 0.9.0", "windows-sys 0.48.0", ] @@ -3838,6 +3859,18 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" +dependencies = [ + "log", + "ring 0.16.20", + "sct", + "webpki", +] + [[package]] name = "rustls" version = "0.21.10" @@ -3845,7 +3878,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring", + "ring 0.17.7", "rustls-webpki", "sct", ] @@ -3868,7 +3901,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64", + "base64 0.21.5", ] [[package]] @@ -3877,8 +3910,8 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring", - "untrusted", + "ring 0.17.7", + "untrusted 0.9.0", ] [[package]] @@ -4018,8 +4051,8 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring", - "untrusted", + "ring 0.17.7", + "untrusted 0.9.0", ] [[package]] @@ -4391,6 +4424,12 @@ dependencies = [ "byteorder", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "spin" version = "0.9.8" @@ -4791,7 +4830,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls", + "rustls 0.21.10", "tokio", ] @@ -4821,7 +4860,7 @@ checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" dependencies = [ "futures-util", "log", - "rustls", + "rustls 0.21.10", "rustls-native-certs", "tokio", "tokio-rustls", @@ -5102,7 +5141,7 @@ dependencies = [ "httparse", "log", "rand", - "rustls", + "rustls 0.21.10", "sha1", "thiserror", "url", @@ -5224,6 +5263,12 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "untrusted" version = "0.9.0" @@ -5236,13 +5281,13 @@ version = "2.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "338b31dd1314f68f3aabf3ed57ab922df95ffcd902476ca7ba3c4ce7b908c46d" dependencies = [ - "base64", + "base64 0.13.1", "flate2", "log", "once_cell", - "rustls 0.20.7", + "rustls 0.20.9", "url", - "webpki 0.22.0", + "webpki", "webpki-roots 0.22.6", ] @@ -5379,7 +5424,7 @@ checksum = "762dac9d5da7f609894b31f7fd03b19ee8959510847c98c1973acce32270b132" dependencies = [ "anyhow", "async-trait", - "base64", + "base64 0.21.5", "bincode", "bytes", "derivative", @@ -5406,7 +5451,7 @@ version = "0.6.2" dependencies = [ "anyhow", "async-trait", - "base64", + "base64 0.21.5", "bincode", "bytecheck", "bytes", @@ -6230,7 +6275,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", - "base64", + "base64 0.21.5", "bincode", "bytecheck", "bytes", @@ -6440,7 +6485,7 @@ version = "0.18.0" dependencies = [ "anyhow", "async-trait", - "base64", + "base64 0.21.5", "bincode", "bytecheck", "bytes", @@ -6825,7 +6870,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "973ca5a91b4fb3e4bb37cfebe03ef9364d0aff2765256abefdb7e79dc9188483" dependencies = [ "anyhow", - "base64", + "base64 0.21.5", "byteorder", "bytes", "flate2", @@ -6850,6 +6895,25 @@ dependencies = [ "wasmer-toml", ] +[[package]] +name = "webpki" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" +dependencies = [ + "ring 0.17.7", + "untrusted 0.9.0", +] + +[[package]] +name = "webpki-roots" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +dependencies = [ + "webpki", +] + [[package]] name = "webpki-roots" version = "0.25.3" diff --git a/examples/http_dynamic_size.rs b/examples/http_dynamic_size.rs index fda8ec66f95..91317f989cb 100644 --- a/examples/http_dynamic_size.rs +++ b/examples/http_dynamic_size.rs @@ -1,5 +1,8 @@ use anyhow::Result; -use wasmer::{wat2wasm, imports, Instance, Module, Store, Memory, AsStoreRef, MemoryView, FunctionEnvMut, WasmPtr, FunctionEnv, Function}; +use wasmer::{ + imports, wat2wasm, AsStoreRef, Function, FunctionEnv, FunctionEnvMut, Instance, Memory, + MemoryView, Module, Store, WasmPtr, +}; // Utils pub fn read_string(view: &MemoryView, start: u32, len: u32) -> Result { @@ -19,7 +22,7 @@ impl ExampleEnv { fn get_memory(&self) -> &Memory { self.memory.as_ref().unwrap() } - + fn view<'a>(&'a self, store: &'a impl AsStoreRef) -> MemoryView<'a> { self.get_memory().view(store) } @@ -35,7 +38,10 @@ fn http_get(mut ctx: FunctionEnvMut, url: u32, url_len: u32) -> u32 // Get request let response = ureq::get(&address).call().unwrap(); - let capacity = match response.header("Content-Length").map(|it| it.parse::()) { + let capacity = match response + .header("Content-Length") + .map(|it| it.parse::()) + { Some(Ok(len)) => len, _ => 1024, }; @@ -44,7 +50,7 @@ fn http_get(mut ctx: FunctionEnvMut, url: u32, url_len: u32) -> u32 reader.read_to_end(&mut buffer).unwrap(); (buffer, memory_size) }; - + // If the response is too big, grow memory if 1114112 + response.len() > memory_size { let delta = (1114112 + response.len() - memory_size) / wasmer::WASM_PAGE_SIZE + 1; @@ -55,8 +61,10 @@ fn http_get(mut ctx: FunctionEnvMut, url: u32, url_len: u32) -> u32 // Write response as string [ptr, cap, len] to wasm memory and return pointer let view = ctx.data().view(&ctx); view.write(1114112, &u32::to_le_bytes(1114124)).unwrap(); - view.write(1114116, &u32::to_le_bytes(response.len() as u32)).unwrap(); - view.write(1114120, &u32::to_le_bytes(response.len() as u32)).unwrap(); + view.write(1114116, &u32::to_le_bytes(response.len() as u32)) + .unwrap(); + view.write(1114120, &u32::to_le_bytes(response.len() as u32)) + .unwrap(); view.write(1114124, &response).unwrap(); 1114112 } @@ -91,7 +99,7 @@ fn main() -> Result<()> { (data (;0;) (i32.const 1048576) "https://postman-echo.com/bytes/5/mb?type=json")) "#, )?; - + // Load module let mut store = Store::default(); let module = Module::new(&store, wasm_bytes)?;