diff --git a/examples/ipfs_node/Config.toml b/examples/ipfs_node/Config.toml index 1c4b5fad..d34e4c90 100644 --- a/examples/ipfs_node/Config.toml +++ b/examples/ipfs_node/Config.toml @@ -5,7 +5,7 @@ [core_module.imports] mysql = "/usr/bin/mysql" - ipfs = "/usr/bin/ipfs" + ipfs = "/usr/local/bin/ipfs" [core_module.wasi] envs = ["asdsad=sdaasd"] diff --git a/examples/ipfs_node/src/imports.rs b/examples/ipfs_node/src/imports.rs index c81b6203..c2a73d71 100644 --- a/examples/ipfs_node/src/imports.rs +++ b/examples/ipfs_node/src/imports.rs @@ -16,6 +16,18 @@ use wasmer_core::vm::Ctx; use wasmer_core::typed_func::DynamicFunc; +use wasmer_core::typed_func::WasmTypeList; +use wasmer_core::types::Value; +use wasmer_core::types::Type; +use wasmer_core::types::FuncSig; +use wasmer_runtime::Func; +use wasmer_runtime::error::ResolveError; +use wasmer_core::backend::SigRegistry; +use wasmer_runtime::types::LocalOrImport; +use wasmer_core::module::ExportIndex; +use wasmer_core::structures::TypedIndex; + +const ALLOCATE_FUNC_NAME: &'static str = "allocate"; pub(super) fn log_utf8_string(ctx: &mut Ctx, offset: i32, size: i32) { use wasmer_core::memory::ptr::{Array, WasmPtr}; @@ -27,10 +39,80 @@ pub(super) fn log_utf8_string(ctx: &mut Ctx, offset: i32, size: i32) { } } -pub(super) fn create_host_import_func(_host_cmd: String) -> DynamicFunc<'static> { - use wasmer_core::types::Value; - use wasmer_core::types::Type; - use wasmer_core::types::FuncSig; +// rewrited from Wasmer: https://github.com/wasmerio/wasmer/blob/081f6250e69b98b9f95a8f62ad6d8386534f3279/lib/runtime-core/src/instance.rs#L863 +unsafe fn get_export_func_by_name<'a, Args, Rets>( + ctx: &'a mut Ctx, + name: &str, +) -> Result, ResolveError> +where + Args: WasmTypeList, + Rets: WasmTypeList, +{ + let module_inner = &(*ctx.module); + + let export_index = + module_inner + .info + .exports + .get(name) + .ok_or_else(|| ResolveError::ExportNotFound { + name: name.to_string(), + })?; + + let export_func_index = match export_index { + ExportIndex::Func(func_index) => func_index, + _ => { + return Err(ResolveError::ExportWrongType { + name: name.to_string(), + }) + } + }; + + let export_func_signature_idx = *module_inner + .info + .func_assoc + .get(*export_func_index) + .expect("broken invariant, incorrect func index"); + + let export_func_signature = &module_inner.info.signatures[export_func_signature_idx]; + let export_func_signature_ref = SigRegistry.lookup_signature_ref(export_func_signature); + + if export_func_signature_ref.params() != Args::types() + || export_func_signature_ref.returns() != Rets::types() + { + return Err(ResolveError::Signature { + expected: (*export_func_signature).clone(), + found: Args::types().to_vec(), + }); + } + + let func_wasm_inner = module_inner + .runnable_module + .get_trampoline(&module_inner.info, export_func_signature_idx) + .unwrap(); + + let export_func_ptr = match export_func_index.local_or_import(&module_inner.info) { + LocalOrImport::Local(local_func_index) => module_inner + .runnable_module + .get_func(&module_inner.info, local_func_index) + .unwrap(), + _ => { + return Err(ResolveError::ExportNotFound { + name: name.to_string(), + }) + } + }; + + let typed_func: Func = + Func::from_raw_parts(func_wasm_inner, export_func_ptr, None, ctx as _); + + Ok(typed_func) +} + +pub(super) fn create_host_import_func(host_cmd: String) -> DynamicFunc<'static> { + let allocate_func: Option> = None; + let set_result_ptr: Option> = None; + let set_result_size: Option> = None; let func = move |ctx: &mut Ctx, inputs: &[Value]| -> Vec { use wasmer_core::memory::ptr::{Array, WasmPtr}; @@ -38,17 +120,58 @@ pub(super) fn create_host_import_func(_host_cmd: String) -> DynamicFunc<'static> println!("inputs size is {}", inputs.len()); // TODO: refactor this - let array_ptr = inputs[1].to_u128() as i32; - let array_size = inputs[0].to_u128() as i32; + let array_ptr = inputs[0].to_u128() as i32; + let array_size = inputs[1].to_u128() as i32; println!("ptr is {}, size is {}", array_ptr, array_size); let wasm_ptr = WasmPtr::::new(array_ptr as _); - match wasm_ptr.get_utf8_string(ctx.memory(0), array_size as _) { - Some(msg) => print!("{}", msg), - None => println!("callback: incorrect UTF8 string's been supplied to logger"), - } + let result = match wasm_ptr.get_utf8_string(ctx.memory(0), array_size as _) { + Some(arg_value) => { + let output = std::process::Command::new(host_cmd.clone()) + .arg(arg_value) + .output() + .unwrap(); + output.stdout + } + None => b"host callback: incorrect UTF8 string's been supplied to import".to_vec(), + }; - vec![Value::I32(0x1337)] + println!("from host import function: result is {:?}", result); + + unsafe { + if let mut allocate_func = None { + let func = match get_export_func_by_name::(ctx, ALLOCATE_FUNC_NAME) { + Ok(func) => func, + Err(_) => return vec![Value::I32(0)], + }; + allocate_func = Some(func); + } + + if let mut set_result_ptr = None { + let func = match get_export_func_by_name::(ctx, ALLOCATE_FUNC_NAME) { + Ok(func) => func, + Err(_) => return vec![Value::I32(0)], + }; + set_result_ptr = Some(func); + } + + if let mut set_result_size = None { + let func = match get_export_func_by_name::(ctx, ALLOCATE_FUNC_NAME) { + Ok(func) => func, + Err(_) => return vec![Value::I32(0)], + }; + set_result_size = Some(func); + } + let mem_address = allocate_func + .clone() + .unwrap() + .call(result.len() as i32) + .unwrap(); + let _ = set_result_ptr.clone().unwrap().call(mem_address as i32); + let _ = set_result_size.clone().unwrap().call(result.len() as i32); + + vec![Value::I32(1)] + } }; DynamicFunc::new( diff --git a/examples/ipfs_node/wasm/ipfs_node/src/lib.rs b/examples/ipfs_node/wasm/ipfs_node/src/lib.rs index 7dc0ac4d..25e1285c 100644 --- a/examples/ipfs_node/wasm/ipfs_node/src/lib.rs +++ b/examples/ipfs_node/wasm/ipfs_node/src/lib.rs @@ -21,28 +21,34 @@ mod result; use crate::result::{RESULT_PTR, RESULT_SIZE}; -#[no_mangle] -pub unsafe fn put(file_content_ptr: *mut u8, file_content_size: usize) { - let file_content = - String::from_raw_parts(file_content_ptr, file_content_size, file_content_size); +const RESULT_PATH: &str = "/tmp/ipfs_rpc_file"; - let msg = format!( - "from Wasm ipfs_node.get: file content is {}\n", - file_content - ); +#[no_mangle] +pub unsafe fn put(file_path_ptr: *mut u8, file_path_size: usize) { + let file_path = String::from_raw_parts(file_path_ptr, file_path_size, file_path_size); + + let msg = format!("from Wasm ipfs_node.put: file path is {}\n", file_path); log_utf8_string(msg.as_ptr() as _, msg.len() as _); - let cmd = format!("put {}", file_content); - let ipfs_result = ipfs(cmd.as_ptr() as _, cmd.len() as _); + let cmd = format!("add -Q {}", file_path); + let result = ipfs(cmd.as_ptr() as _, cmd.len() as _); - let after_ipfs = format!("after ipfs call: {} \n", ipfs_result); - log_utf8_string(after_ipfs.as_ptr() as _, after_ipfs.len() as _); + let hash = if result { + String::from_raw_parts( + *RESULT_PTR.get_mut() as _, + *RESULT_SIZE.get_mut(), + *RESULT_SIZE.get_mut(), + ) + } else { + "host ipfs call failed".to_string() + }; - let result = "IPFS node: hash is asdasdsad".to_string(); + let msg = format!("from Wasm ipfs_node.put: file add wtih hash is {} \n", hash); + log_utf8_string(msg.as_ptr() as _, msg.len() as _); - *RESULT_PTR.get_mut() = result.as_ptr() as _; - *RESULT_SIZE.get_mut() = result.len(); - std::mem::forget(result); + *RESULT_PTR.get_mut() = hash.as_ptr() as _; + *RESULT_SIZE.get_mut() = hash.len(); + std::mem::forget(hash); } #[no_mangle] @@ -52,14 +58,24 @@ pub unsafe fn get(hash_ptr: *mut u8, hash_size: usize) { let msg = format!("from Wasm ipfs_node.get: file hash is {}\n", hash); log_utf8_string(msg.as_ptr() as _, msg.len() as _); - let cmd = format!("get {}", hash); - ipfs(cmd.as_ptr() as _, cmd.len() as _); + let cmd = format!("get -o {} {}", RESULT_PATH, hash); + let _result = ipfs(cmd.as_ptr() as _, cmd.len() as _); - let result = "IPFS node: file is hhhhaaa".to_string(); + let _output = String::from_raw_parts( + *RESULT_PTR.get_mut() as _, + *RESULT_SIZE.get_mut(), + *RESULT_SIZE.get_mut(), + ); - *RESULT_PTR.get_mut() = result.as_ptr() as _; - *RESULT_SIZE.get_mut() = result.len(); - std::mem::forget(result); + // TODO: check output + + let file_path = RESULT_PATH.to_string(); + let msg = format!("from Wasm ipfs_node.get: file path is {}", file_path); + log_utf8_string(msg.as_ptr() as _, msg.len() as _); + + *RESULT_PTR.get_mut() = file_path.as_ptr() as _; + *RESULT_SIZE.get_mut() = file_path.len(); + std::mem::forget(file_path); } #[link(wasm_import_module = "host")] diff --git a/examples/ipfs_node/wasm/ipfs_rpc/src/lib.rs b/examples/ipfs_node/wasm/ipfs_rpc/src/lib.rs index f6636e25..45b33501 100644 --- a/examples/ipfs_node/wasm/ipfs_rpc/src/lib.rs +++ b/examples/ipfs_node/wasm/ipfs_rpc/src/lib.rs @@ -22,31 +22,6 @@ use crate::result::{RESULT_PTR, RESULT_SIZE}; use std::fs; use std::path::PathBuf; -#[no_mangle] -pub unsafe fn get(hash_ptr: *mut u8, hash_size: usize) { - let hash = String::from_raw_parts(hash_ptr, hash_size, hash_size); - - let msg = format!("from Wasm rpc: getting file with hash {}\n", hash); - log_utf8_string(msg.as_ptr() as _, msg.len() as _); - - ipfs_get(hash.as_ptr() as _, hash.len() as _); - - let file_path = String::from_raw_parts( - *RESULT_PTR.get_mut() as _, - *RESULT_SIZE.get_mut(), - *RESULT_SIZE.get_mut(), - ); - - let msg = format!("from Wasm rpc: reading file from {}\n", file_path); - log_utf8_string(msg.as_ptr() as _, msg.len() as _); - - let file_content = fs::read(file_path).unwrap_or_else(|_| b"error while reading file".to_vec()); - - *RESULT_PTR.get_mut() = file_content.as_ptr() as _; - *RESULT_SIZE.get_mut() = file_content.len(); - std::mem::forget(file_content); -} - #[no_mangle] pub unsafe fn put(file_content_ptr: *mut u8, file_content_size: usize) { let file_content = @@ -76,6 +51,31 @@ pub unsafe fn put(file_content_ptr: *mut u8, file_content_size: usize) { std::mem::forget(hash); } +#[no_mangle] +pub unsafe fn get(hash_ptr: *mut u8, hash_size: usize) { + let hash = String::from_raw_parts(hash_ptr, hash_size, hash_size); + + let msg = format!("from Wasm rpc: getting file with hash {}\n", hash); + log_utf8_string(msg.as_ptr() as _, msg.len() as _); + + ipfs_get(hash.as_ptr() as _, hash.len() as _); + + let file_path = String::from_raw_parts( + *RESULT_PTR.get_mut() as _, + *RESULT_SIZE.get_mut(), + *RESULT_SIZE.get_mut(), + ); + + let msg = format!("from Wasm rpc: reading file from {}\n", file_path); + log_utf8_string(msg.as_ptr() as _, msg.len() as _); + + let file_content = fs::read(file_path).unwrap_or_else(|_| b"error while reading file".to_vec()); + + *RESULT_PTR.get_mut() = file_content.as_ptr() as _; + *RESULT_SIZE.get_mut() = file_content.len(); + std::mem::forget(file_content); +} + #[link(wasm_import_module = "host")] extern "C" { /// Writes a byte string of size bytes that starts from ptr to a logger.