diff --git a/blockless/src/lib.rs b/blockless/src/lib.rs index 5504b0b..72f7100 100644 --- a/blockless/src/lib.rs +++ b/blockless/src/lib.rs @@ -30,7 +30,7 @@ pub enum RunTarget { } trait BlocklessConfig2Preview1WasiBuilder { - fn preview1_builder(&self) -> WasiCtxBuilder; + fn preview1_builder(&self) -> anyhow::Result; fn preview1_set_stdio(&self, builder: &mut WasiCtxBuilder); fn preview1_engine_config(&self) -> Config; fn store_limits(&self) -> StoreLimits; @@ -113,7 +113,7 @@ impl BlocklessConfig2Preview1WasiBuilder for BlocklessConfig { } /// create the preview1_builder by the configure. - fn preview1_builder(&self) -> WasiCtxBuilder { + fn preview1_builder(&self) -> anyhow::Result { let b_conf = self; let root_dir = b_conf.fs_root_path_ref().and_then(|path| { wasi_common::sync::Dir::open_ambient_dir(path, ambient_authority()).ok() @@ -121,16 +121,27 @@ impl BlocklessConfig2Preview1WasiBuilder for BlocklessConfig { let mut builder = WasiCtxBuilder::new(); //stdout file process for setting. b_conf.preview1_set_stdio(&mut builder); + // configure to storeLimit - let entry_module = b_conf.entry_module().unwrap(); + let entry_module = b_conf + .entry_module() + .context("not found the entry module.")?; let mut args = vec![entry_module]; args.extend_from_slice(&b_conf.stdin_args_ref()[..]); - builder.args(&args[..]).unwrap(); - builder.envs(&b_conf.envs_ref()[..]).unwrap(); + builder.args(&args[..])?; + builder.envs(&b_conf.envs_ref()[..])?; if let Some(d) = root_dir { - builder.preopened_dir(d, "/").unwrap(); + builder.preopened_dir(d, "/")?; + } + //set the tcp listener. + let mut max_fd: u32 = 3; + for l in b_conf.tcp_listens.iter() { + let l = std::net::TcpListener::bind(l)?; + let l = wasi_common::sync::TcpListener::from_std(l); + builder.preopened_socket(max_fd, l)?; + max_fd += 1; } - builder + anyhow::Ok(builder) } /// convert the blockless configure to wasmtime configure. @@ -232,7 +243,7 @@ impl BlocklessRunner { let engine = Engine::new(&conf)?; let mut linker = wasmtime::Linker::new(&engine); let support_thread = b_conf.feature_thread(); - let mut builder = b_conf.preview1_builder(); + let mut builder = b_conf.preview1_builder()?; let mut preview1_ctx = builder.build(); let drivers = b_conf.drivers_ref(); Self::load_driver(drivers); diff --git a/bls-runtime/src/cli_clap.rs b/bls-runtime/src/cli_clap.rs index 5e8a6fa..a6edc0e 100644 --- a/bls-runtime/src/cli_clap.rs +++ b/bls-runtime/src/cli_clap.rs @@ -8,7 +8,11 @@ use clap::{ builder::{TypedValueParser, ValueParser}, Arg, ArgMatches, Command, Parser, }; -use std::{collections::HashMap, str::FromStr}; +use std::{ + collections::HashMap, + net::{IpAddr, SocketAddr, TcpListener, ToSocketAddrs}, + str::FromStr, +}; use url::Url; use crate::config::CliConfig; @@ -53,6 +57,8 @@ const V86_HELP: &str = const THREAD_SUPPORT_HELP: &str = "the thread support flag when the flag setting the runtime will support multi-threads."; +const TCP_LISTEN_HELP: &str = "grant access to the given TCP listen socket"; + fn parse_envs(envs: &str) -> Result<(String, String)> { let parts: Vec<_> = envs.splitn(2, "=").collect(); if parts.len() != 2 { @@ -133,6 +139,14 @@ fn parse_stdin(stdin: &str) -> Result { } } +fn parse_listen(s: &str) -> Result { + let addrs = s.to_socket_addrs()?; + for addr in addrs { + return Ok(addr); + } + bail!("could not resolve to any addresses") +} + #[derive(Debug)] pub enum RuntimeType { V86, @@ -199,6 +213,9 @@ pub(crate) struct CliCommandOpts { #[clap(long = "module", value_name = "MODULE-NAME=MODULE-PATH", help = MODULES_HELP, value_parser = parse_module)] modules: Vec, + #[clap(long = "tcplisten", help = TCP_LISTEN_HELP, value_parser = parse_listen)] + tcp_listens: Vec, + #[clap(value_name = "ARGS", help = APP_ARGS_HELP)] args: Vec, } @@ -223,7 +240,7 @@ impl CliCommandOpts { &self.input } - pub fn into_config(self, conf: &mut CliConfig) { + pub fn into_config(self, conf: &mut CliConfig) -> Result<()> { conf.0.set_debug_info(self.debug_info); conf.0.set_fs_root_path(self.fs_root_path); conf.0.set_runtime_logger(self.runtime_logger); @@ -266,6 +283,8 @@ impl CliCommandOpts { conf.0 .set_version(blockless::BlocklessConfigVersion::Version1); } + conf.0.tcp_listens = self.tcp_listens; + Ok(()) } } diff --git a/bls-runtime/src/main.rs b/bls-runtime/src/main.rs index b1435f9..7461918 100644 --- a/bls-runtime/src/main.rs +++ b/bls-runtime/src/main.rs @@ -160,7 +160,7 @@ async fn wasm_runtime(mut cfg: CliConfig, cli_command_opts: CliCommandOpts) -> C } let run_time = cfg.0.run_time(); - cli_command_opts.into_config(&mut cfg); + cli_command_opts.into_config(&mut cfg).unwrap(); if cfg.0.is_fixed_stdin() { if let Some(stdin_buffer) = non_blocking_read(std::io::stdin()).await { cfg.0.stdio.stdin = Stdin::Fixed(stdin_buffer); diff --git a/crates/wasi-common/src/blockless/config.rs b/crates/wasi-common/src/blockless/config.rs index 84e433e..2d2ffbd 100644 --- a/crates/wasi-common/src/blockless/config.rs +++ b/crates/wasi-common/src/blockless/config.rs @@ -2,6 +2,7 @@ use crate::Permission; use anyhow::{bail, Ok}; use std::{ collections::HashMap, + net::SocketAddr, path::{Path, PathBuf}, str::FromStr, }; @@ -381,6 +382,7 @@ pub struct BlocklessConfig { pub drivers: Vec, pub store_limited: StoreLimited, pub envs: Vec<(String, String)>, + pub tcp_listens: Vec, pub permisions: Vec, pub fs_root_path: Option, pub modules: Vec, @@ -409,6 +411,7 @@ impl BlocklessConfig { //vm instruction limit. limited_fuel: None, limited_time: None, + tcp_listens: Vec::new(), stdin_args: Vec::new(), //memory limit, 1 page = 64k. store_limited: Default::default(),