diff --git a/Cargo.lock b/Cargo.lock index caf3e710..605bb8a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -482,9 +482,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitvec" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1489fcb93a5bb47da0462ca93ad252ad6af2145cce58d10d46a83931ba9f016b" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", "radium", @@ -705,6 +705,12 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cc" version = "1.0.73" @@ -995,12 +1001,12 @@ dependencies = [ [[package]] name = "criterion" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" +checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" dependencies = [ "atty", - "cast", + "cast 0.3.0", "clap 2.34.0", "criterion-plot", "csv", @@ -1025,7 +1031,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" dependencies = [ - "cast", + "cast 0.2.7", "itertools", ] @@ -3236,9 +3242,9 @@ checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "plotters" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a" +checksum = "9428003b84df1496fb9d6eeee9c5f8145cb41ca375eb0dad204328888832811f" dependencies = [ "num-traits", "plotters-backend", @@ -3249,15 +3255,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" +checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" [[package]] name = "plotters-svg" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9" +checksum = "e0918736323d1baff32ee0eade54984f6f201ad7e97d5cfb5d6ab4a358529615" dependencies = [ "plotters-backend", ] @@ -4220,9 +4226,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.24.5" +version = "0.24.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d80929a3b477bce3a64360ca82bfb361eacce1dcb7b1fb31e8e5e181e37c212" +checksum = "0b6e19da72a8d75be4d40e4dd4686afca31507f26c3ffdf6bd3073278d9de0a0" dependencies = [ "cfg-if 1.0.0", "core-foundation-sys 0.8.3", diff --git a/veilid-core/src/core_context.rs b/veilid-core/src/core_context.rs index f37590a6..bd408f7b 100644 --- a/veilid-core/src/core_context.rs +++ b/veilid-core/src/core_context.rs @@ -5,13 +5,13 @@ use crate::veilid_api::*; use crate::veilid_config::*; use crate::xx::*; -cfg_if! { - if #[cfg(target_arch = "wasm32")] { - pub type UpdateCallback = Arc; - } else { - pub type UpdateCallback = Arc; - } -} +// cfg_if! { +// if #[cfg(target_arch = "wasm32")] { +// pub type UpdateCallback = Arc; +// } else { +pub type UpdateCallback = Arc; +// } +// } struct ServicesContext { pub config: VeilidConfig, diff --git a/veilid-core/src/intf/native/protected_store.rs b/veilid-core/src/intf/native/protected_store.rs index c766b0a7..f4452cda 100644 --- a/veilid-core/src/intf/native/protected_store.rs +++ b/veilid-core/src/intf/native/protected_store.rs @@ -135,7 +135,7 @@ impl ProtectedStore { { Ok(v) => Ok(Some(v)), Err(KeyringError::NoPasswordFound) => Ok(None), - Err(e) => Err(eyre!("Failed to load user secret")), + Err(e) => Err(eyre!("Failed to load user secret: {}", e)), } } @@ -150,7 +150,7 @@ impl ProtectedStore { { Ok(_) => Ok(true), Err(KeyringError::NoPasswordFound) => Ok(false), - Err(e) => Err(eyre!("Failed to remove user secret")), + Err(e) => Err(eyre!("Failed to remove user secret: {}", e)), } } diff --git a/veilid-core/src/intf/table_db.rs b/veilid-core/src/intf/table_db.rs index 88d627d5..d3bdc7d7 100644 --- a/veilid-core/src/intf/table_db.rs +++ b/veilid-core/src/intf/table_db.rs @@ -100,12 +100,7 @@ impl TableDB { return Ok(None); } }; - let obj = match serde_cbor::from_slice::(&b) { - Ok(value) => value, - Err(e) => { - bail!("failed to deserialize"); - } - }; + let obj = serde_cbor::from_slice::(&b).wrap_err("failed to deserialize")?; Ok(Some(obj)) } diff --git a/veilid-core/src/intf/wasm/mod.rs b/veilid-core/src/intf/wasm/mod.rs index 2023e7c1..6b6e6967 100644 --- a/veilid-core/src/intf/wasm/mod.rs +++ b/veilid-core/src/intf/wasm/mod.rs @@ -9,3 +9,4 @@ pub use block_store::*; pub use protected_store::*; pub use system::*; pub use table_store::*; +use utils::*; diff --git a/veilid-core/src/intf/wasm/protected_store.rs b/veilid-core/src/intf/wasm/protected_store.rs index 884fd3c5..51a7619b 100644 --- a/veilid-core/src/intf/wasm/protected_store.rs +++ b/veilid-core/src/intf/wasm/protected_store.rs @@ -1,10 +1,11 @@ -use super::utils; +use super::*; use crate::xx::*; use crate::*; use data_encoding::BASE64URL_NOPAD; use js_sys::*; use wasm_bindgen_futures::*; use web_sys::*; + #[wasm_bindgen] extern "C" { #[wasm_bindgen(catch, js_name = setPassword, js_namespace = ["global", "wasmhost", "keytar"])] @@ -69,10 +70,11 @@ impl ProtectedStore { } pub async fn save_user_secret_string(&self, key: &str, value: &str) -> EyreResult { - if utils::is_nodejs() { + if is_nodejs() { let prev = match JsFuture::from( keytar_getPassword(self.keyring_name().as_str(), key) - .wrap_err("exception thrown")?, + .map_err(map_jsvalue_error) + .wrap_err("exception thrown")?, ) .await { @@ -82,7 +84,8 @@ impl ProtectedStore { match JsFuture::from( keytar_setPassword(self.keyring_name().as_str(), key, value) - .wrap_err("exception thrown")?, + .map_err(map_jsvalue_error) + .wrap_err("exception thrown")?, ) .await { @@ -91,7 +94,7 @@ impl ProtectedStore { } Ok(prev) - } else if utils::is_browser() { + } else if is_browser() { let win = match window() { Some(w) => w, None => { @@ -101,6 +104,7 @@ impl ProtectedStore { let ls = match win .local_storage() + .map_err(map_jsvalue_error) .wrap_err("exception getting local storage")? { Some(l) => l, @@ -113,6 +117,7 @@ impl ProtectedStore { let prev = match ls .get_item(&vkey) + .map_err(map_jsvalue_error) .wrap_err("exception_thrown")? { Some(_) => true, @@ -120,6 +125,7 @@ impl ProtectedStore { }; ls.set_item(&vkey, value) + .map_err(map_jsvalue_error) .wrap_err("exception_thrown")?; Ok(prev) @@ -129,9 +135,10 @@ impl ProtectedStore { } pub async fn load_user_secret_string(&self, key: &str) -> EyreResult> { - if utils::is_nodejs() { + if is_nodejs() { let prev = match JsFuture::from( keytar_getPassword(self.keyring_name().as_str(), key) + .map_err(map_jsvalue_error) .wrap_err("exception thrown")?, ) .await @@ -145,7 +152,7 @@ impl ProtectedStore { } Ok(prev.as_string()) - } else if utils::is_browser() { + } else if is_browser() { let win = match window() { Some(w) => w, None => { @@ -155,6 +162,7 @@ impl ProtectedStore { let ls = match win .local_storage() + .map_err(map_jsvalue_error) .wrap_err("exception getting local storage")? { Some(l) => l, @@ -166,6 +174,7 @@ impl ProtectedStore { let vkey = self.browser_key_name(key); ls.get_item(&vkey) + .map_err(map_jsvalue_error) .wrap_err("exception_thrown") } else { unimplemented!(); @@ -173,16 +182,18 @@ impl ProtectedStore { } pub async fn remove_user_secret_string(&self, key: &str) -> EyreResult { - if utils::is_nodejs() { + if is_nodejs() { match JsFuture::from( - keytar_deletePassword(self.keyring_name().as_str(), key).wrap_err("exception thrown")?, + keytar_deletePassword(self.keyring_name().as_str(), key) + .map_err(map_jsvalue_error) + .wrap_err("exception thrown")?, ) .await { Ok(v) => Ok(v.is_truthy()), Err(_) => bail!("Failed to delete"), } - } else if utils::is_browser() { + } else if is_browser() { let win = match window() { Some(w) => w, None => { @@ -192,6 +203,7 @@ impl ProtectedStore { let ls = match win .local_storage() + .map_err(map_jsvalue_error) .wrap_err("exception getting local storage")? { Some(l) => l, @@ -204,10 +216,12 @@ impl ProtectedStore { match ls .get_item(&vkey) + .map_err(map_jsvalue_error) .wrap_err("exception_thrown")? { Some(_) => { ls.delete(&vkey) + .map_err(map_jsvalue_error) .wrap_err("exception_thrown")?; Ok(true) } diff --git a/veilid-core/src/intf/wasm/system.rs b/veilid-core/src/intf/wasm/system.rs index 541d3ebe..a56c50ce 100644 --- a/veilid-core/src/intf/wasm/system.rs +++ b/veilid-core/src/intf/wasm/system.rs @@ -2,7 +2,6 @@ use super::utils; use crate::xx::*; use crate::*; use async_executors::{Bindgen, LocalSpawnHandleExt /*, SpawnHandleExt*/}; -use core::fmt; use futures_util::future::{select, Either}; use js_sys::*; use wasm_bindgen_futures::*; diff --git a/veilid-core/src/intf/wasm/table_store.rs b/veilid-core/src/intf/wasm/table_store.rs index 51c6bda1..f83e38ef 100644 --- a/veilid-core/src/intf/wasm/table_store.rs +++ b/veilid-core/src/intf/wasm/table_store.rs @@ -28,7 +28,7 @@ impl TableStore { } } - pub async fn init(&self) -> Result<(), String> { + pub async fn init(&self) -> EyreResult<()> { Ok(()) } @@ -49,12 +49,12 @@ impl TableStore { } } - fn get_table_name(&self, table: &str) -> Result { + fn get_table_name(&self, table: &str) -> EyreResult { if !table .chars() .all(|c| char::is_alphanumeric(c) || c == '_' || c == '-') { - return Err(format!("table name '{}' is invalid", table)); + bail!("table name '{}' is invalid", table); } let c = self.config.get(); let namespace = c.namespace.clone(); @@ -65,7 +65,7 @@ impl TableStore { }) } - pub async fn open(&self, name: &str, column_count: u32) -> Result { + pub async fn open(&self, name: &str, column_count: u32) -> EyreResult { let table_name = self.get_table_name(name)?; let mut inner = self.inner.lock(); @@ -81,7 +81,7 @@ impl TableStore { } let db = Database::open(table_name.clone(), column_count) .await - .map_err(|e| format!("failed to open tabledb at: {} ({})", table_name, e))?; + .wrap_err("failed to open tabledb")?; info!("opened table store '{}' with table name '{:?}' with {} columns", name, table_name, column_count); let table_db = TableDB::new(table_name.clone(), self.clone(), db); @@ -91,7 +91,7 @@ impl TableStore { Ok(table_db) } - pub async fn delete(&self, name: &str) -> Result { + pub async fn delete(&self, name: &str) -> EyreResult { trace!("TableStore::delete {}", name); let table_name = self.get_table_name(name)?; @@ -101,11 +101,11 @@ impl TableStore { "TableStore::delete {}: Not deleting, still open.", table_name ); - return Err("Not deleting table that is still opened".to_owned()); + bail!("Not deleting table that is still opened"); } if utils::is_nodejs() { - Err("unimplemented".to_owned()) + unimplemented!(); } else if utils::is_browser() { let out = match Database::delete(table_name.clone()).await { Ok(_) => true, @@ -115,7 +115,7 @@ impl TableStore { trace!("TableStore::deleted {}", table_name); Ok(out) } else { - Err("unimplemented".to_owned()) + unimplemented!(); } } } diff --git a/veilid-core/src/intf/wasm/utils/mod.rs b/veilid-core/src/intf/wasm/utils/mod.rs index a29d4481..dc8be425 100644 --- a/veilid-core/src/intf/wasm/utils/mod.rs +++ b/veilid-core/src/intf/wasm/utils/mod.rs @@ -77,3 +77,11 @@ pub fn node_require(module: &str) -> JsValue { } } } + +#[derive(ThisError, Debug, Clone, Eq, PartialEq)] +#[error("JsValue error")] +pub struct JsValueError(String); + +pub fn map_jsvalue_error(x: JsValue) -> JsValueError { + JsValueError(x.as_string().unwrap_or_default()) +} diff --git a/veilid-core/src/network_manager/wasm/mod.rs b/veilid-core/src/network_manager/wasm/mod.rs index 4157d168..03547b2b 100644 --- a/veilid-core/src/network_manager/wasm/mod.rs +++ b/veilid-core/src/network_manager/wasm/mod.rs @@ -34,14 +34,17 @@ impl Network { } } - pub fn new(network_manager: NetworkManager) -> Self { + pub fn new( + network_manager: NetworkManager, + routing_table: RoutingTable, + connection_manager: ConnectionManager, + ) -> Self { Self { config: network_manager.config(), inner: Arc::new(Mutex::new(Self::new_inner(network_manager))), } } - fn network_manager(&self) -> NetworkManager { self.inner.lock().network_manager.clone() } @@ -61,14 +64,15 @@ impl Network { let res = match dial_info.protocol_type() { ProtocolType::UDP => { - return Err("no support for UDP protocol".to_owned()).map_err(logthru_net!(error)) + bail!("no support for UDP protocol") } ProtocolType::TCP => { - return Err("no support for TCP protocol".to_owned()).map_err(logthru_net!(error)) + bail!("no support for TCP protocol") } ProtocolType::WS | ProtocolType::WSS => { WebsocketProtocolHandler::send_unbound_message(dial_info.clone(), data) .await + .wrap_err("failed to send unbound message") } }; if res.is_ok() { @@ -94,10 +98,10 @@ impl Network { let data_len = data.len(); let out = match dial_info.protocol_type() { ProtocolType::UDP => { - return Err("no support for UDP protocol".to_owned()).map_err(logthru_net!(error)) + bail!("no support for UDP protocol") } ProtocolType::TCP => { - return Err("no support for TCP protocol".to_owned()).map_err(logthru_net!(error)) + bail!("no support for TCP protocol") } ProtocolType::WS | ProtocolType::WSS => { WebsocketProtocolHandler::send_recv_unbound_message( @@ -128,14 +132,14 @@ impl Network { let data_len = data.len(); match descriptor.protocol_type() { ProtocolType::UDP => { - return Err("no support for udp protocol".to_owned()).map_err(logthru_net!(error)) + bail!("no support for UDP protocol") } ProtocolType::TCP => { - return Err("no support for tcp protocol".to_owned()).map_err(logthru_net!(error)) + bail!("no support for TCP protocol") } _ => {} } - + // Handle connection-oriented protocols // Try to send to the exact existing connection if one exists @@ -164,10 +168,10 @@ impl Network { ) -> EyreResult<()> { let data_len = data.len(); if dial_info.protocol_type() == ProtocolType::UDP { - return Err("no support for UDP protocol".to_owned()).map_err(logthru_net!(error)) + bail!("no support for UDP protocol"); } if dial_info.protocol_type() == ProtocolType::TCP { - return Err("no support for TCP protocol".to_owned()).map_err(logthru_net!(error)) + bail!("no support for TCP protocol"); } // Handle connection-oriented protocols @@ -176,7 +180,7 @@ impl Network { .get_or_create_connection(None, dial_info.clone()) .await?; - let res = conn.send_async(data).await.map_err(logthru_net!(error)); + let res = conn.send_async(data).await; if res.is_ok() { // Network accounting self.network_manager() @@ -215,7 +219,7 @@ impl Network { pub fn is_started(&self) -> bool { self.inner.lock().network_started } - + pub fn restart_network(&self) { self.inner.lock().network_needs_restart = true; } @@ -247,8 +251,7 @@ impl Network { pub async fn check_interface_addresses(&self) -> Result { Ok(false) } - - + ////////////////////////////////////////// pub fn get_network_class(&self) -> Option { // xxx eventually detect tor browser? diff --git a/veilid-core/src/network_manager/wasm/protocol/mod.rs b/veilid-core/src/network_manager/wasm/protocol/mod.rs index 778870ed..fe88d2e5 100644 --- a/veilid-core/src/network_manager/wasm/protocol/mod.rs +++ b/veilid-core/src/network_manager/wasm/protocol/mod.rs @@ -3,6 +3,7 @@ pub mod ws; use super::*; use crate::xx::*; +use std::io; #[derive(Debug)] pub enum ProtocolNetworkConnection { diff --git a/veilid-core/src/network_manager/wasm/protocol/ws.rs b/veilid-core/src/network_manager/wasm/protocol/ws.rs index 7ff4b42e..2699f8fc 100644 --- a/veilid-core/src/network_manager/wasm/protocol/ws.rs +++ b/veilid-core/src/network_manager/wasm/protocol/ws.rs @@ -1,7 +1,7 @@ use super::*; -use ws_stream_wasm::*; -use futures_util::{StreamExt, SinkExt}; +use futures_util::{SinkExt, StreamExt}; use std::io; +use ws_stream_wasm::*; struct WebsocketNetworkConnectionInner { ws_meta: WsMeta, @@ -9,9 +9,7 @@ struct WebsocketNetworkConnectionInner { } fn to_io(err: WsErr) -> io::Error { - let kind = match err { - WsErr::InvalidWsState {supplied:_} => io::ErrorKind:: - } + io::Error::new(io::ErrorKind::Other, err.to_string()) } #[derive(Clone)] @@ -27,9 +25,7 @@ impl fmt::Debug for WebsocketNetworkConnection { } impl WebsocketNetworkConnection { - pub fn new( - descriptor: ConnectionDescriptor, - ws_meta: WsMeta, ws_stream: WsStream) -> Self { + pub fn new(descriptor: ConnectionDescriptor, ws_meta: WsMeta, ws_stream: WsStream) -> Self { Self { descriptor, inner: Arc::new(WebsocketNetworkConnectionInner { @@ -53,28 +49,29 @@ impl WebsocketNetworkConnection { if message.len() > MAX_MESSAGE_SIZE { bail_io_error_other!("sending too large WS message"); } - self.inner.ws_stream.clone() - .send(WsMessage::Binary(message)).await - .map_err(|_| "failed to send to websocket".to_owned()) - .map_err(logthru_net!(error)) + self.inner + .ws_stream + .clone() + .send(WsMessage::Binary(message)) + .await + .map_err(to_io) } #[instrument(level = "trace", err, skip(self), fields(ret.len))] - pub async fn recv(&self) -> Result, String> { + pub async fn recv(&self) -> io::Result> { let out = match self.inner.ws_stream.clone().next().await { Some(WsMessage::Binary(v)) => v, Some(x) => { - return Err(format!("Unexpected WS message type: {:?}", x)); + bail_io_error_other!("Unexpected WS message type"); } None => { - return Err("WS stream closed".to_owned()).map_err(logthru_net!(error)); + bail_io_error_other!("WS stream closed"); } }; if out.len() > MAX_MESSAGE_SIZE { - Err("sending too large WS message".to_owned()).map_err(logthru_net!(error)) - } else { - Ok(out) + bail_io_error_other!("sending too large WS message") } + Ok(out) } } @@ -88,8 +85,7 @@ impl WebsocketProtocolHandler { pub async fn connect( local_address: Option, dial_info: DialInfo, - ) -> Result { - + ) -> io::Result { assert!(local_address.is_none()); // Split dial info up @@ -99,34 +95,33 @@ impl WebsocketProtocolHandler { _ => panic!("invalid dialinfo for WS/WSS protocol"), }; let request = dial_info.request().unwrap(); - let split_url = SplitUrl::from_str(&request)?; + let split_url = SplitUrl::from_str(&request).map_err(to_io_error_other)?; if split_url.scheme != scheme { - return Err("invalid websocket url scheme".to_string()); + bail_io_error_other!("invalid websocket url scheme"); } - - let (wsmeta, wsio) = WsMeta::connect(request, None) - .await - .map_err(map_to_string) - .map_err(logthru_net!(error))?; + + let (wsmeta, wsio) = WsMeta::connect(request, None).await.map_err(to_io)?; // Make our connection descriptor - Ok(ProtocolNetworkConnection::Ws(WebsocketNetworkConnection::new(ConnectionDescriptor::new_no_local( - dial_info.to_peer_address(), - ), wsmeta, wsio))) + Ok(ProtocolNetworkConnection::Ws( + WebsocketNetworkConnection::new( + ConnectionDescriptor::new_no_local(dial_info.to_peer_address()), + wsmeta, + wsio, + ), + )) } #[instrument(level = "trace", err, skip(data), fields(data.len = data.len()))] - pub async fn send_unbound_message(dial_info: DialInfo, data: Vec) -> Result<(), String> { + pub async fn send_unbound_message(dial_info: DialInfo, data: Vec) -> io::Result<()> { if data.len() > MAX_MESSAGE_SIZE { - return Err("sending too large unbound WS message".to_owned()); + bail_io_error_other!("sending too large unbound WS message"); } - - // Make the real connection - let conn = Self::connect(None, dial_info) - .await - .map_err(|e| format!("failed to connect websocket for unbound message: {}", e))?; - conn.send(data).await + // Make the real connection + let conn = Self::connect(None, dial_info).await?; + + conn.send(data).await } #[instrument(level = "trace", err, skip(data), fields(data.len = data.len(), ret.len))] @@ -134,23 +129,19 @@ impl WebsocketProtocolHandler { dial_info: DialInfo, data: Vec, timeout_ms: u32, - ) -> Result, String> { + ) -> io::Result> { if data.len() > MAX_MESSAGE_SIZE { - return Err("sending too large unbound WS message".to_owned()); + bail_io_error_other!("sending too large unbound WS message"); } - let conn = Self::connect(None, dial_info.clone()) - .await - .map_err(|e| format!("failed to connect websocket for unbound message: {}", e))?; + let conn = Self::connect(None, dial_info.clone()).await?; conn.send(data).await?; let out = timeout(timeout_ms, conn.recv()) .await - .map_err(map_to_string)??; + .map_err(|e| e.to_io())??; tracing::Span::current().record("ret.len", &out.len()); Ok(out) } - - }