From 7e0d7dad06dd035ce8c8f4016acaf25ed96b532f Mon Sep 17 00:00:00 2001 From: John Smith Date: Sun, 10 Jul 2022 17:36:50 -0400 Subject: [PATCH] refactor --- Cargo.lock | 2 +- veilid-core/Cargo.toml | 2 +- veilid-core/src/attachment_manager.rs | 2 +- veilid-core/src/core_context.rs | 16 +- veilid-core/src/dht/crypto.rs | 24 +- veilid-core/src/dht/envelope.rs | 117 +++++----- veilid-core/src/dht/receipt.rs | 80 ++++--- veilid-core/src/intf/native/block_store.rs | 2 +- .../src/intf/native/protected_store.rs | 46 ++-- veilid-core/src/intf/native/system.rs | 37 ++- veilid-core/src/intf/native/table_store.rs | 24 +- .../native/utils/network_interfaces/apple.rs | 22 +- .../native/utils/network_interfaces/mod.rs | 2 +- .../utils/network_interfaces/netlink.rs | 38 ++-- .../utils/network_interfaces/windows.rs | 6 +- veilid-core/src/intf/table_db.rs | 43 ++-- veilid-core/src/intf/wasm/block_store.rs | 2 +- veilid-core/src/intf/wasm/protected_store.rs | 68 +++--- veilid-core/src/intf/wasm/system.rs | 25 +- .../src/network_manager/connection_handle.rs | 10 +- .../src/network_manager/connection_limits.rs | 26 +-- .../src/network_manager/connection_manager.rs | 10 +- .../src/network_manager/connection_table.rs | 51 ++++- veilid-core/src/network_manager/mod.rs | 214 ++++++++---------- veilid-core/src/network_manager/native/mod.rs | 42 ++-- .../native/network_class_discovery.rs | 10 +- .../src/network_manager/native/network_tcp.rs | 34 +-- .../src/network_manager/native/network_udp.rs | 20 +- .../network_manager/native/protocol/mod.rs | 11 +- .../native/protocol/sockets.rs | 94 +++----- .../network_manager/native/protocol/tcp.rs | 70 ++---- .../network_manager/native/protocol/udp.rs | 117 ++++------ .../src/network_manager/native/protocol/ws.rs | 125 +++++----- .../network_manager/native/start_protocols.rs | 73 +++--- .../src/network_manager/network_connection.rs | 25 +- veilid-core/src/network_manager/wasm/mod.rs | 12 +- .../src/network_manager/wasm/protocol/mod.rs | 22 +- .../src/network_manager/wasm/protocol/ws.rs | 19 +- veilid-core/src/receipt_manager.rs | 12 +- veilid-core/src/routing_table/mod.rs | 80 ++----- veilid-core/src/routing_table/tasks.rs | 48 ++-- .../src/rpc_processor/coders/address.rs | 8 +- .../src/rpc_processor/coders/block_id.rs | 18 +- .../src/rpc_processor/coders/dial_info.rs | 43 ++-- .../rpc_processor/coders/dial_info_detail.rs | 9 +- .../rpc_processor/coders/node_dial_info.rs | 16 +- .../src/rpc_processor/coders/node_info.rs | 14 +- .../rpc_processor/coders/operations/answer.rs | 22 +- .../coders/operations/operation.rs | 10 +- .../operations/operation_cancel_tunnel.rs | 4 +- .../operations/operation_complete_tunnel.rs | 13 +- .../coders/operations/operation_find_block.rs | 19 +- .../coders/operations/operation_find_node.rs | 8 +- .../coders/operations/operation_get_value.rs | 12 +- .../operations/operation_node_info_update.rs | 4 +- .../operations/operation_return_receipt.rs | 2 +- .../coders/operations/operation_route.rs | 19 +- .../coders/operations/operation_set_value.rs | 14 +- .../operations/operation_start_tunnel.rs | 11 +- .../coders/operations/operation_status.rs | 6 +- .../operations/operation_supply_block.rs | 10 +- .../operation_validate_dial_info.rs | 4 +- .../operations/operation_value_changed.rs | 4 +- .../operations/operation_watch_value.rs | 8 +- .../coders/operations/question.rs | 22 +- .../coders/operations/respond_to.rs | 19 +- .../coders/operations/statement.rs | 14 +- .../src/rpc_processor/coders/peer_info.rs | 4 +- .../coders/private_safety_route.rs | 49 ++-- .../src/rpc_processor/coders/public_key.rs | 10 +- .../src/rpc_processor/coders/sender_info.rs | 6 +- .../src/rpc_processor/coders/signal_info.rs | 36 ++- .../rpc_processor/coders/signed_node_info.rs | 6 +- .../rpc_processor/coders/socket_address.rs | 2 +- .../src/rpc_processor/coders/tunnel.rs | 10 +- .../src/rpc_processor/coders/value_data.rs | 5 +- .../src/rpc_processor/coders/value_key.rs | 4 +- veilid-core/src/rpc_processor/debug.rs | 92 -------- veilid-core/src/rpc_processor/mod.rs | 64 +++--- .../src/rpc_processor/private_route.rs | 14 +- .../src/rpc_processor/rpc_cancel_tunnel.rs | 2 +- .../src/rpc_processor/rpc_complete_tunnel.rs | 2 +- veilid-core/src/rpc_processor/rpc_error.rs | 58 +++++ .../src/rpc_processor/rpc_find_block.rs | 2 +- .../src/rpc_processor/rpc_find_node.rs | 6 +- .../src/rpc_processor/rpc_get_value.rs | 2 +- .../src/rpc_processor/rpc_node_info_update.rs | 3 +- .../src/rpc_processor/rpc_return_receipt.rs | 2 +- veilid-core/src/rpc_processor/rpc_route.rs | 2 +- .../src/rpc_processor/rpc_set_value.rs | 2 +- veilid-core/src/rpc_processor/rpc_signal.rs | 2 +- .../src/rpc_processor/rpc_start_tunnel.rs | 2 +- veilid-core/src/rpc_processor/rpc_status.rs | 4 +- .../src/rpc_processor/rpc_supply_block.rs | 2 +- .../rpc_processor/rpc_validate_dial_info.rs | 13 +- .../src/rpc_processor/rpc_value_changed.rs | 2 +- .../src/rpc_processor/rpc_watch_value.rs | 2 +- .../src/tests/common/test_protected_store.rs | 56 ++--- .../src/tests/common/test_table_store.rs | 45 ++-- veilid-core/src/veilid_api/mod.rs | 122 ++-------- veilid-core/src/xx/mod.rs | 5 + veilid-core/src/xx/split_url.rs | 50 ++-- veilid-core/src/xx/tick_task.rs | 48 ++-- veilid-core/src/xx/timeout_or.rs | 98 ++++++++ veilid-core/src/xx/tools.rs | 55 +++-- veilid-flutter/rust/src/tools.rs | 4 +- veilid-server/src/settings.rs | 2 - veilid-server/src/tools.rs | 2 +- 108 files changed, 1378 insertions(+), 1535 deletions(-) delete mode 100644 veilid-core/src/rpc_processor/debug.rs create mode 100644 veilid-core/src/rpc_processor/rpc_error.rs create mode 100644 veilid-core/src/xx/timeout_or.rs diff --git a/Cargo.lock b/Cargo.lock index 9e28534c..caf3e710 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4930,7 +4930,6 @@ dependencies = [ "chacha20 0.9.0", "chacha20poly1305", "chrono", - "color-eyre", "config", "console_error_panic_hook", "curve25519-dalek-ng", @@ -4939,6 +4938,7 @@ dependencies = [ "directories", "ed25519-dalek", "enumset", + "eyre", "flume", "futures-util", "generic-array 0.14.5", diff --git a/veilid-core/Cargo.toml b/veilid-core/Cargo.toml index 558a15c2..cdda10dc 100644 --- a/veilid-core/Cargo.toml +++ b/veilid-core/Cargo.toml @@ -22,7 +22,7 @@ tracking = [ "backtrace" ] tracing = { version = "^0", features = ["log", "attributes"] } tracing-subscriber = "^0" tracing-error = "^0" -color-eyre = "^0" +eyre = "^0" capnp = { version = "^0", default_features = false } rust-fsm = "^0" static_assertions = "^1" diff --git a/veilid-core/src/attachment_manager.rs b/veilid-core/src/attachment_manager.rs index 48576901..4b372f7f 100644 --- a/veilid-core/src/attachment_manager.rs +++ b/veilid-core/src/attachment_manager.rs @@ -277,7 +277,7 @@ impl AttachmentManager { } #[instrument(level = "debug", skip_all, err)] - pub async fn init(&self, update_callback: UpdateCallback) -> Result<(), String> { + pub async fn init(&self, update_callback: UpdateCallback) -> EyreResult<()> { trace!("init"); let network_manager = { let mut inner = self.inner.lock(); diff --git a/veilid-core/src/core_context.rs b/veilid-core/src/core_context.rs index 7647fb37..f37590a6 100644 --- a/veilid-core/src/core_context.rs +++ b/veilid-core/src/core_context.rs @@ -58,7 +58,7 @@ impl ServicesContext { } #[instrument(err, skip_all)] - pub async fn startup(&mut self) -> Result<(), VeilidAPIError> { + pub async fn startup(&mut self) -> EyreResult<()> { info!("Veilid API starting up"); info!("init api tracing"); @@ -69,14 +69,14 @@ impl ServicesContext { let protected_store = ProtectedStore::new(self.config.clone()); if let Err(e) = protected_store.init().await { self.shutdown().await; - return Err(VeilidAPIError::Internal { message: e }); + return Err(e); } self.protected_store = Some(protected_store.clone()); // Init node id from config now that protected store is set up if let Err(e) = self.config.init_node_id(protected_store.clone()).await { self.shutdown().await; - return Err(e); + return Err(e).wrap_err("init node id failed"); } // Set up tablestore @@ -84,7 +84,7 @@ impl ServicesContext { let table_store = TableStore::new(self.config.clone()); if let Err(e) = table_store.init().await { self.shutdown().await; - return Err(VeilidAPIError::Internal { message: e }); + return Err(e); } self.table_store = Some(table_store.clone()); @@ -93,7 +93,7 @@ impl ServicesContext { let crypto = Crypto::new(self.config.clone(), table_store.clone()); if let Err(e) = crypto.init().await { self.shutdown().await; - return Err(VeilidAPIError::Internal { message: e }); + return Err(e); } self.crypto = Some(crypto.clone()); @@ -102,7 +102,7 @@ impl ServicesContext { let block_store = BlockStore::new(self.config.clone()); if let Err(e) = block_store.init().await { self.shutdown().await; - return Err(VeilidAPIError::Internal { message: e }); + return Err(e); } self.block_store = Some(block_store.clone()); @@ -112,7 +112,7 @@ impl ServicesContext { let attachment_manager = AttachmentManager::new(self.config.clone(), table_store, crypto); if let Err(e) = attachment_manager.init(update_callback).await { self.shutdown().await; - return Err(VeilidAPIError::Internal { message: e }); + return Err(e); } self.attachment_manager = Some(attachment_manager); @@ -209,7 +209,7 @@ impl VeilidCoreContext { } let mut sc = ServicesContext::new_empty(config.clone(), update_callback); - sc.startup().await?; + sc.startup().await.map_err(VeilidAPIError::generic)?; Ok(VeilidCoreContext { update_callback: sc.update_callback, diff --git a/veilid-core/src/dht/crypto.rs b/veilid-core/src/dht/crypto.rs index 0ddb8ad5..4040c1a7 100644 --- a/veilid-core/src/dht/crypto.rs +++ b/veilid-core/src/dht/crypto.rs @@ -91,7 +91,7 @@ impl Crypto { } } - pub async fn init(&self) -> Result<(), String> { + pub async fn init(&self) -> EyreResult<()> { trace!("Crypto::init"); // make local copy of node id for easy access @@ -136,7 +136,7 @@ impl Crypto { Ok(()) } - pub async fn flush(&self) -> Result<(), String> { + pub async fn flush(&self) -> EyreResult<()> { //trace!("Crypto::flush"); let (table_store, cache_bytes) = { let inner = self.inner.lock(); @@ -166,23 +166,27 @@ impl Crypto { }; } - fn ed25519_to_x25519_pk(key: &ed::PublicKey) -> Result { + fn ed25519_to_x25519_pk(key: &ed::PublicKey) -> Result { let bytes = key.to_bytes(); let compressed = cd::edwards::CompressedEdwardsY(bytes); let point = compressed .decompress() - .ok_or_else(fn_string!("ed25519_to_x25519_pk failed"))?; + .ok_or_else(|| VeilidAPIError::internal("ed25519_to_x25519_pk failed"))?; let mp = point.to_montgomery(); Ok(xd::PublicKey::from(mp.to_bytes())) } - fn ed25519_to_x25519_sk(key: &ed::SecretKey) -> Result { + fn ed25519_to_x25519_sk(key: &ed::SecretKey) -> Result { let exp = ed::ExpandedSecretKey::from(key); let bytes: [u8; ed::EXPANDED_SECRET_KEY_LENGTH] = exp.to_bytes(); - let lowbytes: [u8; 32] = bytes[0..32].try_into().map_err(map_to_string)?; + let lowbytes: [u8; 32] = bytes[0..32].try_into().map_err(VeilidAPIError::internal)?; Ok(xd::StaticSecret::from(lowbytes)) } - pub fn cached_dh(&self, key: &DHTKey, secret: &DHTKeySecret) -> Result { + pub fn cached_dh( + &self, + key: &DHTKey, + secret: &DHTKeySecret, + ) -> Result { Ok( match self.inner.lock().dh_cache.entry(DHCacheKey { key: *key, @@ -201,12 +205,12 @@ impl Crypto { /////////// // These are safe to use regardless of initialization status - pub fn compute_dh(key: &DHTKey, secret: &DHTKeySecret) -> Result { + pub fn compute_dh(key: &DHTKey, secret: &DHTKeySecret) -> Result { assert!(key.valid); assert!(secret.valid); - let pk_ed = ed::PublicKey::from_bytes(&key.bytes).map_err(map_to_string)?; + let pk_ed = ed::PublicKey::from_bytes(&key.bytes).map_err(VeilidAPIError::internal)?; let pk_xd = Self::ed25519_to_x25519_pk(&pk_ed)?; - let sk_ed = ed::SecretKey::from_bytes(&secret.bytes).map_err(map_to_string)?; + let sk_ed = ed::SecretKey::from_bytes(&secret.bytes).map_err(VeilidAPIError::internal)?; let sk_xd = Self::ed25519_to_x25519_sk(&sk_ed)?; Ok(sk_xd.diffie_hellman(&pk_xd).to_bytes()) } diff --git a/veilid-core/src/dht/envelope.rs b/veilid-core/src/dht/envelope.rs index 7d70a203..d94fbf06 100644 --- a/veilid-core/src/dht/envelope.rs +++ b/veilid-core/src/dht/envelope.rs @@ -3,6 +3,7 @@ use super::crypto::*; use super::key::*; use crate::xx::*; +use crate::*; use core::convert::TryInto; // #[repr(C, packed)] @@ -76,89 +77,103 @@ impl Envelope { } } - pub fn from_signed_data(data: &[u8]) -> Result { + pub fn from_signed_data(data: &[u8]) -> Result { // Ensure we are at least the length of the envelope // Silent drop here, as we use zero length packets as part of the protocol for hole punching if data.len() < MIN_ENVELOPE_SIZE { - return Err(()); + return Err(VeilidAPIError::generic("envelope data too small")); } // Verify magic number - let magic: [u8; 4] = data[0x00..0x04].try_into().map_err(drop)?; + let magic: [u8; 4] = data[0x00..0x04] + .try_into() + .map_err(VeilidAPIError::internal)?; if magic != *ENVELOPE_MAGIC { - trace!("bad magic number: len={:?}", magic); - return Err(()); + return Err(VeilidAPIError::generic("bad magic number")); } // Check version let version = data[0x04]; if version > MAX_VERSION || version < MIN_VERSION { - trace!("unsupported protocol version: version={}", version); - return Err(()); + return Err(VeilidAPIError::parse_error( + "unsupported protocol version", + version, + )); } // Get min version let min_version = data[0x05]; if min_version > version { - trace!( - "invalid version information in envelope: min_version={}, version={}", - min_version, - version, - ); - return Err(()); + return Err(VeilidAPIError::parse_error("version too low", version)); } // Get max version let max_version = data[0x06]; - if version > max_version || min_version > max_version { - trace!( - "invalid version information in envelope: min_version={}, version={}, max_version={}", - min_version, - version, - max_version - ); - return Err(()); + if version > max_version { + return Err(VeilidAPIError::parse_error("version too high", version)); + } + if min_version > max_version { + return Err(VeilidAPIError::generic("version information invalid")); } // Get size and ensure it matches the size of the envelope and is less than the maximum message size - let size: u16 = u16::from_le_bytes(data[0x08..0x0A].try_into().map_err(drop)?); + let size: u16 = u16::from_le_bytes( + data[0x08..0x0A] + .try_into() + .map_err(VeilidAPIError::internal)?, + ); if (size as usize) > MAX_ENVELOPE_SIZE { - trace!("envelope size is too large: size={}", size); - return Err(()); + return Err(VeilidAPIError::parse_error("envelope too large", size)); } if (size as usize) != data.len() { - trace!( - "size doesn't match envelope size: size={} data.len()={}", - size, - data.len() - ); - return Err(()); + return Err(VeilidAPIError::parse_error( + "size doesn't match envelope size", + format!( + "size doesn't match envelope size: size={} data.len()={}", + size, + data.len() + ), + )); } // Get the timestamp - let timestamp: u64 = u64::from_le_bytes(data[0x0A..0x12].try_into().map_err(drop)?); + let timestamp: u64 = u64::from_le_bytes( + data[0x0A..0x12] + .try_into() + .map_err(VeilidAPIError::internal)?, + ); // Get nonce and sender node id - let nonce: EnvelopeNonce = data[0x12..0x2A].try_into().map_err(drop)?; - let sender_id_slice: [u8; 32] = data[0x2A..0x4A].try_into().map_err(drop)?; - let recipient_id_slice: [u8; 32] = data[0x4A..0x6A].try_into().map_err(drop)?; + let nonce: EnvelopeNonce = data[0x12..0x2A] + .try_into() + .map_err(VeilidAPIError::internal)?; + let sender_id_slice: [u8; 32] = data[0x2A..0x4A] + .try_into() + .map_err(VeilidAPIError::internal)?; + let recipient_id_slice: [u8; 32] = data[0x4A..0x6A] + .try_into() + .map_err(VeilidAPIError::internal)?; let sender_id = DHTKey::new(sender_id_slice); let recipient_id = DHTKey::new(recipient_id_slice); // Ensure sender_id and recipient_id are not the same if sender_id == recipient_id { - trace!( - "sender_id should not be same as recipient_id: {}", - recipient_id.encode() - ); - return Err(()); + return Err(VeilidAPIError::parse_error( + "sender_id should not be same as recipient_id", + recipient_id.encode(), + )); } // Get signature - let signature = DHTSignature::new(data[(data.len() - 64)..].try_into().map_err(drop)?); + let signature = DHTSignature::new( + data[(data.len() - 64)..] + .try_into() + .map_err(VeilidAPIError::internal)?, + ); // Validate signature - verify(&sender_id, &data[0..(data.len() - 64)], &signature).map_err(drop)?; + verify(&sender_id, &data[0..(data.len() - 64)], &signature) + .map_err(VeilidAPIError::internal)?; // Return envelope Ok(Self { @@ -177,7 +192,7 @@ impl Envelope { crypto: Crypto, data: &[u8], node_id_secret: &DHTKeySecret, - ) -> Result, String> { + ) -> Result, VeilidAPIError> { // Get DH secret let dh_secret = crypto.cached_dh(&self.sender_id, node_id_secret)?; @@ -192,20 +207,23 @@ impl Envelope { crypto: Crypto, body: &[u8], node_id_secret: &DHTKeySecret, - ) -> Result, ()> { + ) -> Result, VeilidAPIError> { // Ensure sender node id is valid if !self.sender_id.valid { - return Err(()); + return Err(VeilidAPIError::generic("sender id is invalid")); } // Ensure recipient node id is valid if !self.recipient_id.valid { - return Err(()); + return Err(VeilidAPIError::generic("recipient id is invalid")); } // Ensure body isn't too long let envelope_size: usize = body.len() + MIN_ENVELOPE_SIZE; if envelope_size > MAX_ENVELOPE_SIZE { - return Err(()); + return Err(VeilidAPIError::parse_error( + "envelope size is too large", + envelope_size, + )); } let mut data = vec![0u8; envelope_size]; @@ -229,9 +247,7 @@ impl Envelope { data[0x4A..0x6A].copy_from_slice(&self.recipient_id.bytes); // Generate dh secret - let dh_secret = crypto - .cached_dh(&self.recipient_id, node_id_secret) - .map_err(drop)?; + let dh_secret = crypto.cached_dh(&self.recipient_id, node_id_secret)?; // Encrypt and authenticate message let encrypted_body = Crypto::crypt_no_auth(body, &self.nonce, &dh_secret); @@ -246,8 +262,7 @@ impl Envelope { &self.sender_id, node_id_secret, &data[0..(envelope_size - 64)], - ) - .map_err(drop)?; + )?; // Append the signature data[(envelope_size - 64)..].copy_from_slice(&signature.bytes); diff --git a/veilid-core/src/dht/receipt.rs b/veilid-core/src/dht/receipt.rs index 0a6a8554..74d806cb 100644 --- a/veilid-core/src/dht/receipt.rs +++ b/veilid-core/src/dht/receipt.rs @@ -3,6 +3,7 @@ use super::envelope::{MAX_VERSION, MIN_VERSION}; use super::key::*; use crate::xx::*; +use crate::*; use core::convert::TryInto; use data_encoding::BASE64URL_NOPAD; @@ -57,10 +58,13 @@ impl Receipt { nonce: ReceiptNonce, sender_id: DHTKey, extra_data: D, - ) -> Result { + ) -> Result { assert!(sender_id.valid); if extra_data.as_ref().len() > MAX_EXTRA_DATA_SIZE { - return Err("extra data too large for receipt".to_owned()); + return Err(VeilidAPIError::parse_error( + "extra data too large for receipt", + extra_data.as_ref().len(), + )); } Ok(Self { version, @@ -70,53 +74,70 @@ impl Receipt { }) } - pub fn from_signed_data(data: &[u8]) -> Result { + pub fn from_signed_data(data: &[u8]) -> Result { // Ensure we are at least the length of the envelope if data.len() < MIN_RECEIPT_SIZE { - trace!("receipt too small: len={}", data.len()); - return Err(()); + return Err(VeilidAPIError::parse_error("receipt too small", data.len())); } // Verify magic number - let magic: [u8; 4] = data[0x00..0x04].try_into().map_err(drop)?; + let magic: [u8; 4] = data[0x00..0x04] + .try_into() + .map_err(VeilidAPIError::internal)?; if magic != *RECEIPT_MAGIC { - trace!("bad magic number: len={:?}", magic); - return Err(()); + return Err(VeilidAPIError::generic("bad magic number")); } // Check version let version = data[0x04]; if version > MAX_VERSION || version < MIN_VERSION { - trace!("unsupported protocol version: version={}", version); - return Err(()); + return Err(VeilidAPIError::parse_error( + "unsupported protocol version", + version, + )); } // Get size and ensure it matches the size of the envelope and is less than the maximum message size - let size: u16 = u16::from_le_bytes(data[0x06..0x08].try_into().map_err(drop)?); + let size: u16 = u16::from_le_bytes( + data[0x06..0x08] + .try_into() + .map_err(VeilidAPIError::internal)?, + ); if (size as usize) > MAX_RECEIPT_SIZE { - trace!("receipt size is too large: size={}", size); - return Err(()); + return Err(VeilidAPIError::parse_error( + "receipt size is too large", + size, + )); } if (size as usize) != data.len() { - trace!( - "size doesn't match receipt size: size={} data.len()={}", - size, - data.len() - ); - return Err(()); + return Err(VeilidAPIError::parse_error( + "size doesn't match receipt size", + format!("size={} data.len()={}", size, data.len()), + )); } // Get sender id - let sender_id = DHTKey::new(data[0x20..0x40].try_into().map_err(drop)?); + let sender_id = DHTKey::new( + data[0x20..0x40] + .try_into() + .map_err(VeilidAPIError::internal)?, + ); // Get signature - let signature = DHTSignature::new(data[(data.len() - 64)..].try_into().map_err(drop)?); + let signature = DHTSignature::new( + data[(data.len() - 64)..] + .try_into() + .map_err(VeilidAPIError::internal)?, + ); // Validate signature - verify(&sender_id, &data[0..(data.len() - 64)], &signature).map_err(drop)?; + verify(&sender_id, &data[0..(data.len() - 64)], &signature) + .map_err(VeilidAPIError::generic)?; // Get nonce - let nonce: ReceiptNonce = data[0x08..0x20].try_into().map_err(drop)?; + let nonce: ReceiptNonce = data[0x08..0x20] + .try_into() + .map_err(VeilidAPIError::internal)?; // Get extra data and signature let extra_data: Vec = Vec::from(&data[0x40..(data.len() - 64)]); @@ -130,16 +151,19 @@ impl Receipt { }) } - pub fn to_signed_data(&self, secret: &DHTKeySecret) -> Result, ()> { + pub fn to_signed_data(&self, secret: &DHTKeySecret) -> Result, VeilidAPIError> { // Ensure sender node id is valid if !self.sender_id.valid { - return Err(()); + return Err(VeilidAPIError::internal("sender id is invalid")); } // Ensure extra data isn't too long let receipt_size: usize = self.extra_data.len() + MIN_RECEIPT_SIZE; if receipt_size > MAX_RECEIPT_SIZE { - return Err(()); + return Err(VeilidAPIError::parse_error( + "receipt too large", + receipt_size, + )); } let mut data: Vec = vec![0u8; receipt_size]; @@ -158,8 +182,8 @@ impl Receipt { data[0x40..(receipt_size - 64)].copy_from_slice(self.extra_data.as_slice()); } // Sign the receipt - let signature = - sign(&self.sender_id, secret, &data[0..(receipt_size - 64)]).map_err(drop)?; + let signature = sign(&self.sender_id, secret, &data[0..(receipt_size - 64)]) + .map_err(VeilidAPIError::generic)?; // Append the signature data[(receipt_size - 64)..].copy_from_slice(&signature.bytes); diff --git a/veilid-core/src/intf/native/block_store.rs b/veilid-core/src/intf/native/block_store.rs index 5d8bd94f..6df36e6b 100644 --- a/veilid-core/src/intf/native/block_store.rs +++ b/veilid-core/src/intf/native/block_store.rs @@ -22,7 +22,7 @@ impl BlockStore { } } - pub async fn init(&self) -> Result<(), String> { + pub async fn init(&self) -> EyreResult<()> { // Ensure permissions are correct // ensure_file_private_owner(&dbpath)?; diff --git a/veilid-core/src/intf/native/protected_store.rs b/veilid-core/src/intf/native/protected_store.rs index 63593702..c766b0a7 100644 --- a/veilid-core/src/intf/native/protected_store.rs +++ b/veilid-core/src/intf/native/protected_store.rs @@ -3,7 +3,6 @@ use crate::*; use data_encoding::BASE64URL_NOPAD; use keyring_manager::*; use std::path::Path; -use std::result::Result; pub struct ProtectedStoreInner { keyring_manager: Option, @@ -30,7 +29,7 @@ impl ProtectedStore { } #[instrument(level = "trace", skip(self), err)] - pub async fn delete_all(&self) -> Result<(), String> { + pub async fn delete_all(&self) -> EyreResult<()> { // Delete all known keys if self.remove_user_secret_string("node_id").await? { debug!("deleted protected_store key 'node_id'"); @@ -45,7 +44,7 @@ impl ProtectedStore { } #[instrument(level = "debug", skip(self), err)] - pub async fn init(&self) -> Result<(), String> { + pub async fn init(&self) -> EyreResult<()> { let delete = { let c = self.config.get(); let mut inner = self.inner.lock(); @@ -80,12 +79,11 @@ impl ProtectedStore { // Open the insecure keyring inner.keyring_manager = Some( KeyringManager::new_insecure(&c.program_name, &insecure_keyring_file) - .map_err(map_to_string) - .map_err(logthru_pstore!(error))?, + .wrap_err("failed to create insecure keyring")?, ); } if inner.keyring_manager.is_none() { - return Err("Could not initialize the protected store.".to_owned()); + bail!("Could not initialize the protected store."); } c.protected_store.delete }; @@ -112,56 +110,52 @@ impl ProtectedStore { } #[instrument(level = "trace", skip(self, value), ret, err)] - pub async fn save_user_secret_string(&self, key: &str, value: &str) -> Result { + pub async fn save_user_secret_string(&self, key: &str, value: &str) -> EyreResult { let inner = self.inner.lock(); inner .keyring_manager .as_ref() - .ok_or_else(|| "Protected store not initialized".to_owned())? + .ok_or_else(|| eyre!("Protected store not initialized"))? .with_keyring(&self.service_name(), key, |kr| { let existed = kr.get_value().is_ok(); - kr.set_value(value) - .map_err(|e| format!("Failed to save user secret: {}", e))?; + kr.set_value(value)?; Ok(existed) }) - .map_err(map_to_string) - .map_err(logthru_pstore!()) + .wrap_err("failed to save user secret") } #[instrument(level = "trace", skip(self), err)] - pub async fn load_user_secret_string(&self, key: &str) -> Result, String> { + pub async fn load_user_secret_string(&self, key: &str) -> EyreResult> { let inner = self.inner.lock(); match inner .keyring_manager .as_ref() - .ok_or_else(|| "Protected store not initialized".to_owned())? + .ok_or_else(|| eyre!("Protected store not initialized"))? .with_keyring(&self.service_name(), key, |kr| kr.get_value()) - .map_err(logthru_pstore!()) { Ok(v) => Ok(Some(v)), Err(KeyringError::NoPasswordFound) => Ok(None), - Err(e) => Err(format!("Failed to load user secret: {}", e)), + Err(e) => Err(eyre!("Failed to load user secret")), } } #[instrument(level = "trace", skip(self), ret, err)] - pub async fn remove_user_secret_string(&self, key: &str) -> Result { + pub async fn remove_user_secret_string(&self, key: &str) -> EyreResult { let inner = self.inner.lock(); match inner .keyring_manager .as_ref() - .ok_or_else(|| "Protected store not initialized".to_owned())? + .ok_or_else(|| eyre!("Protected store not initialized"))? .with_keyring(&self.service_name(), key, |kr| kr.delete_value()) - .map_err(logthru_pstore!()) { Ok(_) => Ok(true), Err(KeyringError::NoPasswordFound) => Ok(false), - Err(e) => Err(format!("Failed to remove user secret: {}", e)), + Err(e) => Err(eyre!("Failed to remove user secret")), } } #[instrument(level = "trace", skip(self, value), ret, err)] - pub async fn save_user_secret(&self, key: &str, value: &[u8]) -> Result { + pub async fn save_user_secret(&self, key: &str, value: &[u8]) -> EyreResult { let mut s = BASE64URL_NOPAD.encode(value); s.push('!'); @@ -169,7 +163,7 @@ impl ProtectedStore { } #[instrument(level = "trace", skip(self), err)] - pub async fn load_user_secret(&self, key: &str) -> Result>, String> { + pub async fn load_user_secret(&self, key: &str) -> EyreResult>> { let mut s = match self.load_user_secret_string(key).await? { Some(s) => s, None => { @@ -178,7 +172,7 @@ impl ProtectedStore { }; if s.pop() != Some('!') { - return Err("User secret is not a buffer".to_owned()); + bail!("User secret is not a buffer"); } let mut bytes = Vec::::new(); @@ -188,19 +182,19 @@ impl ProtectedStore { bytes.resize(l, 0u8); } Err(_) => { - return Err("Failed to decode".to_owned()); + bail!("Failed to decode"); } } let res = BASE64URL_NOPAD.decode_mut(s.as_bytes(), &mut bytes); match res { Ok(_) => Ok(Some(bytes)), - Err(_) => Err("Failed to decode".to_owned()), + Err(_) => bail!("Failed to decode"), } } #[instrument(level = "trace", skip(self), ret, err)] - pub async fn remove_user_secret(&self, key: &str) -> Result { + pub async fn remove_user_secret(&self, key: &str) -> EyreResult { self.remove_user_secret_string(key).await } } diff --git a/veilid-core/src/intf/native/system.rs b/veilid-core/src/intf/native/system.rs index ae69dfa5..e51ddb02 100644 --- a/veilid-core/src/intf/native/system.rs +++ b/veilid-core/src/intf/native/system.rs @@ -16,9 +16,9 @@ pub fn get_timestamp_string() -> String { dt.time().format("%H:%M:%S.3f").to_string() } -pub fn random_bytes(dest: &mut [u8]) -> Result<(), String> { +pub fn random_bytes(dest: &mut [u8]) -> EyreResult<()> { let mut rng = rand::thread_rng(); - rng.try_fill_bytes(dest).map_err(|err| format!("{:?}", err)) + rng.try_fill_bytes(dest).wrap_err("failed to fill bytes") } pub fn get_random_u32() -> u32 { @@ -137,23 +137,15 @@ where }) } -cfg_if! { - if #[cfg(feature="rt-async-std")] { - pub use async_std::future::TimeoutError; - } else if #[cfg(feature="rt-tokio")] { - pub use tokio::time::error::Elapsed as TimeoutError; - } -} - pub async fn timeout(dur_ms: u32, f: F) -> Result where F: Future, { cfg_if! { if #[cfg(feature="rt-async-std")] { - async_std::future::timeout(Duration::from_millis(dur_ms as u64), f).await + async_std::future::timeout(Duration::from_millis(dur_ms as u64), f).await.map_err(|e| e.into()) } else if #[cfg(feature="rt-tokio")] { - tokio::time::timeout(Duration::from_millis(dur_ms as u64), f).await + tokio::time::timeout(Duration::from_millis(dur_ms as u64), f).await.map_err(|e| e.into()) } } } @@ -228,7 +220,7 @@ cfg_if! { cfg_if! { if #[cfg(not(target_os = "windows"))] { - async fn get_resolver() -> Result { + async fn get_resolver() -> EyreResult { let mut resolver_lock = RESOLVER.lock().await; if let Some(r) = &*resolver_lock { Ok(r.clone()) @@ -250,7 +242,7 @@ cfg_if! { } } -pub async fn txt_lookup>(host: S) -> Result, String> { +pub async fn txt_lookup>(host: S) -> EyreResult> { cfg_if! { if #[cfg(target_os = "windows")] { use core::ffi::c_void; @@ -263,7 +255,7 @@ pub async fn txt_lookup>(host: S) -> Result, String> { let mut p_query_results: *mut DNS_RECORDA = core::ptr::null_mut(); let status = DnsQuery_UTF8(host.as_ref(), DNS_TYPE_TEXT as u16, DNS_QUERY_STANDARD, core::ptr::null_mut(), &mut p_query_results as *mut *mut DNS_RECORDA, core::ptr::null_mut()); if status != 0 { - return Err("Failed to resolve TXT record".to_owned()); + bail!("Failed to resolve TXT record"); } let mut p_record: *mut DNS_RECORDA = p_query_results; @@ -290,12 +282,11 @@ pub async fn txt_lookup>(host: S) -> Result, String> { let resolver = get_resolver().await?; let txt_result = resolver .txt_lookup(host.as_ref()) - .await - .map_err(|e| e.to_string())?; + .await?; let mut out = Vec::new(); for x in txt_result.iter() { for s in x.txt_data() { - out.push(String::from_utf8(s.to_vec()).map_err(|e| e.to_string())?); + out.push(String::from_utf8(s.to_vec()).wrap_err("utf8 conversion error")?); } } Ok(out) @@ -303,7 +294,7 @@ pub async fn txt_lookup>(host: S) -> Result, String> { } } -pub async fn ptr_lookup(ip_addr: IpAddr) -> Result { +pub async fn ptr_lookup(ip_addr: IpAddr) -> EyreResult { cfg_if! { if #[cfg(target_os = "windows")] { use core::ffi::c_void; @@ -329,7 +320,7 @@ pub async fn ptr_lookup(ip_addr: IpAddr) -> Result { let mut p_query_results: *mut DNS_RECORDA = core::ptr::null_mut(); let status = DnsQuery_UTF8(host, DNS_TYPE_PTR as u16, DNS_QUERY_STANDARD, core::ptr::null_mut(), &mut p_query_results as *mut *mut DNS_RECORDA, core::ptr::null_mut()); if status != 0 { - return Err("Failed to resolve PTR record".to_owned()); + bail!("Failed to resolve PTR record"); } let mut p_record: *mut DNS_RECORDA = p_query_results; @@ -346,17 +337,17 @@ pub async fn ptr_lookup(ip_addr: IpAddr) -> Result { } DnsFree(p_query_results as *const c_void, DnsFreeRecordList); } - return Err("No records returned".to_owned()); + bail!("No records returned"); } else { let resolver = get_resolver().await?; let ptr_result = resolver .reverse_lookup(ip_addr) .await - .map_err(|e| e.to_string())?; + .wrap_err("resolver error")?; if let Some(r) = ptr_result.iter().next() { Ok(r.to_string().trim_end_matches('.').to_string()) } else { - Err("PTR lookup returned an empty string".to_owned()) + bail!("PTR lookup returned an empty string"); } } } diff --git a/veilid-core/src/intf/native/table_store.rs b/veilid-core/src/intf/native/table_store.rs index 2038abf5..041c4182 100644 --- a/veilid-core/src/intf/native/table_store.rs +++ b/veilid-core/src/intf/native/table_store.rs @@ -27,13 +27,13 @@ impl TableStore { } } - pub async fn delete_all(&self) -> Result<(), String> { + pub async fn delete_all(&self) -> EyreResult<()> { // Delete all known keys self.delete("crypto_caches").await?; Ok(()) } - pub async fn init(&self) -> Result<(), String> { + pub async fn init(&self) -> EyreResult<()> { Ok(()) } @@ -51,28 +51,27 @@ impl TableStore { } } - fn get_dbpath(&self, table: &str) -> Result { + fn get_dbpath(&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 tablestoredir = c.table_store.directory.clone(); - std::fs::create_dir_all(&tablestoredir) - .map_err(|e| format!("failed to create tablestore path: {}", e))?; + std::fs::create_dir_all(&tablestoredir).wrap_err("failed to create tablestore path")?; let dbpath: PathBuf = [tablestoredir, String::from(table)].iter().collect(); Ok(dbpath) } - 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(); @@ -83,7 +82,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(); @@ -104,8 +103,7 @@ impl TableStore { ensure_file_private_owner(&dbpath)?; let cfg = DatabaseConfig::with_columns(column_count); - let db = - Database::open(&dbpath, cfg).map_err(|e| format!("failed to open tabledb: {}", e))?; + let db = Database::open(&dbpath, cfg).wrap_err("failed to open tabledb")?; // Ensure permissions are correct ensure_file_private_owner(&dbpath)?; @@ -123,12 +121,12 @@ impl TableStore { Ok(table_db) } - pub async fn delete(&self, name: &str) -> Result { + pub async fn delete(&self, name: &str) -> EyreResult { let table_name = self.get_table_name(name)?; let inner = self.inner.lock(); if inner.opened.contains_key(&table_name) { - return Err("Not deleting table that is still opened".to_owned()); + bail!("Not deleting table that is still opened"); } let dbpath = self.get_dbpath(&table_name)?; let ret = std::fs::remove_file(dbpath).is_ok(); diff --git a/veilid-core/src/intf/native/utils/network_interfaces/apple.rs b/veilid-core/src/intf/native/utils/network_interfaces/apple.rs index 8852058a..5eb242ea 100644 --- a/veilid-core/src/intf/native/utils/network_interfaces/apple.rs +++ b/veilid-core/src/intf/native/utils/network_interfaces/apple.rs @@ -266,13 +266,13 @@ pub struct PlatformSupportApple { } impl PlatformSupportApple { - pub fn new() -> Result { + pub fn new() -> EyreResult { Ok(PlatformSupportApple { default_route_interfaces: BTreeSet::new(), }) } - async fn refresh_default_route_interfaces(&mut self) -> Result<(), String> { + async fn refresh_default_route_interfaces(&mut self) -> EyreResult<()> { self.default_route_interfaces.clear(); let mut mib = [CTL_NET, PF_ROUTE, 0, 0, NET_RT_FLAGS, RTF_GATEWAY]; @@ -292,7 +292,7 @@ impl PlatformSupportApple { ) } < 0 { - return Err("Unable to get memory size for routing table".to_owned()); + bail!("Unable to get memory size for routing table"); } // Allocate a buffer @@ -310,7 +310,7 @@ impl PlatformSupportApple { ) } < 0 { - return Err("Unable to get memory size for routing table".to_owned()); + bail!("Unable to get memory size for routing table"); } // Process each routing message @@ -363,7 +363,7 @@ impl PlatformSupportApple { Ok(()) } - fn get_interface_flags(&self, index: u32, flags: c_int) -> Result { + fn get_interface_flags(&self, index: u32, flags: c_int) -> EyreResult { Ok(InterfaceFlags { is_loopback: (flags & IFF_LOOPBACK) != 0, is_running: (flags & IFF_RUNNING) != 0, @@ -371,23 +371,23 @@ impl PlatformSupportApple { }) } - fn get_address_flags(ifname: &str, addr: sockaddr_in6) -> Result { + fn get_address_flags(ifname: &str, addr: sockaddr_in6) -> EyreResult { let mut req = in6_ifreq::from_name(&ifname).unwrap(); req.set_addr(addr); let sock = unsafe { socket(AF_INET6, SOCK_DGRAM, 0) }; if sock < 0 { - return Err(format!("Socket error {:?}", io::Error::last_os_error())); + bail!("Socket error {:?}", io::Error::last_os_error()); } let res = unsafe { ioctl(sock, SIOCGIFAFLAG_IN6, &mut req) }; unsafe { close(sock) }; if res < 0 { - return Err(format!( + bail!( "SIOCGIFAFLAG_IN6 failed with error on device '{}': {:?}", ifname, io::Error::last_os_error() - )); + ); } let flags = req.get_flags6(); @@ -404,12 +404,12 @@ impl PlatformSupportApple { pub async fn get_interfaces( &mut self, interfaces: &mut BTreeMap, - ) -> Result<(), String> { + ) -> EyreResult<()> { self.refresh_default_route_interfaces().await?; // If we have no routes, this isn't going to work if self.default_route_interfaces.is_empty() { - return Err("no routes available for NetworkInterfaces".to_owned()); + bail!("no routes available for NetworkInterfaces"); } // Ask for all the addresses we have diff --git a/veilid-core/src/intf/native/utils/network_interfaces/mod.rs b/veilid-core/src/intf/native/utils/network_interfaces/mod.rs index 514973e5..34cbd6e6 100644 --- a/veilid-core/src/intf/native/utils/network_interfaces/mod.rs +++ b/veilid-core/src/intf/native/utils/network_interfaces/mod.rs @@ -329,7 +329,7 @@ impl NetworkInterfaces { self.valid = false; } // returns Ok(false) if refresh had no changes, Ok(true) if changes were present - pub async fn refresh(&mut self) -> Result { + pub async fn refresh(&mut self) -> EyreResult { self.valid = false; let last_interfaces = core::mem::take(&mut self.interfaces); diff --git a/veilid-core/src/intf/native/utils/network_interfaces/netlink.rs b/veilid-core/src/intf/native/utils/network_interfaces/netlink.rs index 74f2f0b3..fc53362e 100644 --- a/veilid-core/src/intf/native/utils/network_interfaces/netlink.rs +++ b/veilid-core/src/intf/native/utils/network_interfaces/netlink.rs @@ -25,16 +25,16 @@ use std::io; use std::os::raw::c_int; use tools::*; -fn get_interface_name(index: u32) -> Result { +fn get_interface_name(index: u32) -> EyreResult { let mut ifnamebuf = [0u8; (IF_NAMESIZE + 1)]; cfg_if! { if #[cfg(all(any(target_os = "android", target_os="linux"), any(target_arch = "arm", target_arch = "aarch64")))] { if unsafe { if_indextoname(index, ifnamebuf.as_mut_ptr()) }.is_null() { - return Err("if_indextoname returned null".to_owned()); + bail!("if_indextoname returned null"); } } else { if unsafe { if_indextoname(index, ifnamebuf.as_mut_ptr() as *mut i8) }.is_null() { - return Err("if_indextoname returned null".to_owned()); + bail!("if_indextoname returned null"); } } } @@ -42,11 +42,11 @@ fn get_interface_name(index: u32) -> Result { let ifnamebuflen = ifnamebuf .iter() .position(|c| *c == 0u8) - .ok_or_else(|| "null not found in interface name".to_owned())?; + .ok_or_else(|| eyre!("null not found in interface name"))?; let ifname_str = CStr::from_bytes_with_nul(&ifnamebuf[0..=ifnamebuflen]) - .map_err(map_to_string)? + .wrap_err("failed to convert interface name")? .to_str() - .map_err(map_to_string)?; + .wrap_err("invalid characters in interface name")?; Ok(ifname_str.to_owned()) } @@ -67,7 +67,7 @@ pub struct PlatformSupportNetlink { } impl PlatformSupportNetlink { - pub fn new() -> Result { + pub fn new() -> EyreResult { Ok(PlatformSupportNetlink { connection_jh: None, handle: None, @@ -76,7 +76,7 @@ impl PlatformSupportNetlink { } // Figure out which interfaces have default routes - async fn refresh_default_route_interfaces(&mut self) -> Result<(), String> { + async fn refresh_default_route_interfaces(&mut self) -> EyreResult<()> { self.default_route_interfaces.clear(); let mut routesv4 = self .handle @@ -111,12 +111,12 @@ impl PlatformSupportNetlink { Ok(()) } - fn get_interface_flags(&self, index: u32, ifname: &str) -> Result { - let mut req = ifreq::from_name(ifname).map_err(map_to_string)?; + fn get_interface_flags(&self, index: u32, ifname: &str) -> EyreResult { + let mut req = ifreq::from_name(ifname).wrap_err("failed to convert interface name")?; let sock = unsafe { socket(AF_INET as i32, SOCK_DGRAM, 0) }; if sock < 0 { - return Err(io::Error::last_os_error()).map_err(map_to_string); + return Err(io::Error::last_os_error()).wrap_err("failed to create socket"); } cfg_if! { @@ -128,7 +128,7 @@ impl PlatformSupportNetlink { } unsafe { close(sock) }; if res < 0 { - return Err(io::Error::last_os_error()).map_err(map_to_string); + return Err(io::Error::last_os_error()).wrap_err("failed to close socket"); } let flags = req.get_flags() as c_int; @@ -242,13 +242,13 @@ impl PlatformSupportNetlink { async fn get_interfaces_internal( &mut self, interfaces: &mut BTreeMap, - ) -> Result<(), String> { + ) -> EyreResult<()> { // Refresh the routes self.refresh_default_route_interfaces().await?; // If we have no routes, this isn't going to work if self.default_route_interfaces.is_empty() { - return Err("no routes available for NetworkInterfaces".to_owned()); + bail!("no routes available for NetworkInterfaces"); } // Ask for all the addresses we have @@ -257,8 +257,7 @@ impl PlatformSupportNetlink { while let Some(msg) = addresses .try_next() .await - .map_err(map_to_string) - .map_err(logthru_net!(error))? + .wrap_err("failed to iterate interface addresses")? { // Have we seen this interface index yet? // Get the name from the index, cached, if we can @@ -268,7 +267,7 @@ impl PlatformSupportNetlink { let ifname = match get_interface_name(msg.header.index) { Ok(v) => v, Err(e) => { - log_net!( + log_net!(warn "couldn't get interface name for index {}: {}", msg.header.index, e @@ -317,11 +316,10 @@ impl PlatformSupportNetlink { pub async fn get_interfaces( &mut self, interfaces: &mut BTreeMap, - ) -> Result<(), String> { + ) -> EyreResult<()> { // Get the netlink connection let (connection, handle, _) = new_connection_with_socket::() - .map_err(map_to_string) - .map_err(logthru_net!(error))?; + .wrap_err("failed to create rtnetlink socket")?; // Spawn a connection handler let connection_jh = intf::spawn(connection); diff --git a/veilid-core/src/intf/native/utils/network_interfaces/windows.rs b/veilid-core/src/intf/native/utils/network_interfaces/windows.rs index 0f3a4484..d4ca6ec1 100644 --- a/veilid-core/src/intf/native/utils/network_interfaces/windows.rs +++ b/veilid-core/src/intf/native/utils/network_interfaces/windows.rs @@ -28,7 +28,7 @@ use winapi::um::iptypes::{ pub struct PlatformSupportWindows {} impl PlatformSupportWindows { - pub fn new() -> Result { + pub fn new() -> EyreResult { Ok(PlatformSupportWindows {}) } @@ -54,7 +54,7 @@ impl PlatformSupportWindows { pub async fn get_interfaces( &mut self, interfaces: &mut BTreeMap, - ) -> Result<(), String> { + ) -> EyreResult<()> { //self.refresh_default_route_interfaces().await?; // If we have no routes, this isn't going to work @@ -63,7 +63,7 @@ impl PlatformSupportWindows { // } // Iterate all the interfaces - let windows_interfaces = WindowsInterfaces::new().map_err(map_to_string)?; + let windows_interfaces = WindowsInterfaces::new().wrap_err("failed to get windows interfaces")?; for windows_interface in windows_interfaces.iter() { // Get name let intf_name = windows_interface.name(); diff --git a/veilid-core/src/intf/table_db.rs b/veilid-core/src/intf/table_db.rs index f6b4f844..88d627d5 100644 --- a/veilid-core/src/intf/table_db.rs +++ b/veilid-core/src/intf/table_db.rs @@ -48,58 +48,52 @@ impl TableDB { Arc::downgrade(&self.inner) } - pub async fn get_column_count(&self) -> Result { + pub async fn get_column_count(&self) -> EyreResult { let db = &self.inner.lock().database; - db.num_columns() - .map_err(|e| format!("failed to get column count: {}", e)) + db.num_columns().wrap_err("failed to get column count: {}") } - pub async fn get_keys(&self, col: u32) -> Result>, String> { + pub async fn get_keys(&self, col: u32) -> EyreResult>> { let db = &self.inner.lock().database; let mut out: Vec> = Vec::new(); db.iter(col, None, &mut |kv| { out.push(kv.0.clone().into_boxed_slice()); Ok(true) }) - .map_err(|e| format!("failed to get keys for column {}: {}", col, e))?; + .wrap_err("failed to get keys for column")?; Ok(out) } - pub async fn store(&self, col: u32, key: &[u8], value: &[u8]) -> Result<(), String> { + pub async fn store(&self, col: u32, key: &[u8], value: &[u8]) -> EyreResult<()> { let db = &self.inner.lock().database; let mut dbt = db.transaction(); dbt.put(col, key, value); - db.write(dbt) - .map_err(|e| format!("failed to store key {:?}: {}", key, e)) + db.write(dbt).wrap_err("failed to store key") } - pub async fn store_cbor(&self, col: u32, key: &[u8], value: &T) -> Result<(), String> + pub async fn store_cbor(&self, col: u32, key: &[u8], value: &T) -> EyreResult<()> where T: Serialize, { - let v = serde_cbor::to_vec(value).map_err(|_| "couldn't store as CBOR".to_owned())?; + let v = serde_cbor::to_vec(value).wrap_err("couldn't store as CBOR")?; let db = &self.inner.lock().database; let mut dbt = db.transaction(); dbt.put(col, key, v.as_slice()); - db.write(dbt) - .map_err(|e| format!("failed to store key {:?}: {}", key, e)) + db.write(dbt).wrap_err("failed to store key") } - pub async fn load(&self, col: u32, key: &[u8]) -> Result>, String> { + pub async fn load(&self, col: u32, key: &[u8]) -> EyreResult>> { let db = &self.inner.lock().database; - db.get(col, key) - .map_err(|e| format!("failed to get key {:?}: {}", key, e)) + db.get(col, key).wrap_err("failed to get key") } - pub async fn load_cbor(&self, col: u32, key: &[u8]) -> Result, String> + pub async fn load_cbor(&self, col: u32, key: &[u8]) -> EyreResult> where T: for<'de> Deserialize<'de>, { let db = &self.inner.lock().database; - let out = db - .get(col, key) - .map_err(|e| format!("failed to get key {:?}: {}", key, e))?; + let out = db.get(col, key).wrap_err("failed to get key")?; let b = match out { Some(v) => v, None => { @@ -109,24 +103,21 @@ impl TableDB { let obj = match serde_cbor::from_slice::(&b) { Ok(value) => value, Err(e) => { - return Err(format!("failed to deserialize: {}", e)); + bail!("failed to deserialize"); } }; Ok(Some(obj)) } - pub async fn delete(&self, col: u32, key: &[u8]) -> Result { + pub async fn delete(&self, col: u32, key: &[u8]) -> EyreResult { let db = &self.inner.lock().database; - let found = db - .get(col, key) - .map_err(|e| format!("failed to get key {:?}: {}", key, e))?; + let found = db.get(col, key).wrap_err("failed to get key")?; match found { None => Ok(false), Some(_) => { let mut dbt = db.transaction(); dbt.delete(col, key); - db.write(dbt) - .map_err(|e| format!("failed to delete key {:?}: {}", key, e))?; + db.write(dbt).wrap_err("failed to delete key")?; Ok(true) } } diff --git a/veilid-core/src/intf/wasm/block_store.rs b/veilid-core/src/intf/wasm/block_store.rs index 385725f8..3b207947 100644 --- a/veilid-core/src/intf/wasm/block_store.rs +++ b/veilid-core/src/intf/wasm/block_store.rs @@ -23,7 +23,7 @@ impl BlockStore { } } - pub async fn init(&self) -> Result<(), String> { + pub async fn init(&self) -> EyreResult<()> { Ok(()) } diff --git a/veilid-core/src/intf/wasm/protected_store.rs b/veilid-core/src/intf/wasm/protected_store.rs index d99e79a2..884fd3c5 100644 --- a/veilid-core/src/intf/wasm/protected_store.rs +++ b/veilid-core/src/intf/wasm/protected_store.rs @@ -30,7 +30,7 @@ impl ProtectedStore { } } - pub async fn delete_all(&self) -> Result<(), String> { + pub async fn delete_all(&self) -> EyreResult<()> { // Delete all known keys if self.remove_user_secret_string("node_id").await? { debug!("deleted protected_store key 'node_id'"); @@ -44,7 +44,7 @@ impl ProtectedStore { Ok(()) } - pub async fn init(&self) -> Result<(), String> { + pub async fn init(&self) -> EyreResult<()> { Ok(()) } @@ -68,11 +68,11 @@ impl ProtectedStore { } } - pub async fn save_user_secret_string(&self, key: &str, value: &str) -> Result { + pub async fn save_user_secret_string(&self, key: &str, value: &str) -> EyreResult { if utils::is_nodejs() { let prev = match JsFuture::from( keytar_getPassword(self.keyring_name().as_str(), key) - .map_err(|_| "exception thrown".to_owned())?, + .wrap_err("exception thrown")?, ) .await { @@ -82,12 +82,12 @@ impl ProtectedStore { match JsFuture::from( keytar_setPassword(self.keyring_name().as_str(), key, value) - .map_err(|_| "exception thrown".to_owned())?, + .wrap_err("exception thrown")?, ) .await { Ok(_) => {} - Err(_) => return Err("Failed to set password".to_owned()), + Err(_) => bail!("Failed to set password"), } Ok(prev) @@ -95,17 +95,17 @@ impl ProtectedStore { let win = match window() { Some(w) => w, None => { - return Err("failed to get window".to_owned()); + bail!("failed to get window"); } }; let ls = match win .local_storage() - .map_err(|_| "exception getting local storage".to_owned())? + .wrap_err("exception getting local storage")? { Some(l) => l, None => { - return Err("failed to get local storage".to_owned()); + bail!("failed to get local storage"); } }; @@ -113,26 +113,26 @@ impl ProtectedStore { let prev = match ls .get_item(&vkey) - .map_err(|_| "exception_thrown".to_owned())? + .wrap_err("exception_thrown")? { Some(_) => true, None => false, }; ls.set_item(&vkey, value) - .map_err(|_| "exception_thrown".to_owned())?; + .wrap_err("exception_thrown")?; Ok(prev) } else { - Err("unimplemented".to_owned()) + unimplemented!() } } - pub async fn load_user_secret_string(&self, key: &str) -> Result, String> { + pub async fn load_user_secret_string(&self, key: &str) -> EyreResult> { if utils::is_nodejs() { let prev = match JsFuture::from( keytar_getPassword(self.keyring_name().as_str(), key) - .map_err(|_| "exception thrown".to_owned())?, + .wrap_err("exception thrown")?, ) .await { @@ -149,54 +149,54 @@ impl ProtectedStore { let win = match window() { Some(w) => w, None => { - return Err("failed to get window".to_owned()); + bail!("failed to get window"); } }; let ls = match win .local_storage() - .map_err(|_| "exception getting local storage".to_owned())? + .wrap_err("exception getting local storage")? { Some(l) => l, None => { - return Err("failed to get local storage".to_owned()); + bail!("failed to get local storage"); } }; let vkey = self.browser_key_name(key); ls.get_item(&vkey) - .map_err(|_| "exception_thrown".to_owned()) + .wrap_err("exception_thrown") } else { - Err("unimplemented".to_owned()) + unimplemented!(); } } - pub async fn remove_user_secret_string(&self, key: &str) -> Result { + pub async fn remove_user_secret_string(&self, key: &str) -> EyreResult { if utils::is_nodejs() { match JsFuture::from( - keytar_deletePassword(self.keyring_name().as_str(), key).map_err(|_| "exception thrown".to_owned())?, + keytar_deletePassword(self.keyring_name().as_str(), key).wrap_err("exception thrown")?, ) .await { Ok(v) => Ok(v.is_truthy()), - Err(_) => Err("Failed to delete".to_owned()), + Err(_) => bail!("Failed to delete"), } } else if utils::is_browser() { let win = match window() { Some(w) => w, None => { - return Err("failed to get window".to_owned()); + bail!("failed to get window"); } }; let ls = match win .local_storage() - .map_err(|_| "exception getting local storage".to_owned())? + .wrap_err("exception getting local storage")? { Some(l) => l, None => { - return Err("failed to get local storage".to_owned()); + bail!("failed to get local storage"); } }; @@ -204,28 +204,28 @@ impl ProtectedStore { match ls .get_item(&vkey) - .map_err(|_| "exception_thrown".to_owned())? + .wrap_err("exception_thrown")? { Some(_) => { ls.delete(&vkey) - .map_err(|_| "exception_thrown".to_owned())?; + .wrap_err("exception_thrown")?; Ok(true) } None => Ok(false), } } else { - Err("unimplemented".to_owned()) + unimplemented!(); } } - pub async fn save_user_secret(&self, key: &str, value: &[u8]) -> Result { + pub async fn save_user_secret(&self, key: &str, value: &[u8]) -> EyreResult { let mut s = BASE64URL_NOPAD.encode(value); s.push('!'); self.save_user_secret_string(key, s.as_str()).await } - pub async fn load_user_secret(&self, key: &str) -> Result>, String> { + pub async fn load_user_secret(&self, key: &str) -> EyreResult>> { let mut s = match self.load_user_secret_string(key).await? { Some(s) => s, None => { @@ -234,7 +234,7 @@ impl ProtectedStore { }; if s.pop() != Some('!') { - return Err("User secret is not a buffer".to_owned()); + bail!("User secret is not a buffer"); } let mut bytes = Vec::::new(); @@ -244,18 +244,18 @@ impl ProtectedStore { bytes.resize(l, 0u8); } Err(_) => { - return Err("Failed to decode".to_owned()); + bail!("Failed to decode"); } } let res = BASE64URL_NOPAD.decode_mut(s.as_bytes(), &mut bytes); match res { Ok(_) => Ok(Some(bytes)), - Err(_) => Err("Failed to decode".to_owned()), + Err(_) => bail!("Failed to decode"), } } - pub async fn remove_user_secret(&self, key: &str) -> Result { + pub async fn remove_user_secret(&self, key: &str) -> EyreResult { self.remove_user_secret_string(key).await } } \ No newline at end of file diff --git a/veilid-core/src/intf/wasm/system.rs b/veilid-core/src/intf/wasm/system.rs index 5d1c08d7..541d3ebe 100644 --- a/veilid-core/src/intf/wasm/system.rs +++ b/veilid-core/src/intf/wasm/system.rs @@ -39,7 +39,7 @@ pub fn get_timestamp_string() -> String { ) } -pub fn random_bytes(dest: &mut [u8]) -> Result<(), String> { +pub fn random_bytes(dest: &mut [u8]) -> EyreResult<()> { let len = dest.len(); let u32len = len / 4; let remlen = len % 4; @@ -161,25 +161,12 @@ where }) } -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct TimeoutError { - _private: (), -} - -//impl Error for TimeoutError {} - -impl fmt::Display for TimeoutError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "future has timed out".fmt(f) - } -} - pub async fn timeout(dur_ms: u32, f: F) -> Result where F: Future, { match select(Box::pin(intf::sleep(dur_ms)), Box::pin(f)).await { - Either::Left((_x, _b)) => Err(TimeoutError { _private: () }), + Either::Left((_x, _b)) => Err(TimeoutError()), Either::Right((y, _a)) => Ok(y), } } @@ -227,10 +214,10 @@ pub async fn get_outbound_relay_peer() -> Option { // } -pub async fn txt_lookup>(_host: S) -> Result, String> { - Err("wasm does not support txt lookup".to_owned()) +pub async fn txt_lookup>(_host: S) -> EyreResult> { + bail!("wasm does not support txt lookup") } -pub async fn ptr_lookup(_ip_addr: IpAddr) -> Result { - Err("wasm does not support ptr lookup".to_owned()) +pub async fn ptr_lookup(_ip_addr: IpAddr) -> EyreResult { + bail!("wasm does not support ptr lookup") } diff --git a/veilid-core/src/network_manager/connection_handle.rs b/veilid-core/src/network_manager/connection_handle.rs index ac5b6389..1b085a89 100644 --- a/veilid-core/src/network_manager/connection_handle.rs +++ b/veilid-core/src/network_manager/connection_handle.rs @@ -18,14 +18,16 @@ impl ConnectionHandle { self.descriptor.clone() } - pub fn send(&self, message: Vec) -> Result<(), String> { - self.channel.send(message).map_err(map_to_string) + pub fn send(&self, message: Vec) -> EyreResult<()> { + self.channel + .send(message) + .wrap_err("failed to send to connection") } - pub async fn send_async(&self, message: Vec) -> Result<(), String> { + pub async fn send_async(&self, message: Vec) -> EyreResult<()> { self.channel .send_async(message) .await - .map_err(map_to_string) + .wrap_err("failed to send_async to connection") } } diff --git a/veilid-core/src/network_manager/connection_limits.rs b/veilid-core/src/network_manager/connection_limits.rs index 451ba173..2102bfe5 100644 --- a/veilid-core/src/network_manager/connection_limits.rs +++ b/veilid-core/src/network_manager/connection_limits.rs @@ -1,33 +1,17 @@ use super::*; use alloc::collections::btree_map::Entry; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(ThisError, Debug, Clone, Copy, PartialEq, Eq)] pub enum AddressFilterError { + #[error("Count exceeded")] CountExceeded, + #[error("Rate exceeded")] RateExceeded, } -impl fmt::Display for AddressFilterError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{}", - match *self { - Self::CountExceeded => "Count exceeded", - Self::RateExceeded => "Rate exceeded", - } - ) - } -} -impl std::error::Error for AddressFilterError {} -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(ThisError, Debug, Clone, Copy, PartialEq, Eq)] +#[error("Address not in table")] pub struct AddressNotInTableError {} -impl fmt::Display for AddressNotInTableError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Address not in table") - } -} -impl std::error::Error for AddressNotInTableError {} #[derive(Debug)] pub struct ConnectionLimits { diff --git a/veilid-core/src/network_manager/connection_manager.rs b/veilid-core/src/network_manager/connection_manager.rs index 7afb6c3e..cd0dcfe2 100644 --- a/veilid-core/src/network_manager/connection_manager.rs +++ b/veilid-core/src/network_manager/connection_manager.rs @@ -142,13 +142,13 @@ impl ConnectionManager { &self, inner: &mut ConnectionManagerInner, conn: ProtocolNetworkConnection, - ) -> Result { + ) -> EyreResult { log_net!("on_new_protocol_network_connection: {:?}", conn); // Wrap with NetworkConnection object to start the connection processing loop let stop_token = match &inner.stop_source { Some(ss) => ss.token(), - None => return Err("not creating connection because we are stopping".to_owned()), + None => bail!("not creating connection because we are stopping"), }; let conn = NetworkConnection::from_protocol(self.clone(), stop_token, conn); @@ -165,7 +165,7 @@ impl ConnectionManager { &self, local_addr: Option, dial_info: DialInfo, - ) -> Result { + ) -> EyreResult { let killed = { let mut inner = self.arc.inner.lock(); let inner = match &mut *inner { @@ -274,7 +274,7 @@ impl ConnectionManager { let inner = match &mut *inner { Some(v) => v, None => { - return Err("shutting down".to_owned()); + bail!("shutting down"); } }; self.on_new_protocol_network_connection(inner, conn) @@ -336,7 +336,7 @@ impl ConnectionManager { pub(super) async fn on_accepted_protocol_network_connection( &self, conn: ProtocolNetworkConnection, - ) -> Result<(), String> { + ) -> EyreResult<()> { // Get channel sender let sender = { let mut inner = self.arc.inner.lock(); diff --git a/veilid-core/src/network_manager/connection_table.rs b/veilid-core/src/network_manager/connection_table.rs index d526a383..d2e6d094 100644 --- a/veilid-core/src/network_manager/connection_table.rs +++ b/veilid-core/src/network_manager/connection_table.rs @@ -3,6 +3,39 @@ use alloc::collections::btree_map::Entry; use futures_util::StreamExt; use hashlink::LruCache; +/////////////////////////////////////////////////////////////////////////////// +#[derive(ThisError, Debug, Clone, Eq, PartialEq)] +pub enum ConnectionTableAddError { + #[error("Connection already added to table")] + AlreadyExists, + #[error("Connection address was filtered")] + AddressFilter(AddressFilterError), +} + +impl ConnectionTableAddError { + pub fn already_exists() -> Self { + ConnectionTableAddError::AlreadyExists + } + pub fn address_filter(err: AddressFilterError) -> Self { + ConnectionTableAddError::AddressFilter(err) + } +} + +/////////////////////////////////////////////////////////////////////////////// +#[derive(ThisError, Debug, Clone, Eq, PartialEq)] +pub enum ConnectionTableRemoveError { + #[error("Connection not in table")] + NotInTable, +} + +impl ConnectionTableRemoveError { + pub fn not_in_table() -> Self { + ConnectionTableRemoveError::NotInTable + } +} + +/////////////////////////////////////////////////////////////////////////////// + #[derive(Debug)] pub struct ConnectionTable { max_connections: Vec, @@ -53,20 +86,22 @@ impl ConnectionTable { while unord.next().await.is_some() {} } - pub fn add_connection(&mut self, conn: NetworkConnection) -> Result<(), String> { + pub fn add_connection( + &mut self, + conn: NetworkConnection, + ) -> Result<(), ConnectionTableAddError> { let descriptor = conn.connection_descriptor(); let ip_addr = descriptor.remote_address().to_ip_addr(); let index = protocol_to_index(descriptor.protocol_type()); if self.conn_by_descriptor[index].contains_key(&descriptor) { - return Err(format!( - "Connection already added to table: {:?}", - descriptor - )); + return Err(ConnectionTableAddError::already_exists()); } // Filter by ip for connection limits - self.address_filter.add(ip_addr).map_err(map_to_string)?; + self.address_filter + .add(ip_addr) + .map_err(ConnectionTableAddError::address_filter)?; // Add the connection to the table let res = self.conn_by_descriptor[index].insert(descriptor.clone(), conn); @@ -164,11 +199,11 @@ impl ConnectionTable { pub fn remove_connection( &mut self, descriptor: ConnectionDescriptor, - ) -> Result { + ) -> Result { let index = protocol_to_index(descriptor.protocol_type()); let conn = self.conn_by_descriptor[index] .remove(&descriptor) - .ok_or_else(|| format!("Connection not in table: {:?}", descriptor))?; + .ok_or_else(|| ConnectionTableRemoveError::not_in_table())?; self.remove_connection_records(descriptor); Ok(conn) diff --git a/veilid-core/src/network_manager/mod.rs b/veilid-core/src/network_manager/mod.rs index c945ed08..9b2db725 100644 --- a/veilid-core/src/network_manager/mod.rs +++ b/veilid-core/src/network_manager/mod.rs @@ -127,8 +127,8 @@ struct NetworkManagerInner { struct NetworkManagerUnlockedInner { // Background processes - rolling_transfers_task: TickTask, - relay_management_task: TickTask, + rolling_transfers_task: TickTask, + relay_management_task: TickTask, } #[derive(Clone)] @@ -236,7 +236,7 @@ impl NetworkManager { } #[instrument(level = "debug", skip_all, err)] - pub async fn init(&self, update_callback: UpdateCallback) -> Result<(), String> { + pub async fn init(&self, update_callback: UpdateCallback) -> EyreResult<()> { let routing_table = RoutingTable::new(self.clone()); routing_table.init().await?; self.inner.lock().routing_table = Some(routing_table.clone()); @@ -257,7 +257,7 @@ impl NetworkManager { } #[instrument(level = "debug", skip_all, err)] - pub async fn internal_startup(&self) -> Result<(), String> { + pub async fn internal_startup(&self) -> EyreResult<()> { trace!("NetworkManager::internal_startup begin"); if self.inner.lock().components.is_some() { debug!("NetworkManager::internal_startup already started"); @@ -292,7 +292,7 @@ impl NetworkManager { } #[instrument(level = "debug", skip_all, err)] - pub async fn startup(&self) -> Result<(), String> { + pub async fn startup(&self) -> EyreResult<()> { if let Err(e) = self.internal_startup().await { self.shutdown().await; return Err(e); @@ -387,7 +387,7 @@ impl NetworkManager { } #[instrument(level = "debug", skip_all, err)] - async fn restart_net(&self, net: Network) -> Result<(), String> { + async fn restart_net(&self, net: Network) -> EyreResult<()> { net.shutdown().await; self.send_network_update(); net.startup().await?; @@ -395,7 +395,7 @@ impl NetworkManager { Ok(()) } - pub async fn tick(&self) -> Result<(), String> { + pub async fn tick(&self) -> EyreResult<()> { let (routing_table, net, receipt_manager) = { let inner = self.inner.lock(); let components = inner.components.as_ref().unwrap(); @@ -481,7 +481,7 @@ impl NetworkManager { expected_returns: u32, extra_data: D, callback: impl ReceiptCallback, - ) -> Result, String> { + ) -> EyreResult> { let receipt_manager = self.receipt_manager(); let routing_table = self.routing_table(); @@ -490,7 +490,7 @@ impl NetworkManager { let receipt = Receipt::try_new(0, nonce, routing_table.node_id(), extra_data)?; let out = receipt .to_signed_data(&routing_table.node_id_secret()) - .map_err(|_| "failed to generate signed receipt".to_owned())?; + .wrap_err("failed to generate signed receipt")?; // Record the receipt for later let exp_ts = intf::get_timestamp() + expiration_us; @@ -505,7 +505,7 @@ impl NetworkManager { &self, expiration_us: u64, extra_data: D, - ) -> Result<(Vec, EventualValueFuture), String> { + ) -> EyreResult<(Vec, EventualValueFuture)> { let receipt_manager = self.receipt_manager(); let routing_table = self.routing_table(); @@ -514,7 +514,7 @@ impl NetworkManager { let receipt = Receipt::try_new(0, nonce, routing_table.node_id(), extra_data)?; let out = receipt .to_signed_data(&routing_table.node_id_secret()) - .map_err(|_| "failed to generate signed receipt".to_owned())?; + .wrap_err("failed to generate signed receipt")?; // Record the receipt for later let exp_ts = intf::get_timestamp() + expiration_us; @@ -530,11 +530,11 @@ impl NetworkManager { pub async fn handle_out_of_band_receipt>( &self, receipt_data: R, - ) -> Result<(), String> { + ) -> EyreResult<()> { let receipt_manager = self.receipt_manager(); let receipt = Receipt::from_signed_data(receipt_data.as_ref()) - .map_err(|_| "failed to parse signed out-of-band receipt".to_owned())?; + .wrap_err("failed to parse signed out-of-band receipt")?; receipt_manager.handle_receipt(receipt, None).await } @@ -545,11 +545,11 @@ impl NetworkManager { &self, receipt_data: R, inbound_nr: NodeRef, - ) -> Result<(), String> { + ) -> EyreResult<()> { let receipt_manager = self.receipt_manager(); let receipt = Receipt::from_signed_data(receipt_data.as_ref()) - .map_err(|_| "failed to parse signed in-band receipt".to_owned())?; + .wrap_err("failed to parse signed in-band receipt")?; receipt_manager .handle_receipt(receipt, Some(inbound_nr)) @@ -558,7 +558,7 @@ impl NetworkManager { // Process a received signal #[instrument(level = "trace", skip(self), err)] - pub async fn handle_signal(&self, signal_info: SignalInfo) -> Result<(), String> { + pub async fn handle_signal(&self, signal_info: SignalInfo) -> EyreResult<()> { match signal_info { SignalInfo::ReverseConnect { receipt, peer_info } => { let routing_table = self.routing_table(); @@ -573,7 +573,7 @@ impl NetworkManager { // Make a reverse connection to the peer and send the receipt to it rpc.rpc_call_return_receipt(Destination::Direct(peer_nr), None, receipt) .await - .map_err(map_to_string)?; + .wrap_err("rpc failure")?; } SignalInfo::HolePunch { receipt, peer_info } => { let routing_table = self.routing_table(); @@ -589,7 +589,7 @@ impl NetworkManager { peer_nr.filter_protocols(ProtocolSet::only(ProtocolType::UDP)); let hole_punch_dial_info_detail = peer_nr .first_filtered_dial_info_detail(Some(RoutingDomain::PublicInternet)) - .ok_or_else(|| "No hole punch capable dialinfo found for node".to_owned())?; + .ok_or_else(|| eyre!("No hole punch capable dialinfo found for node"))?; // Now that we picked a specific dialinfo, further restrict the noderef to the specific address type let mut filter = peer_nr.take_filter().unwrap(); @@ -611,7 +611,7 @@ impl NetworkManager { // Return the receipt using the same dial info send the receipt to it rpc.rpc_call_return_receipt(Destination::Direct(peer_nr), None, receipt) .await - .map_err(map_to_string)?; + .wrap_err("rpc failure")?; } } @@ -625,7 +625,7 @@ impl NetworkManager { dest_node_id: DHTKey, version: u8, body: B, - ) -> Result, String> { + ) -> EyreResult> { // DH to get encryption key let routing_table = self.routing_table(); let node_id = routing_table.node_id(); @@ -639,7 +639,7 @@ impl NetworkManager { let envelope = Envelope::new(version, ts, nonce, node_id, dest_node_id); envelope .to_encrypted_data(self.crypto.clone(), body.as_ref(), &node_id_secret) - .map_err(|_| "envelope failed to encode".to_owned()) + .wrap_err("envelope failed to encode") } // Called by the RPC handler when we want to issue an RPC request or response @@ -652,7 +652,7 @@ impl NetworkManager { node_ref: NodeRef, envelope_node_id: Option, body: B, - ) -> Result { + ) -> EyreResult { let via_node_id = node_ref.node_id(); let envelope_node_id = envelope_node_id.unwrap_or(via_node_id); @@ -671,11 +671,12 @@ impl NetworkManager { { #[allow(clippy::absurd_extreme_comparisons)] if node_min > MAX_VERSION || node_max < MIN_VERSION { - return Err(format!( + bail!( "can't talk to this node {} because version is unsupported: ({},{})", - via_node_id, node_min, node_max - )) - .map_err(logthru_rpc!(warn)); + via_node_id, + node_min, + node_max + ); } cmp::min(node_max, MAX_VERSION) } else { @@ -703,7 +704,7 @@ impl NetworkManager { &self, dial_info: DialInfo, rcpt_data: Vec, - ) -> Result<(), String> { + ) -> EyreResult<()> { // Do we need to validate the outgoing receipt? Probably not // because it is supposed to be opaque and the // recipient/originator does the validation @@ -717,8 +718,8 @@ impl NetworkManager { } // Figure out how to reach a node - #[instrument(level = "trace", skip(self), ret, err)] - fn get_contact_method(&self, mut target_node_ref: NodeRef) -> Result { + #[instrument(level = "trace", skip(self), ret)] + fn get_contact_method(&self, mut target_node_ref: NodeRef) -> ContactMethod { let routing_table = self.routing_table(); // Get our network class and protocol config and node id @@ -727,14 +728,14 @@ impl NetworkManager { // Scope noderef down to protocols we can do outbound if !target_node_ref.filter_protocols(our_protocol_config.outbound) { - return Ok(ContactMethod::Unreachable); + return ContactMethod::Unreachable; } // Get the best matching local direct dial info if we have it let opt_target_local_did = target_node_ref.first_filtered_dial_info_detail(Some(RoutingDomain::LocalNetwork)); if let Some(target_local_did) = opt_target_local_did { - return Ok(ContactMethod::Direct(target_local_did.dial_info)); + return ContactMethod::Direct(target_local_did.dial_info); } // Get the best match internet dial info if we have it @@ -744,7 +745,7 @@ impl NetworkManager { // Do we need to signal before going inbound? if !target_public_did.class.requires_signal() { // Go direct without signaling - return Ok(ContactMethod::Direct(target_public_did.dial_info)); + return ContactMethod::Direct(target_public_did.dial_info); } // Get the target's inbound relay, it must have one or it is not reachable @@ -767,10 +768,10 @@ impl NetworkManager { ) { // Can we receive a direct reverse connection? if !reverse_did.class.requires_signal() { - return Ok(ContactMethod::SignalReverse( + return ContactMethod::SignalReverse( inbound_relay_nr, target_node_ref, - )); + ); } } @@ -798,16 +799,16 @@ impl NetworkManager { ) .is_some(); if target_has_udp_dialinfo && self_has_udp_dialinfo { - return Ok(ContactMethod::SignalHolePunch( + return ContactMethod::SignalHolePunch( inbound_relay_nr, udp_target_nr, - )); + ); } } // Otherwise we have to inbound relay } - return Ok(ContactMethod::InboundRelay(inbound_relay_nr)); + return ContactMethod::InboundRelay(inbound_relay_nr); } } } @@ -818,22 +819,17 @@ impl NetworkManager { .first_filtered_dial_info_detail(Some(RoutingDomain::PublicInternet)) .is_some() { - return Ok(ContactMethod::InboundRelay(target_inbound_relay_nr)); + return ContactMethod::InboundRelay(target_inbound_relay_nr); } } // If we can't reach the node by other means, try our outbound relay if we have one if let Some(relay_node) = self.relay_node() { - return Ok(ContactMethod::OutboundRelay(relay_node)); + return ContactMethod::OutboundRelay(relay_node); } // Otherwise, we can't reach this node debug!("unable to reach node {:?}", target_node_ref); - // trace!( - // "unable to reach node {:?}: {}", - // target_node_ref, - // target_node_ref.operate(|e| format!("{:#?}", e)) - // ); - Ok(ContactMethod::Unreachable) + ContactMethod::Unreachable } // Send a reverse connection signal and wait for the return receipt over it @@ -844,13 +840,11 @@ impl NetworkManager { relay_nr: NodeRef, target_nr: NodeRef, data: Vec, - ) -> Result<(), String> { + ) -> EyreResult<()> { // Build a return receipt for the signal let receipt_timeout = ms_to_us(self.config.get().network.reverse_connection_receipt_time_ms); - let (receipt, eventual_value) = self - .generate_single_shot_receipt(receipt_timeout, []) - .map_err(map_to_string)?; + let (receipt, eventual_value) = self.generate_single_shot_receipt(receipt_timeout, [])?; // Get our peer info let peer_info = self.routing_table().get_own_peer_info(); @@ -863,32 +857,25 @@ impl NetworkManager { SignalInfo::ReverseConnect { receipt, peer_info }, ) .await - .map_err(logthru_net!("failed to send signal to {:?}", relay_nr)) - .map_err(map_to_string)?; + .wrap_err("failed to send signal")?; // Wait for the return receipt let inbound_nr = match eventual_value.await.take_value().unwrap() { ReceiptEvent::ReturnedOutOfBand => { - return Err("reverse connect receipt should be returned in-band".to_owned()); + bail!("reverse connect receipt should be returned in-band"); } ReceiptEvent::ReturnedInBand { inbound_noderef } => inbound_noderef, ReceiptEvent::Expired => { - return Err(format!( - "reverse connect receipt expired from {:?}", - target_nr - )); + bail!("reverse connect receipt expired from {:?}", target_nr); } ReceiptEvent::Cancelled => { - return Err(format!( - "reverse connect receipt cancelled from {:?}", - target_nr - )); + bail!("reverse connect receipt cancelled from {:?}", target_nr); } }; // We expect the inbound noderef to be the same as the target noderef // if they aren't the same, we should error on this and figure out what then hell is up if target_nr != inbound_nr { - error!("unexpected noderef mismatch on reverse connect"); + bail!("unexpected noderef mismatch on reverse connect"); } // And now use the existing connection to send over @@ -899,10 +886,10 @@ impl NetworkManager { .await? { None => Ok(()), - Some(_) => Err("unable to send over reverse connection".to_owned()), + Some(_) => bail!("unable to send over reverse connection"), } } else { - Err("no reverse connection available".to_owned()) + bail!("no reverse connection available") } } @@ -914,7 +901,7 @@ impl NetworkManager { relay_nr: NodeRef, target_nr: NodeRef, data: Vec, - ) -> Result<(), String> { + ) -> EyreResult<()> { // Ensure we are filtered down to UDP (the only hole punch protocol supported today) assert!(target_nr .filter_ref() @@ -923,17 +910,14 @@ impl NetworkManager { // Build a return receipt for the signal let receipt_timeout = ms_to_us(self.config.get().network.hole_punch_receipt_time_ms); - let (receipt, eventual_value) = self - .generate_single_shot_receipt(receipt_timeout, []) - .map_err(map_to_string)?; - + let (receipt, eventual_value) = self.generate_single_shot_receipt(receipt_timeout, [])?; // Get our peer info let peer_info = self.routing_table().get_own_peer_info(); // Get the udp direct dialinfo for the hole punch let hole_punch_did = target_nr .first_filtered_dial_info_detail(Some(RoutingDomain::PublicInternet)) - .ok_or_else(|| "No hole punch capable dialinfo found for node".to_owned())?; + .ok_or_else(|| eyre!("No hole punch capable dialinfo found for node"))?; // Do our half of the hole punch by sending an empty packet // Both sides will do this and then the receipt will get sent over the punched hole @@ -949,30 +933,30 @@ impl NetworkManager { SignalInfo::HolePunch { receipt, peer_info }, ) .await - .map_err(logthru_net!("failed to send signal to {:?}", relay_nr)) - .map_err(map_to_string)?; + .wrap_err("failed to send signal")?; // Wait for the return receipt let inbound_nr = match eventual_value.await.take_value().unwrap() { ReceiptEvent::ReturnedOutOfBand => { - return Err("hole punch receipt should be returned in-band".to_owned()); + bail!("hole punch receipt should be returned in-band"); } ReceiptEvent::ReturnedInBand { inbound_noderef } => inbound_noderef, ReceiptEvent::Expired => { - return Err(format!("hole punch receipt expired from {}", target_nr)); + bail!("hole punch receipt expired from {}", target_nr); } ReceiptEvent::Cancelled => { - return Err(format!("hole punch receipt cancelled from {}", target_nr)); + bail!("hole punch receipt cancelled from {}", target_nr); } }; // We expect the inbound noderef to be the same as the target noderef // if they aren't the same, we should error on this and figure out what then hell is up if target_nr != inbound_nr { - return Err(format!( + bail!( "unexpected noderef mismatch on hole punch {}, expected {}", - inbound_nr, target_nr - )); + inbound_nr, + target_nr + ); } // And now use the existing connection to send over @@ -983,10 +967,10 @@ impl NetworkManager { .await? { None => Ok(()), - Some(_) => Err("unable to send over hole punch".to_owned()), + Some(_) => bail!("unable to send over hole punch"), } } else { - Err("no hole punch available".to_owned()) + bail!("no hole punch available") } } @@ -1003,7 +987,7 @@ impl NetworkManager { &self, node_ref: NodeRef, data: Vec, - ) -> SystemPinBoxFuture> { + ) -> SystemPinBoxFuture> { let this = self.clone(); Box::pin(async move { // First try to send data to the last socket we've seen this peer on @@ -1028,11 +1012,7 @@ impl NetworkManager { log_net!("send_data via dialinfo to {:?}", node_ref); // If we don't have last_connection, try to reach out to the peer via its dial info - match this - .get_contact_method(node_ref.clone()) - .map_err(logthru_net!(debug)) - .map(logthru_net!("get_contact_method for {:?}", node_ref))? - { + match this.get_contact_method(node_ref.clone()) { ContactMethod::OutboundRelay(relay_nr) | ContactMethod::InboundRelay(relay_nr) => { this.send_data(relay_nr, data) .await @@ -1057,14 +1037,13 @@ impl NetworkManager { .do_hole_punch(relay_nr, target_node_ref, data) .await .map(|_| SendDataKind::GlobalDirect), - ContactMethod::Unreachable => Err("Can't send to this node".to_owned()), + ContactMethod::Unreachable => Err(eyre!("Can't send to this node")), } - .map_err(logthru_net!(debug)) }) } // Direct bootstrap request handler (separate fallback mechanism from cheaper TXT bootstrap mechanism) - async fn handle_boot_request(&self, descriptor: ConnectionDescriptor) -> Result<(), String> { + async fn handle_boot_request(&self, descriptor: ConnectionDescriptor) -> EyreResult<()> { let routing_table = self.routing_table(); // Get a bunch of nodes with the various @@ -1087,12 +1066,13 @@ impl NetworkManager { // Bootstrap reply was sent Ok(()) } - Some(_) => Err("bootstrap reply could not be sent".to_owned()), + Some(_) => Err(eyre!("bootstrap reply could not be sent")), } } // Direct bootstrap request - pub async fn boot_request(&self, dial_info: DialInfo) -> Result, String> { + #[instrument(level = "trace", err, skip(self))] + pub async fn boot_request(&self, dial_info: DialInfo) -> EyreResult> { let timeout_ms = { let c = self.config.get(); c.network.rpc.timeout_ms @@ -1105,8 +1085,8 @@ impl NetworkManager { .await?; let bootstrap_peerinfo: Vec = - deserialize_json(std::str::from_utf8(&out_data).map_err(map_to_string)?) - .map_err(map_to_string)?; + deserialize_json(std::str::from_utf8(&out_data).wrap_err("bad utf8 in boot peerinfo")?) + .wrap_err("failed to deserialize boot peerinfo")?; Ok(bootstrap_peerinfo) } @@ -1119,7 +1099,7 @@ impl NetworkManager { &self, data: &[u8], descriptor: ConnectionDescriptor, - ) -> Result { + ) -> EyreResult { log_net!( "envelope of {} bytes received from {:?}", data.len(), @@ -1138,7 +1118,7 @@ impl NetworkManager { // Ensure we can read the magic number if data.len() < 4 { - return Err("short packet".to_owned()); + bail!("short packet"); } // Is this a direct bootstrap request instead of an envelope? @@ -1154,13 +1134,7 @@ impl NetworkManager { } // Decode envelope header (may fail signature validation) - let envelope = Envelope::from_signed_data(data).map_err(|_| { - format!( - "envelope failed to decode from {:?}: {} bytes", - descriptor, - data.len() - ) - })?; + let envelope = Envelope::from_signed_data(data).wrap_err("envelope failed to decode")?; // Get routing table and rpc processor let (routing_table, rpc) = { @@ -1185,18 +1159,18 @@ impl NetworkManager { let ets = envelope.get_timestamp(); if let Some(tsbehind) = tsbehind { if tsbehind > 0 && (ts > ets && ts - ets > tsbehind) { - return Err(format!( + bail!( "envelope time was too far in the past: {}ms ", timestamp_to_secs(ts - ets) * 1000f64 - )); + ); } } if let Some(tsahead) = tsahead { if tsahead > 0 && (ts < ets && ets - ts > tsahead) { - return Err(format!( + bail!( "envelope time was too far in the future: {}ms", timestamp_to_secs(ets - ts) * 1000f64 - )); + ); } } @@ -1211,12 +1185,9 @@ impl NetworkManager { let relay_nr = if self.check_client_whitelist(sender_id) { // Full relay allowed, do a full resolve_node - rpc.resolve_node(recipient_id).await.map_err(|e| { - format!( - "failed to resolve recipient node for relay, dropping outbound relayed packet...: {:?}", - e - ) - })? + rpc.resolve_node(recipient_id).await.wrap_err( + "failed to resolve recipient node for relay, dropping outbound relayed packet", + )? } else { // If this is not a node in the client whitelist, only allow inbound relay // which only performs a lightweight lookup before passing the packet back out @@ -1226,7 +1197,7 @@ impl NetworkManager { // should be mutually in each others routing tables. The node needing the relay will be // pinging this node regularly to keep itself in the routing table routing_table.lookup_node_ref(recipient_id).ok_or_else(|| { - format!( + eyre!( "Inbound relay asked for recipient not in routing table: sender_id={:?} recipient={:?}", sender_id, recipient_id ) @@ -1236,7 +1207,7 @@ impl NetworkManager { // Relay the packet to the desired destination self.send_data(relay_nr, data.to_vec()) .await - .map_err(|e| format!("failed to forward envelope: {}", e))?; + .wrap_err("failed to forward envelope")?; // Inform caller that we dealt with the envelope, but did not process it locally return Ok(false); } @@ -1248,19 +1219,20 @@ impl NetworkManager { // xxx: punish nodes that send messages that fail to decrypt eventually let body = envelope .decrypt_body(self.crypto(), data, &node_id_secret) - .map_err(|_| "failed to decrypt envelope body".to_owned())?; + .wrap_err("failed to decrypt envelope body")?; // Cache the envelope information in the routing table - let source_noderef = routing_table - .register_node_with_existing_connection(envelope.get_sender_id(), descriptor, ts) - .map_err(|e| format!("node id registration failed: {}", e))?; + let source_noderef = routing_table.register_node_with_existing_connection( + envelope.get_sender_id(), + descriptor, + ts, + )?; source_noderef.operate_mut(|e| e.set_min_max_version(envelope.get_min_max_version())); // xxx: deal with spoofing and flooding here? // Pass message to RPC system - rpc.enqueue_message(envelope, body, source_noderef) - .map_err(|e| format!("enqueing rpc message failed: {}", e))?; + rpc.enqueue_message(envelope, body, source_noderef)?; // Inform caller that we dealt with the envelope locally Ok(true) @@ -1273,7 +1245,7 @@ impl NetworkManager { stop_token: StopToken, _last_ts: u64, cur_ts: u64, - ) -> Result<(), String> { + ) -> EyreResult<()> { // Get our node's current node info and network class and do the right thing let routing_table = self.routing_table(); let node_info = routing_table.get_own_node_info(); @@ -1354,7 +1326,7 @@ impl NetworkManager { stop_token: StopToken, last_ts: u64, cur_ts: u64, - ) -> Result<(), String> { + ) -> EyreResult<()> { // log_net!("--- network manager rolling_transfers task"); { let inner = &mut *self.inner.lock(); diff --git a/veilid-core/src/network_manager/native/mod.rs b/veilid-core/src/network_manager/native/mod.rs index b194c5d5..15376ea8 100644 --- a/veilid-core/src/network_manager/native/mod.rs +++ b/veilid-core/src/network_manager/native/mod.rs @@ -61,7 +61,7 @@ struct NetworkUnlockedInner { network_manager: NetworkManager, connection_manager: ConnectionManager, // Background processes - update_network_class_task: TickTask, + update_network_class_task: TickTask, } #[derive(Clone)] @@ -266,7 +266,7 @@ impl Network { // See if our interface addresses have changed, if so we need to punt the network // and redo all our addresses. This is overkill, but anything more accurate // would require inspection of routing tables that we dont want to bother with - pub async fn check_interface_addresses(&self) -> Result { + pub async fn check_interface_addresses(&self) -> EyreResult { let mut inner = self.inner.lock(); if !inner.interfaces.refresh().await? { return Ok(false); @@ -286,7 +286,7 @@ impl Network { &self, dial_info: DialInfo, data: Vec, - ) -> Result<(), String> { + ) -> EyreResult<()> { let data_len = data.len(); let res = match dial_info.protocol_type() { ProtocolType::UDP => { @@ -300,7 +300,8 @@ impl Network { ProtocolType::WS | ProtocolType::WSS => { WebsocketProtocolHandler::send_unbound_message(dial_info.clone(), data).await } - }; + } + .wrap_err("low level network error"); if res.is_ok() { // Network accounting self.network_manager() @@ -320,7 +321,7 @@ impl Network { dial_info: DialInfo, data: Vec, timeout_ms: u32, - ) -> Result, String> { + ) -> EyreResult> { let data_len = data.len(); let out = match dial_info.protocol_type() { ProtocolType::UDP => { @@ -358,7 +359,7 @@ impl Network { &self, descriptor: ConnectionDescriptor, data: Vec, - ) -> Result>, String> { + ) -> EyreResult>> { let data_len = data.len(); // Handle connectionless protocol @@ -369,12 +370,10 @@ impl Network { &peer_socket_addr, &descriptor.local().map(|sa| sa.to_socket_addr()), ) { - log_net!( - "send_data_to_existing_connection connectionless to {:?}", - descriptor - ); - - ph.clone().send_message(data, peer_socket_addr).await?; + ph.clone() + .send_message(data, peer_socket_addr) + .await + .wrap_err("sending data to existing conection")?; // Network accounting self.network_manager() @@ -389,10 +388,10 @@ impl Network { // Try to send to the exact existing connection if one exists if let Some(conn) = self.connection_manager().get_connection(descriptor).await { - log_net!("send_data_to_existing_connection to {:?}", descriptor); - // connection exists, send over it - conn.send_async(data).await?; + conn.send_async(data) + .await + .wrap_err("sending data to existing connection")?; // Network accounting self.network_manager() @@ -413,13 +412,16 @@ impl Network { &self, dial_info: DialInfo, data: Vec, - ) -> Result<(), String> { + ) -> EyreResult<()> { let data_len = data.len(); // Handle connectionless protocol if dial_info.protocol_type() == ProtocolType::UDP { let peer_socket_addr = dial_info.to_socket_addr(); if let Some(ph) = self.find_best_udp_protocol_handler(&peer_socket_addr, &None) { - let res = ph.send_message(data, peer_socket_addr).await; + let res = ph + .send_message(data, peer_socket_addr) + .await + .wrap_err("failed to send data to dial info"); if res.is_ok() { // Network accounting self.network_manager() @@ -427,7 +429,7 @@ impl Network { } return res; } - return Err("no appropriate UDP protocol handler for dial_info".to_owned()); + bail!("no appropriate UDP protocol handler for dial_info"); } // Handle connection-oriented protocols @@ -453,7 +455,7 @@ impl Network { } #[instrument(level = "debug", err, skip_all)] - pub async fn startup(&self) -> Result<(), String> { + pub async fn startup(&self) -> EyreResult<()> { // initialize interfaces let mut interfaces = NetworkInterfaces::new(); interfaces.refresh().await?; @@ -604,7 +606,7 @@ impl Network { ////////////////////////////////////////// - pub async fn tick(&self) -> Result<(), String> { + pub async fn tick(&self) -> EyreResult<()> { let network_class = self.get_network_class().unwrap_or(NetworkClass::Invalid); let routing_table = self.routing_table(); diff --git a/veilid-core/src/network_manager/native/network_class_discovery.rs b/veilid-core/src/network_manager/native/network_class_discovery.rs index 73be25a1..7810fe82 100644 --- a/veilid-core/src/network_manager/native/network_class_discovery.rs +++ b/veilid-core/src/network_manager/native/network_class_discovery.rs @@ -250,7 +250,7 @@ impl DiscoveryContext { // If we know we are not behind NAT, check our firewall status #[instrument(level = "trace", skip(self), err)] - pub async fn protocol_process_no_nat(&self) -> Result<(), String> { + pub async fn protocol_process_no_nat(&self) -> EyreResult<()> { let (node_1, external_1_dial_info) = { let inner = self.inner.lock(); ( @@ -281,7 +281,7 @@ impl DiscoveryContext { // If we know we are behind NAT check what kind #[instrument(level = "trace", skip(self), ret, err)] - pub async fn protocol_process_nat(&self) -> Result { + pub async fn protocol_process_nat(&self) -> EyreResult { let (node_1, external_1_dial_info, external_1_address, protocol_type, address_type) = { let inner = self.inner.lock(); ( @@ -375,7 +375,7 @@ impl Network { &self, context: &DiscoveryContext, protocol_type: ProtocolType, - ) -> Result<(), String> { + ) -> EyreResult<()> { let mut retry_count = { let c = self.config.get(); c.network.restricted_nat_retries @@ -437,7 +437,7 @@ impl Network { &self, context: &DiscoveryContext, protocol_type: ProtocolType, - ) -> Result<(), String> { + ) -> EyreResult<()> { // Start doing ipv6 protocol context.protocol_begin(protocol_type, AddressType::IPV6); @@ -479,7 +479,7 @@ impl Network { stop_token: StopToken, _l: u64, _t: u64, - ) -> Result<(), String> { + ) -> EyreResult<()> { // Ensure we aren't trying to update this without clearing it first let old_network_class = self.inner.lock().network_class; assert_eq!(old_network_class, None); diff --git a/veilid-core/src/network_manager/native/network_tcp.rs b/veilid-core/src/network_manager/native/network_tcp.rs index d4050345..1fbd0e6b 100644 --- a/veilid-core/src/network_manager/native/network_tcp.rs +++ b/veilid-core/src/network_manager/native/network_tcp.rs @@ -25,14 +25,14 @@ impl ListenerState { ///////////////////////////////////////////////////////////////// impl Network { - fn get_or_create_tls_acceptor(&self) -> Result { + fn get_or_create_tls_acceptor(&self) -> EyreResult { if let Some(ts) = self.inner.lock().tls_acceptor.as_ref() { return Ok(ts.clone()); } let server_config = self .load_server_config() - .map_err(|e| format!("Couldn't create TLS configuration: {}", e))?; + .wrap_err("Couldn't create TLS configuration")?; let acceptor = TlsAcceptor::from(Arc::new(server_config)); self.inner.lock().tls_acceptor = Some(acceptor.clone()); Ok(acceptor) @@ -45,12 +45,11 @@ impl Network { addr: SocketAddr, protocol_handlers: &[Box], tls_connection_initial_timeout_ms: u32, - ) -> Result, String> { + ) -> EyreResult> { let tls_stream = tls_acceptor .accept(stream) .await - .map_err(map_to_string) - .map_err(logthru_net!(debug "TLS stream failed handshake"))?; + .wrap_err("TLS stream failed handshake")?; let ps = AsyncPeekStream::new(tls_stream); let mut first_packet = [0u8; PEEK_DETECT_LEN]; @@ -63,8 +62,8 @@ impl Network { ps.peek_exact(&mut first_packet), ) .await - .map_err(map_to_string)? - .map_err(map_to_string)?; + .wrap_err("tls initial timeout")? + .wrap_err("failed to peek tls stream")?; self.try_handlers(ps, addr, protocol_handlers).await } @@ -74,9 +73,13 @@ impl Network { stream: AsyncPeekStream, addr: SocketAddr, protocol_accept_handlers: &[Box], - ) -> Result, String> { + ) -> EyreResult> { for ah in protocol_accept_handlers.iter() { - if let Some(nc) = ah.on_accept(stream.clone(), addr).await? { + if let Some(nc) = ah + .on_accept(stream.clone(), addr) + .await + .wrap_err("io error")? + { return Ok(Some(nc)); } } @@ -114,7 +117,7 @@ impl Network { return; } }; - // XXX limiting + // XXX limiting here instead for connection table? may be faster and avoids tls negotiation log_net!("TCP connection from: {}", addr); @@ -185,7 +188,7 @@ impl Network { } } - async fn spawn_socket_listener(&self, addr: SocketAddr) -> Result<(), String> { + async fn spawn_socket_listener(&self, addr: SocketAddr) -> EyreResult<()> { // Get config let (connection_initial_timeout_ms, tls_connection_initial_timeout_ms) = { let c = self.config.get(); @@ -196,11 +199,12 @@ impl Network { }; // Create a reusable socket with no linger time, and no delay - let socket = new_bound_shared_tcp_socket(addr)?; + let socket = new_bound_shared_tcp_socket(addr) + .wrap_err("failed to create bound shared tcp socket")?; // Listen on the socket socket .listen(128) - .map_err(|e| format!("Couldn't listen on TCP socket: {}", e))?; + .wrap_err("Couldn't listen on TCP socket")?; // Make an async tcplistener from the socket2 socket let std_listener: std::net::TcpListener = socket.into(); @@ -209,7 +213,7 @@ impl Network { let listener = TcpListener::from(std_listener); } else if #[cfg(feature="rt-tokio")] { std_listener.set_nonblocking(true).expect("failed to set nonblocking"); - let listener = TcpListener::from_std(std_listener).map_err(map_to_string)?; + let listener = TcpListener::from_std(std_listener).wrap_err("failed to create tokio tcp listener")?; } } @@ -279,7 +283,7 @@ impl Network { port: u16, is_tls: bool, new_protocol_accept_handler: Box, - ) -> Result, String> { + ) -> EyreResult> { let mut out = Vec::::new(); for ip_addr in ip_addrs { diff --git a/veilid-core/src/network_manager/native/network_udp.rs b/veilid-core/src/network_manager/native/network_udp.rs index 3f6c8570..1627afb0 100644 --- a/veilid-core/src/network_manager/native/network_udp.rs +++ b/veilid-core/src/network_manager/native/network_udp.rs @@ -3,7 +3,7 @@ use sockets::*; use stop_token::future::FutureExt; impl Network { - pub(super) async fn create_udp_listener_tasks(&self) -> Result<(), String> { + pub(super) async fn create_udp_listener_tasks(&self) -> EyreResult<()> { // Spawn socket tasks let mut task_count = { let c = self.config.get(); @@ -73,7 +73,7 @@ impl Network { .on_recv_envelope(&data[..size], descriptor) .await { - log_net!(error "failed to process received udp envelope: {}", e); + log_net!(debug "failed to process received udp envelope: {}", e); } } Ok(Err(_)) => { @@ -110,7 +110,7 @@ impl Network { Ok(()) } - pub(super) async fn create_udp_outbound_sockets(&self) -> Result<(), String> { + pub(super) async fn create_udp_outbound_sockets(&self) -> EyreResult<()> { let mut inner = self.inner.lock(); let mut port = inner.udp_port; // v4 @@ -119,9 +119,9 @@ impl Network { // Pull the port if we randomly bound, so v6 can be on the same port port = socket .local_addr() - .map_err(map_to_string)? + .wrap_err("failed to get local address")? .as_socket_ipv4() - .ok_or_else(|| "expected ipv4 address type".to_owned())? + .ok_or_else(|| eyre!("expected ipv4 address type"))? .port(); // Make an async UdpSocket from the socket2 socket @@ -131,7 +131,7 @@ impl Network { let udp_socket = UdpSocket::from(std_udp_socket); } else if #[cfg(feature="rt-tokio")] { std_udp_socket.set_nonblocking(true).expect("failed to set nonblocking"); - let udp_socket = UdpSocket::from_std(std_udp_socket).map_err(map_to_string)?; + let udp_socket = UdpSocket::from_std(std_udp_socket).wrap_err("failed to make outbound v4 tokio udpsocket")?; } } let socket_arc = Arc::new(udp_socket); @@ -152,7 +152,7 @@ impl Network { let udp_socket = UdpSocket::from(std_udp_socket); } else if #[cfg(feature="rt-tokio")] { std_udp_socket.set_nonblocking(true).expect("failed to set nonblocking"); - let udp_socket = UdpSocket::from_std(std_udp_socket).map_err(map_to_string)?; + let udp_socket = UdpSocket::from_std(std_udp_socket).wrap_err("failed to make outbound v6 tokio udpsocket")?; } } let socket_arc = Arc::new(udp_socket); @@ -166,7 +166,7 @@ impl Network { Ok(()) } - async fn create_udp_inbound_socket(&self, addr: SocketAddr) -> Result<(), String> { + async fn create_udp_inbound_socket(&self, addr: SocketAddr) -> EyreResult<()> { log_net!("create_udp_inbound_socket on {:?}", &addr); // Create a reusable socket @@ -179,7 +179,7 @@ impl Network { let udp_socket = UdpSocket::from(std_udp_socket); } else if #[cfg(feature="rt-tokio")] { std_udp_socket.set_nonblocking(true).expect("failed to set nonblocking"); - let udp_socket = UdpSocket::from_std(std_udp_socket).map_err(map_to_string)?; + let udp_socket = UdpSocket::from_std(std_udp_socket).wrap_err("failed to make inbound tokio udpsocket")?; } } let socket_arc = Arc::new(udp_socket); @@ -200,7 +200,7 @@ impl Network { &self, ip_addrs: Vec, port: u16, - ) -> Result, String> { + ) -> EyreResult> { let mut out = Vec::::new(); for ip_addr in ip_addrs { diff --git a/veilid-core/src/network_manager/native/protocol/mod.rs b/veilid-core/src/network_manager/native/protocol/mod.rs index 26291f76..77f95a0d 100644 --- a/veilid-core/src/network_manager/native/protocol/mod.rs +++ b/veilid-core/src/network_manager/native/protocol/mod.rs @@ -6,6 +6,7 @@ pub mod ws; use super::*; use crate::xx::*; +use std::io; #[derive(Debug)] pub enum ProtocolNetworkConnection { @@ -21,7 +22,7 @@ impl ProtocolNetworkConnection { pub async fn connect( local_address: Option, dial_info: DialInfo, - ) -> Result { + ) -> io::Result { match dial_info.protocol_type() { ProtocolType::UDP => { panic!("Should not connect to UDP dialinfo"); @@ -35,7 +36,7 @@ impl ProtocolNetworkConnection { } } - 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<()> { match dial_info.protocol_type() { ProtocolType::UDP => { let peer_socket_addr = dial_info.to_socket_addr(); @@ -55,7 +56,7 @@ impl ProtocolNetworkConnection { dial_info: DialInfo, data: Vec, timeout_ms: u32, - ) -> Result, String> { + ) -> io::Result> { match dial_info.protocol_type() { ProtocolType::UDP => { let peer_socket_addr = dial_info.to_socket_addr(); @@ -102,7 +103,7 @@ impl ProtocolNetworkConnection { // } // } - pub async fn send(&self, message: Vec) -> Result<(), String> { + pub async fn send(&self, message: Vec) -> io::Result<()> { match self { Self::Dummy(d) => d.send(message), Self::RawTcp(t) => t.send(message).await, @@ -111,7 +112,7 @@ impl ProtocolNetworkConnection { Self::Wss(w) => w.send(message).await, } } - pub async fn recv(&self) -> Result, String> { + pub async fn recv(&self) -> io::Result> { match self { Self::Dummy(d) => d.recv(), Self::RawTcp(t) => t.recv().await, diff --git a/veilid-core/src/network_manager/native/protocol/sockets.rs b/veilid-core/src/network_manager/native/protocol/sockets.rs index bd7aa6d2..6c4b3cc5 100644 --- a/veilid-core/src/network_manager/native/protocol/sockets.rs +++ b/veilid-core/src/network_manager/native/protocol/sockets.rs @@ -1,6 +1,8 @@ use crate::xx::*; use crate::*; use async_io::Async; +use std::io; + cfg_if! { if #[cfg(feature="rt-async-std")] { pub use async_std::net::{TcpStream, TcpListener, Shutdown, UdpSocket}; @@ -19,12 +21,12 @@ cfg_if! { use winapi::ctypes::c_int; use std::os::windows::io::AsRawSocket; - fn set_exclusiveaddruse(socket: &Socket) -> Result<(), String> { + fn set_exclusiveaddruse(socket: &Socket) -> io::Result<()> { unsafe { let optval:c_int = 1; if setsockopt(socket.as_raw_socket().try_into().unwrap(), SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (&optval as *const c_int).cast(), std::mem::size_of::() as c_int) == SOCKET_ERROR { - return Err("Unable to SO_EXCLUSIVEADDRUSE".to_owned()); + return Err(io::Error::last_os_error()); } Ok(()) } @@ -32,49 +34,37 @@ cfg_if! { } } -pub fn new_unbound_shared_udp_socket(domain: Domain) -> Result { - let socket = Socket::new(domain, Type::DGRAM, Some(Protocol::UDP)) - .map_err(|e| format!("Couldn't create UDP socket: {}", e))?; +pub fn new_unbound_shared_udp_socket(domain: Domain) -> io::Result { + let socket = Socket::new(domain, Type::DGRAM, Some(Protocol::UDP))?; if domain == Domain::IPV6 { - socket - .set_only_v6(true) - .map_err(|e| format!("Couldn't set IPV6_V6ONLY: {}", e))?; + socket.set_only_v6(true)?; } - socket - .set_reuse_address(true) - .map_err(|e| format!("Couldn't set reuse address: {}", e))?; + socket.set_reuse_address(true)?; + cfg_if! { if #[cfg(unix)] { - socket.set_reuse_port(true).map_err(|e| format!("Couldn't set reuse port: {}", e))?; + socket.set_reuse_port(true)?; } } Ok(socket) } -pub fn new_bound_shared_udp_socket(local_address: SocketAddr) -> Result { +pub fn new_bound_shared_udp_socket(local_address: SocketAddr) -> io::Result { let domain = Domain::for_address(local_address); let socket = new_unbound_shared_udp_socket(domain)?; let socket2_addr = SockAddr::from(local_address); - socket.bind(&socket2_addr).map_err(|e| { - format!( - "failed to bind UDP socket to '{}' in domain '{:?}': {} ", - local_address, domain, e - ) - })?; + socket.bind(&socket2_addr)?; log_net!("created bound shared udp socket on {:?}", &local_address); Ok(socket) } -pub fn new_bound_first_udp_socket(local_address: SocketAddr) -> Result { +pub fn new_bound_first_udp_socket(local_address: SocketAddr) -> io::Result { let domain = Domain::for_address(local_address); - let socket = Socket::new(domain, Type::DGRAM, Some(Protocol::UDP)) - .map_err(|e| format!("Couldn't create UDP socket: {}", e))?; + let socket = Socket::new(domain, Type::DGRAM, Some(Protocol::UDP))?; if domain == Domain::IPV6 { - socket - .set_only_v6(true) - .map_err(|e| format!("Couldn't set IPV6_V6ONLY: {}", e))?; + socket.set_only_v6(true)?; } // Bind the socket -first- before turning on 'reuse address' this way it will // fail if the port is already taken @@ -87,18 +77,15 @@ pub fn new_bound_first_udp_socket(local_address: SocketAddr) -> Result Result Result { - let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP)) - .map_err(map_to_string) - .map_err(logthru_net!("failed to create TCP socket"))?; +pub fn new_unbound_shared_tcp_socket(domain: Domain) -> io::Result { + let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?; if let Err(e) = socket.set_linger(Some(core::time::Duration::from_secs(0))) { log_net!(error "Couldn't set TCP linger: {}", e); } @@ -117,43 +102,33 @@ pub fn new_unbound_shared_tcp_socket(domain: Domain) -> Result { log_net!(error "Couldn't set TCP nodelay: {}", e); } if domain == Domain::IPV6 { - socket - .set_only_v6(true) - .map_err(|e| format!("Couldn't set IPV6_V6ONLY: {}", e))?; + socket.set_only_v6(true)?; } - socket - .set_reuse_address(true) - .map_err(|e| format!("Couldn't set reuse address: {}", e))?; + socket.set_reuse_address(true)?; cfg_if! { if #[cfg(unix)] { - socket.set_reuse_port(true).map_err(|e| format!("Couldn't set reuse port: {}", e))?; + socket.set_reuse_port(true)?; } } Ok(socket) } -pub fn new_bound_shared_tcp_socket(local_address: SocketAddr) -> Result { +pub fn new_bound_shared_tcp_socket(local_address: SocketAddr) -> io::Result { let domain = Domain::for_address(local_address); - let socket = new_unbound_shared_tcp_socket(domain)?; - let socket2_addr = SockAddr::from(local_address); - socket - .bind(&socket2_addr) - .map_err(|e| format!("failed to bind TCP socket: {}", e))?; + socket.bind(&socket2_addr)?; log_net!("created bound shared tcp socket on {:?}", &local_address); Ok(socket) } -pub fn new_bound_first_tcp_socket(local_address: SocketAddr) -> Result { +pub fn new_bound_first_tcp_socket(local_address: SocketAddr) -> io::Result { let domain = Domain::for_address(local_address); - let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP)) - .map_err(map_to_string) - .map_err(logthru_net!("failed to create TCP socket"))?; + let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?; if let Err(e) = socket.set_linger(Some(core::time::Duration::from_secs(0))) { log_net!(error "Couldn't set TCP linger: {}", e); } @@ -161,9 +136,7 @@ pub fn new_bound_first_tcp_socket(local_address: SocketAddr) -> Result Result Result std::io::Result { +pub async fn nonblocking_connect(socket: Socket, addr: SocketAddr) -> io::Result { // Set for non blocking connect socket.set_nonblocking(true)?; diff --git a/veilid-core/src/network_manager/native/protocol/tcp.rs b/veilid-core/src/network_manager/native/protocol/tcp.rs index de54e18c..0b4feed5 100644 --- a/veilid-core/src/network_manager/native/protocol/tcp.rs +++ b/veilid-core/src/network_manager/native/protocol/tcp.rs @@ -42,47 +42,45 @@ impl RawTcpNetworkConnection { // } // } - async fn send_internal(stream: &mut AsyncPeekStream, message: Vec) -> Result<(), String> { + async fn send_internal(stream: &mut AsyncPeekStream, message: Vec) -> io::Result<()> { log_net!("sending TCP message of size {}", message.len()); if message.len() > MAX_MESSAGE_SIZE { - return Err("sending too large TCP message".to_owned()); + bail_io_error_other!("sending too large TCP message"); } let len = message.len() as u16; let header = [b'V', b'L', len as u8, (len >> 8) as u8]; - stream.write_all(&header).await.map_err(map_to_string)?; - stream.write_all(&message).await.map_err(map_to_string) + stream.write_all(&header).await?; + stream.write_all(&message).await } #[instrument(level="trace", err, skip(self, message), fields(message.len = message.len()))] - pub async fn send(&self, message: Vec) -> Result<(), String> { + pub async fn send(&self, message: Vec) -> io::Result<()> { let mut stream = self.stream.clone(); Self::send_internal(&mut stream, message).await } - pub async fn recv_internal(stream: &mut AsyncPeekStream) -> Result, String> { + pub async fn recv_internal(stream: &mut AsyncPeekStream) -> io::Result> { let mut header = [0u8; 4]; - stream - .read_exact(&mut header) - .await - .map_err(|e| format!("TCP recv error: {}", e))?; + stream.read_exact(&mut header).await?; + if header[0] != b'V' || header[1] != b'L' { - return Err("received invalid TCP frame header".to_owned()); + bail_io_error_other!("received invalid TCP frame header"); } let len = ((header[3] as usize) << 8) | (header[2] as usize); if len > MAX_MESSAGE_SIZE { - return Err("received too large TCP frame".to_owned()); + bail_io_error_other!("received too large TCP frame"); } let mut out: Vec = vec![0u8; len]; - stream.read_exact(&mut out).await.map_err(map_to_string)?; + stream.read_exact(&mut out).await?; Ok(out) } #[instrument(level="trace", err, skip(self), fields(ret.len))] - pub async fn recv(&self) -> Result, String> { + pub async fn recv(&self) -> io::Result> { let mut stream = self.stream.clone(); let out = Self::recv_internal(&mut stream).await?; tracing::Span::current().record("ret.len", &out.len()); @@ -121,14 +119,10 @@ impl RawTcpProtocolHandler { self, stream: AsyncPeekStream, socket_addr: SocketAddr, - ) -> Result, String> { + ) -> io::Result> { log_net!("TCP: on_accept_async: enter"); let mut peekbuf: [u8; PEEK_DETECT_LEN] = [0u8; PEEK_DETECT_LEN]; - let peeklen = stream - .peek(&mut peekbuf) - .await - .map_err(map_to_string) - .map_err(logthru_net!("could not peek tcp stream"))?; + let peeklen = stream.peek(&mut peekbuf).await?; assert_eq!(peeklen, PEEK_DETECT_LEN); let peer_addr = PeerAddress::new( @@ -150,7 +144,7 @@ impl RawTcpProtocolHandler { pub async fn connect( local_address: Option, dial_info: DialInfo, - ) -> Result { + ) -> io::Result { // Get remote socket address to connect to let remote_socket_addr = dial_info.to_socket_addr(); @@ -163,15 +157,10 @@ impl RawTcpProtocolHandler { }; // Non-blocking connect to remote address - let ts = nonblocking_connect(socket, remote_socket_addr).await - .map_err(map_to_string) - .map_err(logthru_net!(error "local_address={:?} remote_addr={}", local_address, remote_socket_addr))?; + let ts = nonblocking_connect(socket, remote_socket_addr).await?; // See what local address we ended up with and turn this into a stream - let actual_local_address = ts - .local_addr() - .map_err(map_to_string) - .map_err(logthru_net!("could not get local address from TCP stream"))?; + let actual_local_address = ts.local_addr()?; #[cfg(feature = "rt-tokio")] let ts = ts.compat(); let ps = AsyncPeekStream::new(ts); @@ -189,12 +178,9 @@ impl RawTcpProtocolHandler { } #[instrument(level = "trace", err, skip(data), fields(data.len = data.len()))] - pub async fn send_unbound_message( - socket_addr: SocketAddr, - data: Vec, - ) -> Result<(), String> { + pub async fn send_unbound_message(socket_addr: SocketAddr, data: Vec) -> io::Result<()> { if data.len() > MAX_MESSAGE_SIZE { - return Err("sending too large unbound TCP message".to_owned()); + bail_io_error_other!("sending too large unbound TCP message"); } trace!( "sending unbound message of length {} to {}", @@ -206,10 +192,7 @@ impl RawTcpProtocolHandler { let socket = new_unbound_shared_tcp_socket(socket2::Domain::for_address(socket_addr))?; // Non-blocking connect to remote address - let ts = nonblocking_connect(socket, socket_addr) - .await - .map_err(map_to_string) - .map_err(logthru_net!(error "remote_addr={}", socket_addr))?; + let ts = nonblocking_connect(socket, socket_addr).await?; // See what local address we ended up with and turn this into a stream // let actual_local_address = ts @@ -231,9 +214,9 @@ impl RawTcpProtocolHandler { socket_addr: SocketAddr, data: Vec, timeout_ms: u32, - ) -> Result, String> { + ) -> io::Result> { if data.len() > MAX_MESSAGE_SIZE { - return Err("sending too large unbound TCP message".to_owned()); + bail_io_error_other!("sending too large unbound TCP message"); } trace!( "sending unbound message of length {} to {}", @@ -245,10 +228,7 @@ impl RawTcpProtocolHandler { let socket = new_unbound_shared_tcp_socket(socket2::Domain::for_address(socket_addr))?; // Non-blocking connect to remote address - let ts = nonblocking_connect(socket, socket_addr) - .await - .map_err(map_to_string) - .map_err(logthru_net!(error "remote_addr={}", socket_addr))?; + let ts = nonblocking_connect(socket, socket_addr).await?; // See what local address we ended up with and turn this into a stream // let actual_local_address = ts @@ -265,7 +245,7 @@ impl RawTcpProtocolHandler { let out = timeout(timeout_ms, RawTcpNetworkConnection::recv_internal(&mut ps)) .await - .map_err(map_to_string)??; + .map_err(|e| e.to_io())??; tracing::Span::current().record("ret.len", &out.len()); Ok(out) @@ -277,7 +257,7 @@ impl ProtocolAcceptHandler for RawTcpProtocolHandler { &self, stream: AsyncPeekStream, peer_addr: SocketAddr, - ) -> SystemPinBoxFuture, String>> { + ) -> SystemPinBoxFuture>> { Box::pin(self.clone().on_accept_async(stream, peer_addr)) } } diff --git a/veilid-core/src/network_manager/native/protocol/udp.rs b/veilid-core/src/network_manager/native/protocol/udp.rs index 1d31f21b..2c71294c 100644 --- a/veilid-core/src/network_manager/native/protocol/udp.rs +++ b/veilid-core/src/network_manager/native/protocol/udp.rs @@ -12,27 +12,30 @@ impl RawUdpProtocolHandler { } #[instrument(level = "trace", err, skip(self, data), fields(data.len = data.len(), ret.len, ret.from))] - pub async fn recv_message( - &self, - data: &mut [u8], - ) -> Result<(usize, ConnectionDescriptor), String> { - let (size, remote_addr) = self.socket.recv_from(data).await.map_err(map_to_string)?; - - if size > MAX_MESSAGE_SIZE { - return Err("received too large UDP message".to_owned()); - } - - trace!( - "receiving UDP message of length {} from {}", - size, - remote_addr - ); + pub async fn recv_message(&self, data: &mut [u8]) -> io::Result<(usize, ConnectionDescriptor)> { + let (size, remote_addr) = loop { + match self.socket.recv_from(data).await { + Ok((size, remote_addr)) => { + if size > MAX_MESSAGE_SIZE { + bail_io_error_other!("received too large UDP message"); + } + break (size, remote_addr); + } + Err(e) => { + if e.kind() == io::ErrorKind::ConnectionReset { + // Ignore icmp + } else { + return Err(e); + } + } + } + }; let peer_addr = PeerAddress::new( SocketAddress::from_socket_addr(remote_addr), ProtocolType::UDP, ); - let local_socket_addr = self.socket.local_addr().map_err(map_to_string)?; + let local_socket_addr = self.socket.local_addr()?; let descriptor = ConnectionDescriptor::new( peer_addr, SocketAddress::from_socket_addr(local_socket_addr), @@ -44,45 +47,24 @@ impl RawUdpProtocolHandler { } #[instrument(level = "trace", err, skip(self, data), fields(data.len = data.len(), ret.len, ret.from))] - pub async fn send_message(&self, data: Vec, socket_addr: SocketAddr) -> Result<(), String> { + pub async fn send_message(&self, data: Vec, socket_addr: SocketAddr) -> io::Result<()> { if data.len() > MAX_MESSAGE_SIZE { - return Err("sending too large UDP message".to_owned()).map_err(logthru_net!(error)); + bail_io_error_other!("sending too large UDP message"); } - log_net!( - "sending UDP message of length {} to {}", - data.len(), - socket_addr - ); - - let len = self - .socket - .send_to(&data, socket_addr) - .await - .map_err(map_to_string) - .map_err(logthru_net!(error "failed udp send: addr={}", socket_addr))?; - + let len = self.socket.send_to(&data, socket_addr).await?; if len != data.len() { - Err("UDP partial send".to_owned()).map_err(logthru_net!(error)) - } else { - Ok(()) + bail_io_error_other!("UDP partial send") } + + Ok(()) } #[instrument(level = "trace", err, skip(data), fields(data.len = data.len()))] - pub async fn send_unbound_message( - socket_addr: SocketAddr, - data: Vec, - ) -> Result<(), String> { + pub async fn send_unbound_message(socket_addr: SocketAddr, data: Vec) -> io::Result<()> { if data.len() > MAX_MESSAGE_SIZE { - return Err("sending too large unbound UDP message".to_owned()) - .map_err(logthru_net!(error)); + bail_io_error_other!("sending too large unbound UDP message"); } - log_net!( - "sending unbound message of length {} to {}", - data.len(), - socket_addr - ); // get local wildcard address for bind let local_socket_addr = match socket_addr { @@ -91,20 +73,13 @@ impl RawUdpProtocolHandler { SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), 0) } }; - let socket = UdpSocket::bind(local_socket_addr) - .await - .map_err(map_to_string) - .map_err(logthru_net!(error "failed to bind unbound udp socket"))?; - let len = socket - .send_to(&data, socket_addr) - .await - .map_err(map_to_string) - .map_err(logthru_net!(error "failed unbound udp send: addr={}", socket_addr))?; + let socket = UdpSocket::bind(local_socket_addr).await?; + let len = socket.send_to(&data, socket_addr).await?; if len != data.len() { - Err("UDP partial unbound send".to_owned()).map_err(logthru_net!(error)) - } else { - Ok(()) + bail_io_error_other!("UDP partial unbound send") } + + Ok(()) } #[instrument(level = "trace", err, skip(data), fields(data.len = data.len(), ret.len))] @@ -112,16 +87,10 @@ impl RawUdpProtocolHandler { socket_addr: SocketAddr, data: Vec, timeout_ms: u32, - ) -> Result, String> { + ) -> io::Result> { if data.len() > MAX_MESSAGE_SIZE { - return Err("sending too large unbound UDP message".to_owned()) - .map_err(logthru_net!(error)); + bail_io_error_other!("sending too large unbound UDP message"); } - log_net!( - "sending unbound message of length {} to {}", - data.len(), - socket_addr - ); // get local wildcard address for bind let local_socket_addr = match socket_addr { @@ -132,29 +101,21 @@ impl RawUdpProtocolHandler { }; // get unspecified bound socket - let socket = UdpSocket::bind(local_socket_addr) - .await - .map_err(map_to_string) - .map_err(logthru_net!(error "failed to bind unbound udp socket"))?; - let len = socket - .send_to(&data, socket_addr) - .await - .map_err(map_to_string) - .map_err(logthru_net!(error "failed unbound udp send: addr={}", socket_addr))?; + let socket = UdpSocket::bind(local_socket_addr).await?; + let len = socket.send_to(&data, socket_addr).await?; if len != data.len() { - return Err("UDP partial unbound send".to_owned()).map_err(logthru_net!(error)); + bail_io_error_other!("UDP partial unbound send"); } // receive single response let mut out = vec![0u8; MAX_MESSAGE_SIZE]; let (len, from_addr) = timeout(timeout_ms, socket.recv_from(&mut out)) .await - .map_err(map_to_string)? - .map_err(map_to_string)?; + .map_err(|e| e.to_io())??; // if the from address is not the same as the one we sent to, then drop this if from_addr != socket_addr { - return Err(format!( + bail_io_error_other!(format!( "Unbound response received from wrong address: addr={}", from_addr, )); diff --git a/veilid-core/src/network_manager/native/protocol/ws.rs b/veilid-core/src/network_manager/native/protocol/ws.rs index 753e716a..b2b5092d 100644 --- a/veilid-core/src/network_manager/native/protocol/ws.rs +++ b/veilid-core/src/network_manager/native/protocol/ws.rs @@ -17,6 +17,25 @@ cfg_if! { } } +fn to_io(err: async_tungstenite::tungstenite::Error) -> io::Error { + let kind = match err { + async_tungstenite::tungstenite::Error::ConnectionClosed => io::ErrorKind::ConnectionReset, + async_tungstenite::tungstenite::Error::AlreadyClosed => io::ErrorKind::NotConnected, + async_tungstenite::tungstenite::Error::Io(x) => { + return x; + } + async_tungstenite::tungstenite::Error::Tls(_) => io::ErrorKind::InvalidData, + async_tungstenite::tungstenite::Error::Capacity(_) => io::ErrorKind::Other, + async_tungstenite::tungstenite::Error::Protocol(_) => io::ErrorKind::Other, + async_tungstenite::tungstenite::Error::SendQueueFull(_) => io::ErrorKind::Other, + async_tungstenite::tungstenite::Error::Utf8 => io::ErrorKind::Other, + async_tungstenite::tungstenite::Error::Url(_) => io::ErrorKind::Other, + async_tungstenite::tungstenite::Error::Http(_) => io::ErrorKind::Other, + async_tungstenite::tungstenite::Error::HttpFormat(_) => io::ErrorKind::Other, + }; + io::Error::new(kind, err) +} + pub type WebSocketNetworkConnectionAccepted = WebsocketNetworkConnection; pub struct WebsocketNetworkConnection @@ -62,41 +81,49 @@ where // } #[instrument(level = "trace", err, skip(self, message), fields(message.len = message.len()))] - pub async fn send(&self, message: Vec) -> Result<(), String> { + pub async fn send(&self, message: Vec) -> io::Result<()> { if message.len() > MAX_MESSAGE_SIZE { - return Err("received too large WS message".to_owned()); + bail_io_error_other!("received too large WS message"); } self.stream .clone() .send(Message::binary(message)) .await - .map_err(map_to_string) - .map_err(logthru_net!(error "failed to send websocket message")) + .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.stream.clone().next().await { - Some(Ok(Message::Binary(v))) => v, - Some(Ok(Message::Close(e))) => { - return Err(format!("WS connection closed: {:?}", e)); + Some(Ok(Message::Binary(v))) => { + if v.len() > MAX_MESSAGE_SIZE { + return Err(io::Error::new( + io::ErrorKind::ConnectionReset, + "too large ws message", + )); + } + v + } + Some(Ok(Message::Close(_))) => { + return Err(io::Error::new(io::ErrorKind::ConnectionReset, "closeframe")) } Some(Ok(x)) => { - return Err(format!("Unexpected WS message type: {:?}", x)); - } - Some(Err(e)) => { - return Err(e.to_string()).map_err(logthru_net!(error)); + return Err(io::Error::new( + io::ErrorKind::InvalidData, + format!("Unexpected WS message type: {:?}", x), + )); } + Some(Err(e)) => return Err(to_io(e)), None => { - return Err("WS stream closed".to_owned()); + return Err(io::Error::new( + io::ErrorKind::ConnectionReset, + "connection ended", + )) } }; - if out.len() > MAX_MESSAGE_SIZE { - Err("sending too large WS message".to_owned()).map_err(logthru_net!(error)) - } else { - tracing::Span::current().record("ret.len", &out.len()); - Ok(out) - } + + tracing::Span::current().record("ret.len", &out.len()); + Ok(out) } } @@ -145,21 +172,18 @@ impl WebsocketProtocolHandler { self, ps: AsyncPeekStream, socket_addr: SocketAddr, - ) -> Result, String> { + ) -> io::Result> { log_net!("WS: on_accept_async: enter"); let request_path_len = self.arc.request_path.len() + 2; let mut peekbuf: Vec = vec![0u8; request_path_len]; - match timeout( + if let Err(_) = timeout( self.arc.connection_initial_timeout_ms, ps.peek_exact(&mut peekbuf), ) .await { - Ok(_) => (), - Err(e) => { - return Err(e.to_string()); - } + return Ok(None); } // Check for websocket path @@ -169,15 +193,12 @@ impl WebsocketProtocolHandler { && peekbuf[request_path_len - 1] == b' ')); if !matches_path { - log_net!("WS: not websocket"); return Ok(None); } - log_net!("WS: found websocket"); let ws_stream = accept_async(ps) .await - .map_err(map_to_string) - .map_err(logthru_net!("failed websockets handshake"))?; + .map_err(|e| io_error_other!(format!("failed websockets handshake: {}", e)))?; // Wrap the websocket in a NetworkConnection and register it let protocol_type = if self.arc.tls { @@ -205,7 +226,7 @@ impl WebsocketProtocolHandler { async fn connect_internal( local_address: Option, dial_info: DialInfo, - ) -> Result { + ) -> io::Result { // Split dial info up let (tls, scheme) = match &dial_info { DialInfo::WS(_) => (false, "ws"), @@ -213,9 +234,9 @@ 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 domain = split_url.host.clone(); @@ -231,12 +252,10 @@ impl WebsocketProtocolHandler { }; // Non-blocking connect to remote address - let tcp_stream = nonblocking_connect(socket, remote_socket_addr).await - .map_err(map_to_string) - .map_err(logthru_net!(error "local_address={:?} remote_addr={}", local_address, remote_socket_addr))?; + let tcp_stream = nonblocking_connect(socket, remote_socket_addr).await?; // See what local address we ended up with - let actual_local_addr = tcp_stream.local_addr().map_err(map_to_string)?; + let actual_local_addr = tcp_stream.local_addr()?; #[cfg(feature = "rt-tokio")] let tcp_stream = tcp_stream.compat(); @@ -249,15 +268,10 @@ impl WebsocketProtocolHandler { // Negotiate TLS if this is WSS if tls { let connector = TlsConnector::default(); - let tls_stream = connector - .connect(domain.to_string(), tcp_stream) - .await - .map_err(map_to_string) - .map_err(logthru_net!(error))?; + let tls_stream = connector.connect(domain.to_string(), tcp_stream).await?; let (ws_stream, _response) = client_async(request, tls_stream) .await - .map_err(map_to_string) - .map_err(logthru_net!(error))?; + .map_err(to_io_error_other)?; Ok(ProtocolNetworkConnection::Wss( WebsocketNetworkConnection::new(descriptor, ws_stream), @@ -265,8 +279,7 @@ impl WebsocketProtocolHandler { } else { let (ws_stream, _response) = client_async(request, tcp_stream) .await - .map_err(map_to_string) - .map_err(logthru_net!(error))?; + .map_err(to_io_error_other)?; Ok(ProtocolNetworkConnection::Ws( WebsocketNetworkConnection::new(descriptor, ws_stream), )) @@ -277,19 +290,17 @@ impl WebsocketProtocolHandler { pub async fn connect( local_address: Option, dial_info: DialInfo, - ) -> Result { + ) -> io::Result { Self::connect_internal(local_address, dial_info).await } #[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"); } - let protconn = Self::connect_internal(None, dial_info.clone()) - .await - .map_err(|e| format!("failed to connect websocket for unbound message: {}", e))?; + let protconn = Self::connect_internal(None, dial_info.clone()).await?; protconn.send(data).await } @@ -299,19 +310,17 @@ 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 protconn = Self::connect_internal(None, dial_info.clone()) - .await - .map_err(|e| format!("failed to connect websocket for unbound message: {}", e))?; + let protconn = Self::connect_internal(None, dial_info.clone()).await?; protconn.send(data).await?; let out = timeout(timeout_ms, protconn.recv()) .await - .map_err(map_to_string)??; + .map_err(|e| e.to_io())??; tracing::Span::current().record("ret.len", &out.len()); Ok(out) @@ -323,7 +332,7 @@ impl ProtocolAcceptHandler for WebsocketProtocolHandler { &self, stream: AsyncPeekStream, peer_addr: SocketAddr, - ) -> SystemPinBoxFuture, String>> { + ) -> SystemPinBoxFuture>> { Box::pin(self.clone().on_accept_async(stream, peer_addr)) } } diff --git a/veilid-core/src/network_manager/native/start_protocols.rs b/veilid-core/src/network_manager/native/start_protocols.rs index b64ee3bd..7f21f10a 100644 --- a/veilid-core/src/network_manager/native/start_protocols.rs +++ b/veilid-core/src/network_manager/native/start_protocols.rs @@ -164,7 +164,7 @@ impl Network { ///////////////////////////////////////////////////// - fn find_available_udp_port(&self) -> Result { + fn find_available_udp_port(&self) -> EyreResult { // If the address is empty, iterate ports until we find one we can use. let mut udp_port = 5150u16; loop { @@ -175,14 +175,14 @@ impl Network { break; } if udp_port == 65535 { - return Err("Could not find free udp port to listen on".to_owned()); + bail!("Could not find free udp port to listen on"); } udp_port += 1; } Ok(udp_port) } - fn find_available_tcp_port(&self) -> Result { + fn find_available_tcp_port(&self) -> EyreResult { // If the address is empty, iterate ports until we find one we can use. let mut tcp_port = 5150u16; loop { @@ -193,17 +193,14 @@ impl Network { break; } if tcp_port == 65535 { - return Err("Could not find free tcp port to listen on".to_owned()); + bail!("Could not find free tcp port to listen on"); } tcp_port += 1; } Ok(tcp_port) } - async fn allocate_udp_port( - &self, - listen_address: String, - ) -> Result<(u16, Vec), String> { + async fn allocate_udp_port(&self, listen_address: String) -> EyreResult<(u16, Vec)> { if listen_address.is_empty() { // If listen address is empty, find us a port iteratively let port = self.find_available_udp_port()?; @@ -217,21 +214,17 @@ impl Network { // If the address is specified, only use the specified port and fail otherwise let sockaddrs = listen_address_to_socket_addrs(&listen_address)?; if sockaddrs.is_empty() { - return Err(format!("No valid listen address: {}", listen_address)); + bail!("No valid listen address: {}", listen_address); } let port = sockaddrs[0].port(); - if self.bind_first_udp_port(port) { - Ok((port, sockaddrs.iter().map(|s| s.ip()).collect())) - } else { - Err("Could not find free udp port to listen on".to_owned()) + if !self.bind_first_udp_port(port) { + bail!("Could not find free udp port to listen on"); } + Ok((port, sockaddrs.iter().map(|s| s.ip()).collect())) } } - async fn allocate_tcp_port( - &self, - listen_address: String, - ) -> Result<(u16, Vec), String> { + async fn allocate_tcp_port(&self, listen_address: String) -> EyreResult<(u16, Vec)> { if listen_address.is_empty() { // If listen address is empty, find us a port iteratively let port = self.find_available_tcp_port()?; @@ -245,20 +238,19 @@ impl Network { // If the address is specified, only use the specified port and fail otherwise let sockaddrs = listen_address_to_socket_addrs(&listen_address)?; if sockaddrs.is_empty() { - return Err(format!("No valid listen address: {}", listen_address)); + bail!("No valid listen address: {}", listen_address); } let port = sockaddrs[0].port(); - if self.bind_first_tcp_port(port) { - Ok((port, sockaddrs.iter().map(|s| s.ip()).collect())) - } else { - Err("Could not find free tcp port to listen on".to_owned()) + if !self.bind_first_tcp_port(port) { + bail!("Could not find free tcp port to listen on"); } + Ok((port, sockaddrs.iter().map(|s| s.ip()).collect())) } } ///////////////////////////////////////////////////// - pub(super) async fn start_udp_listeners(&self) -> Result<(), String> { + pub(super) async fn start_udp_listeners(&self) -> EyreResult<()> { trace!("starting udp listeners"); let routing_table = self.routing_table(); let (listen_address, public_address, enable_local_peer_scope) = { @@ -319,7 +311,7 @@ impl Network { // Resolve statically configured public dialinfo let mut public_sockaddrs = public_address .to_socket_addrs() - .map_err(|e| format!("Unable to resolve address: {}\n{}", public_address, e))?; + .wrap_err(format!("Unable to resolve address: {}", public_address))?; // Add all resolved addresses as public dialinfo for pdi_addr in &mut public_sockaddrs { @@ -364,7 +356,7 @@ impl Network { self.create_udp_listener_tasks().await } - pub(super) async fn start_ws_listeners(&self) -> Result<(), String> { + pub(super) async fn start_ws_listeners(&self) -> EyreResult<()> { trace!("starting ws listeners"); let routing_table = self.routing_table(); let (listen_address, url, path, enable_local_peer_scope) = { @@ -405,9 +397,9 @@ impl Network { // Add static public dialinfo if it's configured if let Some(url) = url.as_ref() { - let mut split_url = SplitUrl::from_str(url)?; + let mut split_url = SplitUrl::from_str(url).wrap_err("couldn't split url")?; if split_url.scheme.to_ascii_lowercase() != "ws" { - return Err("WS URL must use 'ws://' scheme".to_owned()); + bail!("WS URL must use 'ws://' scheme"); } split_url.scheme = "ws".to_owned(); @@ -415,13 +407,11 @@ impl Network { let global_socket_addrs = split_url .host_port(80) .to_socket_addrs() - .map_err(map_to_string) - .map_err(logthru_net!(error))?; + .wrap_err("failed to resolve ws url")?; for gsa in global_socket_addrs { let pdi = DialInfo::try_ws(SocketAddress::from_socket_addr(gsa), url.clone()) - .map_err(map_to_string) - .map_err(logthru_net!(error))?; + .wrap_err("try_ws failed")?; routing_table.register_dial_info( RoutingDomain::PublicInternet, @@ -458,9 +448,7 @@ impl Network { } // Build dial info request url let local_url = format!("ws://{}/{}", socket_address, path); - let local_di = DialInfo::try_ws(socket_address, local_url) - .map_err(map_to_string) - .map_err(logthru_net!(error))?; + let local_di = DialInfo::try_ws(socket_address, local_url).wrap_err("try_ws failed")?; if url.is_none() && (socket_address.address().is_global() || enable_local_peer_scope) { // Register public dial info @@ -490,7 +478,7 @@ impl Network { Ok(()) } - pub(super) async fn start_wss_listeners(&self) -> Result<(), String> { + pub(super) async fn start_wss_listeners(&self) -> EyreResult<()> { trace!("starting wss listeners"); let routing_table = self.routing_table(); @@ -538,7 +526,7 @@ impl Network { // Add static public dialinfo if it's configured let mut split_url = SplitUrl::from_str(url)?; if split_url.scheme.to_ascii_lowercase() != "wss" { - return Err("WSS URL must use 'wss://' scheme".to_owned()); + bail!("WSS URL must use 'wss://' scheme"); } split_url.scheme = "wss".to_owned(); @@ -546,13 +534,10 @@ impl Network { let global_socket_addrs = split_url .host_port(443) .to_socket_addrs() - .map_err(map_to_string) - .map_err(logthru_net!(error))?; - + .wrap_err("failed to resolve wss url")?; for gsa in global_socket_addrs { let pdi = DialInfo::try_wss(SocketAddress::from_socket_addr(gsa), url.clone()) - .map_err(map_to_string) - .map_err(logthru_net!(error))?; + .wrap_err("try_wss failed")?; routing_table.register_dial_info( RoutingDomain::PublicInternet, @@ -581,7 +566,7 @@ impl Network { registered_addresses.insert(gsa.ip()); } } else { - return Err("WSS URL must be specified due to TLS requirements".to_owned()); + bail!("WSS URL must be specified due to TLS requirements"); } if static_public { @@ -594,7 +579,7 @@ impl Network { Ok(()) } - pub(super) async fn start_tcp_listeners(&self) -> Result<(), String> { + pub(super) async fn start_tcp_listeners(&self) -> EyreResult<()> { trace!("starting tcp listeners"); let routing_table = self.routing_table(); @@ -659,7 +644,7 @@ impl Network { // Resolve statically configured public dialinfo let mut public_sockaddrs = public_address .to_socket_addrs() - .map_err(|e| format!("Unable to resolve address: {}\n{}", public_address, e))?; + .wrap_err("failed to resolve tcp address")?; // Add all resolved addresses as public dialinfo for pdi_addr in &mut public_sockaddrs { diff --git a/veilid-core/src/network_manager/network_connection.rs b/veilid-core/src/network_manager/network_connection.rs index 61af8c86..c83c3de3 100644 --- a/veilid-core/src/network_manager/network_connection.rs +++ b/veilid-core/src/network_manager/network_connection.rs @@ -1,5 +1,6 @@ use super::*; use futures_util::{FutureExt, StreamExt}; +use std::io; use stop_token::prelude::*; cfg_if::cfg_if! { @@ -15,7 +16,7 @@ cfg_if::cfg_if! { &self, stream: AsyncPeekStream, peer_addr: SocketAddr, - ) -> SystemPinBoxFuture, String>>; + ) -> SystemPinBoxFuture>>; } pub trait ProtocolAcceptHandlerClone { @@ -52,13 +53,13 @@ impl DummyNetworkConnection { pub fn descriptor(&self) -> ConnectionDescriptor { self.descriptor.clone() } - pub fn close(&self) -> Result<(), String> { + // pub fn close(&self) -> Result<(), String> { + // Ok(()) + // } + pub fn send(&self, _message: Vec) -> io::Result<()> { Ok(()) } - pub fn send(&self, _message: Vec) -> Result<(), String> { - Ok(()) - } - pub fn recv(&self) -> Result, String> { + pub fn recv(&self) -> io::Result> { Ok(Vec::new()) } } @@ -178,7 +179,7 @@ impl NetworkConnection { protocol_connection: &ProtocolNetworkConnection, stats: Arc>, message: Vec, - ) -> Result<(), String> { + ) -> io::Result<()> { let ts = intf::get_timestamp(); let out = protocol_connection.send(message).await; if out.is_ok() { @@ -190,7 +191,7 @@ impl NetworkConnection { async fn recv_internal( protocol_connection: &ProtocolNetworkConnection, stats: Arc>, - ) -> Result, String> { + ) -> io::Result> { let ts = intf::get_timestamp(); let out = protocol_connection.recv().await; if out.is_ok() { @@ -222,7 +223,7 @@ impl NetworkConnection { ) -> SystemPinBoxFuture<()> { Box::pin(async move { log_net!( - "Starting process_connection loop for {:?}", + "== Starting process_connection loop for {:?}", descriptor.green() ); @@ -236,7 +237,7 @@ impl NetworkConnection { let new_timer = || { intf::sleep(connection_inactivity_timeout_ms).then(|_| async { // timeout - log_net!("connection timeout on {:?}", descriptor.green()); + log_net!("== Connection timeout on {:?}", descriptor.green()); RecvLoopAction::Timeout }) }; @@ -288,7 +289,7 @@ impl NetworkConnection { .on_recv_envelope(message.as_slice(), descriptor) .await { - log_net!(error e); + log_net!(debug "failed to process received envelope: {}", e); RecvLoopAction::Finish } else { RecvLoopAction::Recv @@ -296,7 +297,7 @@ impl NetworkConnection { } Err(e) => { // Connection unable to receive, closed - log_net!(warn e); + log_net!(debug e); RecvLoopAction::Finish } } diff --git a/veilid-core/src/network_manager/wasm/mod.rs b/veilid-core/src/network_manager/wasm/mod.rs index 96f1fcd7..4157d168 100644 --- a/veilid-core/src/network_manager/wasm/mod.rs +++ b/veilid-core/src/network_manager/wasm/mod.rs @@ -56,7 +56,7 @@ impl Network { &self, dial_info: DialInfo, data: Vec, - ) -> Result<(), String> { + ) -> EyreResult<()> { let data_len = data.len(); let res = match dial_info.protocol_type() { @@ -90,7 +90,7 @@ impl Network { dial_info: DialInfo, data: Vec, timeout_ms: u32, - ) -> Result, String> { + ) -> EyreResult> { let data_len = data.len(); let out = match dial_info.protocol_type() { ProtocolType::UDP => { @@ -124,7 +124,7 @@ impl Network { &self, descriptor: ConnectionDescriptor, data: Vec, - ) -> Result>, String> { + ) -> EyreResult>> { let data_len = data.len(); match descriptor.protocol_type() { ProtocolType::UDP => { @@ -161,7 +161,7 @@ impl Network { &self, dial_info: DialInfo, data: Vec, - ) -> Result<(), String> { + ) -> 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)) @@ -187,7 +187,7 @@ impl Network { ///////////////////////////////////////////////////////////////// - pub async fn startup(&self) -> Result<(), String> { + pub async fn startup(&self) -> EyreResult<()> { // get protocol config self.inner.lock().protocol_config = Some({ let c = self.config.get(); @@ -269,7 +269,7 @@ impl Network { } ////////////////////////////////////////// - pub async fn tick(&self) -> Result<(), String> { + pub async fn tick(&self) -> EyreResult<()> { Ok(()) } } diff --git a/veilid-core/src/network_manager/wasm/protocol/mod.rs b/veilid-core/src/network_manager/wasm/protocol/mod.rs index 7938e247..778870ed 100644 --- a/veilid-core/src/network_manager/wasm/protocol/mod.rs +++ b/veilid-core/src/network_manager/wasm/protocol/mod.rs @@ -15,7 +15,7 @@ impl ProtocolNetworkConnection { pub async fn connect( local_address: Option, dial_info: DialInfo, - ) -> Result { + ) -> io::Result { match dial_info.protocol_type() { ProtocolType::UDP => { panic!("UDP dial info is not supported on WASM targets"); @@ -32,7 +32,7 @@ impl ProtocolNetworkConnection { pub async fn send_unbound_message( dial_info: DialInfo, data: Vec, - ) -> Result<(), String> { + ) -> io::Result<()> { match dial_info.protocol_type() { ProtocolType::UDP => { panic!("UDP dial info is not supported on WASM targets"); @@ -50,7 +50,7 @@ impl ProtocolNetworkConnection { dial_info: DialInfo, data: Vec, timeout_ms: u32, - ) -> Result, String> { + ) -> io::Result> { match dial_info.protocol_type() { ProtocolType::UDP => { panic!("UDP dial info is not supported on WASM targets"); @@ -72,20 +72,20 @@ impl ProtocolNetworkConnection { } } - pub async fn close(&self) -> Result<(), String> { - match self { - Self::Dummy(d) => d.close(), - Self::Ws(w) => w.close().await, - } - } - pub async fn send(&self, message: Vec) -> Result<(), String> { + // pub async fn close(&self) -> io::Result<()> { + // match self { + // Self::Dummy(d) => d.close(), + // Self::Ws(w) => w.close().await, + // } + // } + pub async fn send(&self, message: Vec) -> io::Result<()> { match self { Self::Dummy(d) => d.send(message), Self::Ws(w) => w.send(message).await, } } - pub async fn recv(&self) -> Result, String> { + pub async fn recv(&self) -> io::Result> { match self { Self::Dummy(d) => d.recv(), Self::Ws(w) => w.recv().await, diff --git a/veilid-core/src/network_manager/wasm/protocol/ws.rs b/veilid-core/src/network_manager/wasm/protocol/ws.rs index 88d156f0..7ff4b42e 100644 --- a/veilid-core/src/network_manager/wasm/protocol/ws.rs +++ b/veilid-core/src/network_manager/wasm/protocol/ws.rs @@ -1,12 +1,19 @@ use super::*; use ws_stream_wasm::*; use futures_util::{StreamExt, SinkExt}; +use std::io; struct WebsocketNetworkConnectionInner { ws_meta: WsMeta, ws_stream: CloneStream, } +fn to_io(err: WsErr) -> io::Error { + let kind = match err { + WsErr::InvalidWsState {supplied:_} => io::ErrorKind:: + } +} + #[derive(Clone)] pub struct WebsocketNetworkConnection { descriptor: ConnectionDescriptor, @@ -36,15 +43,15 @@ impl WebsocketNetworkConnection { self.descriptor.clone() } - #[instrument(level = "trace", err, skip(self))] - pub async fn close(&self) -> Result<(), String> { - self.inner.ws_meta.close().await.map_err(map_to_string).map(drop) - } + // #[instrument(level = "trace", err, skip(self))] + // pub async fn close(&self) -> Result<(), String> { + // self.inner.ws_meta.close().await.map_err(map_to_string).map(drop) + // } #[instrument(level = "trace", err, skip(self, message), fields(message.len = message.len()))] - pub async fn send(&self, message: Vec) -> Result<(), String> { + pub async fn send(&self, message: Vec) -> io::Result<()> { if message.len() > MAX_MESSAGE_SIZE { - return Err("sending too large WS message".to_owned()).map_err(logthru_net!(error)); + bail_io_error_other!("sending too large WS message"); } self.inner.ws_stream.clone() .send(WsMessage::Binary(message)).await diff --git a/veilid-core/src/receipt_manager.rs b/veilid-core/src/receipt_manager.rs index d1c0b343..f7ad684f 100644 --- a/veilid-core/src/receipt_manager.rs +++ b/veilid-core/src/receipt_manager.rs @@ -201,7 +201,7 @@ impl ReceiptManager { self.inner.lock().network_manager.clone() } - pub async fn startup(&self) -> Result<(), String> { + pub async fn startup(&self) -> EyreResult<()> { trace!("startup receipt manager"); // Retrieve config @@ -288,7 +288,7 @@ impl ReceiptManager { } } - pub async fn tick(&self) -> Result<(), String> { + pub async fn tick(&self) -> EyreResult<()> { let (next_oldest_ts, timeout_task, stop_token) = { let inner = self.inner.lock(); let stop_token = match inner.stop_source.as_ref() { @@ -390,7 +390,7 @@ impl ReceiptManager { inner.next_oldest_ts = new_next_oldest_ts; } - pub async fn cancel_receipt(&self, nonce: &ReceiptNonce) -> Result<(), String> { + pub async fn cancel_receipt(&self, nonce: &ReceiptNonce) -> EyreResult<()> { log_rpc!(debug "== Cancel Receipt {}", nonce.encode()); // Remove the record @@ -399,7 +399,7 @@ impl ReceiptManager { let record = match inner.records_by_nonce.remove(nonce) { Some(r) => r, None => { - return Err("receipt not recorded".to_owned()); + bail!("receipt not recorded"); } }; Self::update_next_oldest_timestamp(&mut *inner); @@ -424,7 +424,7 @@ impl ReceiptManager { &self, receipt: Receipt, inbound_noderef: Option, - ) -> Result<(), String> { + ) -> EyreResult<()> { let receipt_nonce = receipt.get_nonce(); let extra_data = receipt.get_extra_data(); @@ -456,7 +456,7 @@ impl ReceiptManager { let record = match inner.records_by_nonce.get(&receipt_nonce) { Some(r) => r.clone(), None => { - return Err("receipt not recorded".to_owned()); + bail!("receipt not recorded"); } }; // Generate the callback future diff --git a/veilid-core/src/routing_table/mod.rs b/veilid-core/src/routing_table/mod.rs index ea3a9d83..8e25add2 100644 --- a/veilid-core/src/routing_table/mod.rs +++ b/veilid-core/src/routing_table/mod.rs @@ -69,12 +69,12 @@ pub struct RoutingTableHealth { struct RoutingTableUnlockedInner { // Background processes - rolling_transfers_task: TickTask, - bootstrap_task: TickTask, - peer_minimum_refresh_task: TickTask, - ping_validator_task: TickTask, + rolling_transfers_task: TickTask, + bootstrap_task: TickTask, + peer_minimum_refresh_task: TickTask, + ping_validator_task: TickTask, node_info_update_single_future: MustJoinSingleFuture<()>, - kick_buckets_task: TickTask, + kick_buckets_task: TickTask, } #[derive(Clone)] @@ -283,7 +283,7 @@ impl RoutingTable { domain: RoutingDomain, dial_info: DialInfo, class: DialInfoClass, - ) -> Result<(), String> { + ) -> EyreResult<()> { log_rtab!(debug "Registering dial_info with:\n domain: {:?}\n dial_info: {:?}\n class: {:?}", domain, dial_info, class @@ -298,15 +298,13 @@ impl RoutingTable { && matches!(domain, RoutingDomain::PublicInternet) && dial_info.is_local() { - return Err("shouldn't be registering local addresses as public".to_owned()) - .map_err(logthru_rtab!(error)); + bail!("shouldn't be registering local addresses as public"); } if !dial_info.is_valid() { - return Err(format!( + bail!( "shouldn't be registering invalid addresses: {:?}", dial_info - )) - .map_err(logthru_rtab!(error)); + ); } let mut inner = self.inner.write(); @@ -379,7 +377,7 @@ impl RoutingTable { } } - pub async fn init(&self) -> Result<(), String> { + pub async fn init(&self) -> EyreResult<()> { let mut inner = self.inner.write(); // Size the buckets (one per bit) inner.buckets.reserve(DHT_KEY_LENGTH * 8); @@ -578,13 +576,13 @@ impl RoutingTable { // Create a node reference, possibly creating a bucket entry // the 'update_func' closure is called on the node, and, if created, // in a locked fashion as to ensure the bucket entry state is always valid - pub fn create_node_ref(&self, node_id: DHTKey, update_func: F) -> Result + pub fn create_node_ref(&self, node_id: DHTKey, update_func: F) -> EyreResult where F: FnOnce(&mut BucketEntryInner), { // Ensure someone isn't trying register this node itself if node_id == self.node_id() { - return Err("can't register own node".to_owned()).map_err(logthru_rtab!(error)); + bail!("can't register own node"); } // Lock this entire operation @@ -647,14 +645,14 @@ impl RoutingTable { &self, node_id: DHTKey, signed_node_info: SignedNodeInfo, - ) -> Result { + ) -> EyreResult { // validate signed node info is not something malicious if node_id == self.node_id() { - return Err("can't register own node id in routing table".to_owned()); + bail!("can't register own node id in routing table"); } if let Some(rpi) = &signed_node_info.node_info.relay_peer_info { if rpi.node_id.key == node_id { - return Err("node can not be its own relay".to_owned()); + bail!("node can not be its own relay"); } } @@ -672,7 +670,7 @@ impl RoutingTable { node_id: DHTKey, descriptor: ConnectionDescriptor, timestamp: u64, - ) -> Result { + ) -> EyreResult { let nr = self.create_node_ref(node_id, |e| { // set the most recent node address for connection finding and udp replies e.set_last_connection(descriptor, timestamp); @@ -681,53 +679,9 @@ impl RoutingTable { Ok(nr) } - // fn operate_on_bucket_entry_inner_locked( - // inner: &RoutingTableInner, - // node_id: DHTKey, - // f: F, - // ) -> T - // where - // F: FnOnce(&BucketEntryInner) -> T, - // { - // let idx = Self::find_bucket_index(&*inner, node_id); - // let bucket = &inner.buckets[idx]; - // let entry = bucket.entry(&node_id).unwrap(); - // entry.with(f) - // } - - // fn operate_on_bucket_entry_inner_locked_mut( - // inner: &RoutingTableInner, - // node_id: DHTKey, - // f: F, - // ) -> T - // where - // F: FnOnce(&mut BucketEntryInner) -> T, - // { - // let idx = Self::find_bucket_index(&*inner, node_id); - // let bucket = &inner.buckets[idx]; - // let entry = bucket.entry(&node_id).unwrap(); - // entry.with_mut(f) - // } - - // fn operate_on_bucket_entry(&self, node_id: DHTKey, f: F) -> T - // where - // F: FnOnce(&BucketEntryInner) -> T, - // { - // let inner = self.inner.read(); - // Self::operate_on_bucket_entry_inner_locked(&mut *inner, node_id, f) - // } - - // fn operate_on_bucket_entry_mut(&self, node_id: DHTKey, f: F) -> T - // where - // F: FnOnce(&mut BucketEntryInner) -> T, - // { - // let inner = self.inner.read(); - // Self::operate_on_bucket_entry_inner_locked_mut(&*inner, node_id, f) - // } - // Ticks about once per second // to run tick tasks which may run at slower tick rates as configured - pub async fn tick(&self) -> Result<(), String> { + pub async fn tick(&self) -> EyreResult<()> { // Do rolling transfers every ROLLING_TRANSFERS_INTERVAL_SECS secs self.unlocked_inner.rolling_transfers_task.tick().await?; diff --git a/veilid-core/src/routing_table/tasks.rs b/veilid-core/src/routing_table/tasks.rs index 1671498b..4c17f08b 100644 --- a/veilid-core/src/routing_table/tasks.rs +++ b/veilid-core/src/routing_table/tasks.rs @@ -13,7 +13,7 @@ impl RoutingTable { _stop_token: StopToken, last_ts: u64, cur_ts: u64, - ) -> Result<(), String> { + ) -> EyreResult<()> { // log_rtab!("--- rolling_transfers task"); let mut inner = self.inner.write(); let inner = &mut *inner; @@ -37,7 +37,7 @@ impl RoutingTable { pub(super) async fn resolve_bootstrap( &self, bootstrap: Vec, - ) -> Result { + ) -> EyreResult { // Resolve from bootstrap root to bootstrap hostnames let mut bsnames = Vec::::new(); for bh in bootstrap { @@ -202,7 +202,7 @@ impl RoutingTable { self, stop_token: StopToken, bootstrap_dialinfos: Vec, - ) -> Result<(), String> { + ) -> EyreResult<()> { let network_manager = self.network_manager(); let mut unord = FuturesUnordered::new(); @@ -219,9 +219,7 @@ impl RoutingTable { for pi in peer_info { let k = pi.node_id.key; // Register the node - let nr = self - .register_node_with_signed_node_info(k, pi.signed_node_info) - .map_err(logthru_rtab!(error "Couldn't add bootstrap node: {}", k))?; + let nr = self.register_node_with_signed_node_info(k, pi.signed_node_info)?; // Add this our futures to process in parallel unord.push( @@ -238,7 +236,7 @@ impl RoutingTable { } #[instrument(level = "trace", skip(self), err)] - pub(super) async fn bootstrap_task_routine(self, stop_token: StopToken) -> Result<(), String> { + pub(super) async fn bootstrap_task_routine(self, stop_token: StopToken) -> EyreResult<()> { let (bootstrap, bootstrap_nodes) = { let c = self.config.get(); ( @@ -272,11 +270,7 @@ impl RoutingTable { let mut bootstrap_node_dial_infos = Vec::new(); for b in bootstrap_nodes { let ndis = NodeDialInfo::from_str(b.as_str()) - .map_err(map_to_string) - .map_err(logthru_rtab!( - "Invalid node dial info in bootstrap entry: {}", - b - ))?; + .wrap_err("Invalid node dial info in bootstrap entry")?; bootstrap_node_dial_infos.push(ndis); } for ndi in bootstrap_node_dial_infos { @@ -311,19 +305,17 @@ impl RoutingTable { log_rtab!("--- bootstrapping {} with {:?}", k.encode(), &v); // Make invalid signed node info (no signature) - let nr = self - .register_node_with_signed_node_info( - k, - SignedNodeInfo::with_no_signature(NodeInfo { - network_class: NetworkClass::InboundCapable, // Bootstraps are always inbound capable - outbound_protocols: ProtocolSet::empty(), // Bootstraps do not participate in relaying and will not make outbound requests - min_version: v.min_version, // Minimum protocol version specified in txt record - max_version: v.max_version, // Maximum protocol version specified in txt record - dial_info_detail_list: v.dial_info_details, // Dial info is as specified in the bootstrap list - relay_peer_info: None, // Bootstraps never require a relay themselves - }), - ) - .map_err(logthru_rtab!(error "Couldn't add bootstrap node: {}", k))?; + let nr = self.register_node_with_signed_node_info( + k, + SignedNodeInfo::with_no_signature(NodeInfo { + network_class: NetworkClass::InboundCapable, // Bootstraps are always inbound capable + outbound_protocols: ProtocolSet::empty(), // Bootstraps do not participate in relaying and will not make outbound requests + min_version: v.min_version, // Minimum protocol version specified in txt record + max_version: v.max_version, // Maximum protocol version specified in txt record + dial_info_detail_list: v.dial_info_details, // Dial info is as specified in the bootstrap list + relay_peer_info: None, // Bootstraps never require a relay themselves + }), + )?; // Add this our futures to process in parallel let this = self.clone(); @@ -359,7 +351,7 @@ impl RoutingTable { stop_token: StopToken, _last_ts: u64, cur_ts: u64, - ) -> Result<(), String> { + ) -> EyreResult<()> { let rpc = self.rpc_processor(); let netman = self.network_manager(); let relay_node_id = netman.relay_node().map(|nr| nr.node_id()); @@ -389,7 +381,7 @@ impl RoutingTable { pub(super) async fn peer_minimum_refresh_task_routine( self, stop_token: StopToken, - ) -> Result<(), String> { + ) -> EyreResult<()> { // get list of all peers we know about, even the unreliable ones, and ask them to find nodes close to our node too let noderefs = { let inner = self.inner.read(); @@ -421,7 +413,7 @@ impl RoutingTable { _stop_token: StopToken, _last_ts: u64, cur_ts: u64, - ) -> Result<(), String> { + ) -> EyreResult<()> { let mut inner = self.inner.write(); let kick_queue: Vec = inner.kick_queue.iter().map(|v| *v).collect(); inner.kick_queue.clear(); diff --git a/veilid-core/src/rpc_processor/coders/address.rs b/veilid-core/src/rpc_processor/coders/address.rs index 7dfac2e8..ff3aabea 100644 --- a/veilid-core/src/rpc_processor/coders/address.rs +++ b/veilid-core/src/rpc_processor/coders/address.rs @@ -55,6 +55,12 @@ pub fn decode_address(reader: &veilid_capnp::address::Reader) -> Result Err(rpc_error_protocol("invalid address type")), + Ok(veilid_capnp::address::Which::Ipv4(Err(_))) => { + Err(RPCError::protocol("invalid ipv4 address")) + } + Ok(veilid_capnp::address::Which::Ipv6(Err(_))) => { + Err(RPCError::protocol("invalid ipv6 address")) + } + Err(_) => Err(RPCError::protocol("invalid address type")), } } diff --git a/veilid-core/src/rpc_processor/coders/block_id.rs b/veilid-core/src/rpc_processor/coders/block_id.rs index 5da590db..d071197f 100644 --- a/veilid-core/src/rpc_processor/coders/block_id.rs +++ b/veilid-core/src/rpc_processor/coders/block_id.rs @@ -23,27 +23,19 @@ pub fn encode_block_id( builder: &mut veilid_capnp::b_l_a_k_e3_hash::Builder, ) -> Result<(), RPCError> { if !key.valid { - return Err(rpc_error_protocol("invalid key")); + return Err(RPCError::protocol("invalid key")); } builder.set_u0(u64::from_be_bytes( - key.bytes[0..8] - .try_into() - .map_err(map_error_protocol!("slice with incorrect length"))?, + key.bytes[0..8].try_into().map_err(RPCError::internal)?, )); builder.set_u1(u64::from_be_bytes( - key.bytes[8..16] - .try_into() - .map_err(map_error_protocol!("slice with incorrect length"))?, + key.bytes[8..16].try_into().map_err(RPCError::internal)?, )); builder.set_u2(u64::from_be_bytes( - key.bytes[16..24] - .try_into() - .map_err(map_error_protocol!("slice with incorrect length"))?, + key.bytes[16..24].try_into().map_err(RPCError::internal)?, )); builder.set_u3(u64::from_be_bytes( - key.bytes[24..32] - .try_into() - .map_err(map_error_protocol!("slice with incorrect length"))?, + key.bytes[24..32].try_into().map_err(RPCError::internal)?, )); Ok(()) } diff --git a/veilid-core/src/rpc_processor/coders/dial_info.rs b/veilid-core/src/rpc_processor/coders/dial_info.rs index 48bf5df8..c178bb0c 100644 --- a/veilid-core/src/rpc_processor/coders/dial_info.rs +++ b/veilid-core/src/rpc_processor/coders/dial_info.rs @@ -4,44 +4,51 @@ use core::convert::TryInto; use rpc_processor::*; pub fn decode_dial_info(reader: &veilid_capnp::dial_info::Reader) -> Result { - match reader.reborrow().which() { - Ok(veilid_capnp::dial_info::Which::Udp(Ok(udp))) => { + match reader + .reborrow() + .which() + .map_err(RPCError::map_protocol("Missing dial info type"))? + { + veilid_capnp::dial_info::Which::Udp(udp) => { let socket_address_reader = udp + .map_err(RPCError::protocol)? .get_socket_address() - .map_err(map_error_protocol!("missing UDP socketAddress"))?; + .map_err(RPCError::map_protocol("missing UDP socketAddress"))?; let socket_address = decode_socket_address(&socket_address_reader)?; Ok(DialInfo::udp(socket_address)) } - Ok(veilid_capnp::dial_info::Which::Tcp(Ok(tcp))) => { + veilid_capnp::dial_info::Which::Tcp(tcp) => { let socket_address_reader = tcp + .map_err(RPCError::protocol)? .get_socket_address() - .map_err(map_error_protocol!("missing TCP socketAddress"))?; + .map_err(RPCError::map_protocol("missing TCP socketAddress"))?; let socket_address = decode_socket_address(&socket_address_reader)?; Ok(DialInfo::tcp(socket_address)) } - Ok(veilid_capnp::dial_info::Which::Ws(Ok(ws))) => { + veilid_capnp::dial_info::Which::Ws(ws) => { + let ws = ws.map_err(RPCError::protocol)?; let socket_address_reader = ws .get_socket_address() - .map_err(map_error_protocol!("missing WS socketAddress"))?; + .map_err(RPCError::map_protocol("missing WS socketAddress"))?; let socket_address = decode_socket_address(&socket_address_reader)?; let request = ws .get_request() - .map_err(map_error_protocol!("missing WS request"))?; + .map_err(RPCError::map_protocol("missing WS request"))?; DialInfo::try_ws(socket_address, request.to_owned()) - .map_err(map_error_protocol!("invalid WS dial info")) + .map_err(RPCError::map_protocol("invalid WS dial info")) } - Ok(veilid_capnp::dial_info::Which::Wss(Ok(wss))) => { + veilid_capnp::dial_info::Which::Wss(wss) => { + let wss = wss.map_err(RPCError::protocol)?; let socket_address_reader = wss .get_socket_address() - .map_err(map_error_protocol!("missing WSS socketAddress"))?; + .map_err(RPCError::map_protocol("missing WSS socketAddress"))?; let socket_address = decode_socket_address(&socket_address_reader)?; let request = wss .get_request() - .map_err(map_error_protocol!("missing WSS request"))?; + .map_err(RPCError::map_protocol("missing WSS request"))?; DialInfo::try_wss(socket_address, request.to_owned()) - .map_err(map_error_protocol!("invalid WSS dial info")) + .map_err(RPCError::map_protocol("invalid WSS dial info")) } - _ => Err(rpc_error_internal("invalid dial info type")), } } @@ -72,13 +79,13 @@ pub fn encode_dial_info( )?; let request = dial_info .request() - .ok_or_else(|| rpc_error_internal("no request for WS dialinfo"))?; + .ok_or_else(RPCError::else_internal("no request for WS dialinfo"))?; let mut requestb = di_ws_builder.init_request( request .len() .try_into() - .map_err(map_error_protocol!("request too long"))?, + .map_err(RPCError::map_protocol("request too long"))?, ); requestb.push_str(request.as_str()); } @@ -90,13 +97,13 @@ pub fn encode_dial_info( )?; let request = dial_info .request() - .ok_or_else(|| rpc_error_internal("no request for WSS dialinfo"))?; + .ok_or_else(RPCError::else_internal("no request for WSS dialinfo"))?; let mut requestb = di_wss_builder.init_request( request .len() .try_into() - .map_err(map_error_protocol!("request too long"))?, + .map_err(RPCError::map_protocol("request too long"))?, ); requestb.push_str(request.as_str()); } diff --git a/veilid-core/src/rpc_processor/coders/dial_info_detail.rs b/veilid-core/src/rpc_processor/coders/dial_info_detail.rs index 3a237c18..c3dc1b27 100644 --- a/veilid-core/src/rpc_processor/coders/dial_info_detail.rs +++ b/veilid-core/src/rpc_processor/coders/dial_info_detail.rs @@ -19,15 +19,10 @@ pub fn decode_dial_info_detail( &reader .reborrow() .get_dial_info() - .map_err(map_error_capnp_error!())?, + .map_err(RPCError::protocol)?, )?; - let class = decode_dial_info_class( - reader - .reborrow() - .get_class() - .map_err(map_error_capnp_notinschema!())?, - ); + let class = decode_dial_info_class(reader.reborrow().get_class().map_err(RPCError::protocol)?); Ok(DialInfoDetail { dial_info, class }) } diff --git a/veilid-core/src/rpc_processor/coders/node_dial_info.rs b/veilid-core/src/rpc_processor/coders/node_dial_info.rs index 84030093..47ae96ad 100644 --- a/veilid-core/src/rpc_processor/coders/node_dial_info.rs +++ b/veilid-core/src/rpc_processor/coders/node_dial_info.rs @@ -15,16 +15,12 @@ pub fn encode_node_dial_info( pub fn decode_node_dial_info( reader: &veilid_capnp::node_dial_info::Reader, ) -> Result { - let node_id = decode_public_key( - &reader - .get_node_id() - .map_err(map_error_protocol!("invalid public key in node_dial_info"))?, - ); - let dial_info = decode_dial_info( - &reader - .get_dial_info() - .map_err(map_error_protocol!("invalid dial_info in node_dial_info"))?, - )?; + let node_id = decode_public_key(&reader.get_node_id().map_err(RPCError::map_protocol( + "invalid public key in node_dial_info", + ))?); + let dial_info = decode_dial_info(&reader.get_dial_info().map_err(RPCError::map_protocol( + "invalid dial_info in node_dial_info", + ))?)?; Ok(NodeDialInfo { node_id: NodeId::new(node_id), diff --git a/veilid-core/src/rpc_processor/coders/node_info.rs b/veilid-core/src/rpc_processor/coders/node_info.rs index f338f473..e6382fe2 100644 --- a/veilid-core/src/rpc_processor/coders/node_info.rs +++ b/veilid-core/src/rpc_processor/coders/node_info.rs @@ -18,8 +18,8 @@ pub fn encode_node_info( .dial_info_detail_list .len() .try_into() - .map_err(map_error_protocol!( - "too many dial info details in node info" + .map_err(RPCError::map_protocol( + "too many dial info details in node info", ))?, ); @@ -44,14 +44,14 @@ pub fn decode_node_info( reader .reborrow() .get_network_class() - .map_err(map_error_capnp_notinschema!())?, + .map_err(RPCError::protocol)?, ); let outbound_protocols = decode_protocol_set( &reader .reborrow() .get_outbound_protocols() - .map_err(map_error_capnp_error!())?, + .map_err(RPCError::protocol)?, )?; let min_version = reader.reborrow().get_min_version(); @@ -60,12 +60,12 @@ pub fn decode_node_info( let didl_reader = reader .reborrow() .get_dial_info_detail_list() - .map_err(map_error_capnp_error!())?; + .map_err(RPCError::protocol)?; let mut dial_info_detail_list = Vec::::with_capacity( didl_reader .len() .try_into() - .map_err(map_error_protocol!("too many dial info details"))?, + .map_err(RPCError::map_protocol("too many dial info details"))?, ); for did in didl_reader.iter() { dial_info_detail_list.push(decode_dial_info_detail(&did)?) @@ -77,7 +77,7 @@ pub fn decode_node_info( &reader .reborrow() .get_relay_peer_info() - .map_err(map_error_capnp_error!())?, + .map_err(RPCError::protocol)?, false, )?)) } else { diff --git a/veilid-core/src/rpc_processor/coders/operations/answer.rs b/veilid-core/src/rpc_processor/coders/operations/answer.rs index b13f3dda..906132f2 100644 --- a/veilid-core/src/rpc_processor/coders/operations/answer.rs +++ b/veilid-core/src/rpc_processor/coders/operations/answer.rs @@ -64,55 +64,55 @@ impl RPCAnswerDetail { pub fn decode( reader: &veilid_capnp::answer::detail::Reader, ) -> Result { - let which_reader = reader.which().map_err(map_error_capnp_notinschema!())?; + let which_reader = reader.which().map_err(RPCError::protocol)?; let out = match which_reader { veilid_capnp::answer::detail::StatusA(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationStatusA::decode(&op_reader)?; RPCAnswerDetail::StatusA(out) } veilid_capnp::answer::detail::FindNodeA(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationFindNodeA::decode(&op_reader)?; RPCAnswerDetail::FindNodeA(out) } veilid_capnp::answer::detail::GetValueA(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationGetValueA::decode(&op_reader)?; RPCAnswerDetail::GetValueA(out) } veilid_capnp::answer::detail::SetValueA(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationSetValueA::decode(&op_reader)?; RPCAnswerDetail::SetValueA(out) } veilid_capnp::answer::detail::WatchValueA(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationWatchValueA::decode(&op_reader)?; RPCAnswerDetail::WatchValueA(out) } veilid_capnp::answer::detail::SupplyBlockA(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationSupplyBlockA::decode(&op_reader)?; RPCAnswerDetail::SupplyBlockA(out) } veilid_capnp::answer::detail::FindBlockA(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationFindBlockA::decode(&op_reader)?; RPCAnswerDetail::FindBlockA(out) } veilid_capnp::answer::detail::StartTunnelA(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationStartTunnelA::decode(&op_reader)?; RPCAnswerDetail::StartTunnelA(out) } veilid_capnp::answer::detail::CompleteTunnelA(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationCompleteTunnelA::decode(&op_reader)?; RPCAnswerDetail::CompleteTunnelA(out) } veilid_capnp::answer::detail::CancelTunnelA(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationCancelTunnelA::decode(&op_reader)?; RPCAnswerDetail::CancelTunnelA(out) } diff --git a/veilid-core/src/rpc_processor/coders/operations/operation.rs b/veilid-core/src/rpc_processor/coders/operations/operation.rs index 6b813f77..c09ce08e 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation.rs @@ -21,22 +21,20 @@ impl RPCOperationKind { kind_reader: &veilid_capnp::operation::kind::Reader, sender_node_id: &DHTKey, ) -> Result { - let which_reader = kind_reader - .which() - .map_err(map_error_capnp_notinschema!())?; + let which_reader = kind_reader.which().map_err(RPCError::protocol)?; let out = match which_reader { veilid_capnp::operation::kind::Which::Question(r) => { - let q_reader = r.map_err(map_error_capnp_error!())?; + let q_reader = r.map_err(RPCError::protocol)?; let out = RPCQuestion::decode(&q_reader, sender_node_id)?; RPCOperationKind::Question(out) } veilid_capnp::operation::kind::Which::Statement(r) => { - let q_reader = r.map_err(map_error_capnp_error!())?; + let q_reader = r.map_err(RPCError::protocol)?; let out = RPCStatement::decode(&q_reader, sender_node_id)?; RPCOperationKind::Statement(out) } veilid_capnp::operation::kind::Which::Answer(r) => { - let q_reader = r.map_err(map_error_capnp_error!())?; + let q_reader = r.map_err(RPCError::protocol)?; let out = RPCAnswer::decode(&q_reader)?; RPCOperationKind::Answer(out) } diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_cancel_tunnel.rs b/veilid-core/src/rpc_processor/coders/operations/operation_cancel_tunnel.rs index 54741954..c9ca4e96 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_cancel_tunnel.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_cancel_tunnel.rs @@ -34,12 +34,12 @@ impl RPCOperationCancelTunnelA { pub fn decode( reader: &veilid_capnp::operation_cancel_tunnel_a::Reader, ) -> Result { - match reader.which().map_err(map_error_capnp_notinschema!())? { + match reader.which().map_err(RPCError::protocol)? { veilid_capnp::operation_cancel_tunnel_a::Which::Tunnel(r) => { Ok(RPCOperationCancelTunnelA::Tunnel(r)) } veilid_capnp::operation_cancel_tunnel_a::Which::Error(r) => { - let tunnel_error = decode_tunnel_error(r.map_err(map_error_capnp_notinschema!())?); + let tunnel_error = decode_tunnel_error(r.map_err(RPCError::protocol)?); Ok(RPCOperationCancelTunnelA::Error(tunnel_error)) } } diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_complete_tunnel.rs b/veilid-core/src/rpc_processor/coders/operations/operation_complete_tunnel.rs index 012f6f91..453c38c0 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_complete_tunnel.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_complete_tunnel.rs @@ -14,15 +14,12 @@ impl RPCOperationCompleteTunnelQ { reader: &veilid_capnp::operation_complete_tunnel_q::Reader, ) -> Result { let id = reader.get_id(); - let local_mode = match reader - .get_local_mode() - .map_err(map_error_capnp_notinschema!())? - { + let local_mode = match reader.get_local_mode().map_err(RPCError::protocol)? { veilid_capnp::TunnelEndpointMode::Raw => TunnelMode::Raw, veilid_capnp::TunnelEndpointMode::Turn => TunnelMode::Turn, }; let depth = reader.get_depth(); - let te_reader = reader.get_endpoint().map_err(map_error_capnp_error!())?; + let te_reader = reader.get_endpoint().map_err(RPCError::protocol)?; let endpoint = decode_tunnel_endpoint(&te_reader)?; Ok(RPCOperationCompleteTunnelQ { @@ -59,14 +56,14 @@ impl RPCOperationCompleteTunnelA { pub fn decode( reader: &veilid_capnp::operation_complete_tunnel_a::Reader, ) -> Result { - match reader.which().map_err(map_error_capnp_notinschema!())? { + match reader.which().map_err(RPCError::protocol)? { veilid_capnp::operation_complete_tunnel_a::Which::Tunnel(r) => { - let ft_reader = r.map_err(map_error_capnp_error!())?; + let ft_reader = r.map_err(RPCError::protocol)?; let full_tunnel = decode_full_tunnel(&ft_reader)?; Ok(RPCOperationCompleteTunnelA::Tunnel(full_tunnel)) } veilid_capnp::operation_complete_tunnel_a::Which::Error(r) => { - let tunnel_error = decode_tunnel_error(r.map_err(map_error_capnp_notinschema!())?); + let tunnel_error = decode_tunnel_error(r.map_err(RPCError::protocol)?); Ok(RPCOperationCompleteTunnelA::Error(tunnel_error)) } } diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_find_block.rs b/veilid-core/src/rpc_processor/coders/operations/operation_find_block.rs index 2bc0ea47..6e561635 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_find_block.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_find_block.rs @@ -10,7 +10,7 @@ impl RPCOperationFindBlockQ { pub fn decode( reader: &veilid_capnp::operation_find_block_q::Reader, ) -> Result { - let bi_reader = reader.get_block_id().map_err(map_error_capnp_error!())?; + let bi_reader = reader.get_block_id().map_err(RPCError::protocol)?; let block_id = decode_block_id(&bi_reader); Ok(RPCOperationFindBlockQ { block_id }) @@ -37,29 +37,26 @@ impl RPCOperationFindBlockA { pub fn decode( reader: &veilid_capnp::operation_find_block_a::Reader, ) -> Result { - let data = reader - .get_data() - .map_err(map_error_capnp_error!())? - .to_vec(); + let data = reader.get_data().map_err(RPCError::protocol)?.to_vec(); - let suppliers_reader = reader.get_suppliers().map_err(map_error_capnp_error!())?; + let suppliers_reader = reader.get_suppliers().map_err(RPCError::protocol)?; let mut suppliers = Vec::::with_capacity( suppliers_reader .len() .try_into() - .map_err(map_error_internal!("too many suppliers"))?, + .map_err(RPCError::map_internal("too many suppliers"))?, ); for s in suppliers_reader.iter() { let peer_info = decode_peer_info(&s, true)?; suppliers.push(peer_info); } - let peers_reader = reader.get_peers().map_err(map_error_capnp_error!())?; + let peers_reader = reader.get_peers().map_err(RPCError::protocol)?; let mut peers = Vec::::with_capacity( peers_reader .len() .try_into() - .map_err(map_error_internal!("too many peers"))?, + .map_err(RPCError::map_internal("too many peers"))?, ); for p in peers_reader.iter() { let peer_info = decode_peer_info(&p, true)?; @@ -83,7 +80,7 @@ impl RPCOperationFindBlockA { self.suppliers .len() .try_into() - .map_err(map_error_internal!("invalid suppliers list length"))?, + .map_err(RPCError::map_internal("invalid suppliers list length"))?, ); for (i, peer) in self.suppliers.iter().enumerate() { let mut pi_builder = suppliers_builder.reborrow().get(i as u32); @@ -94,7 +91,7 @@ impl RPCOperationFindBlockA { self.peers .len() .try_into() - .map_err(map_error_internal!("invalid peers list length"))?, + .map_err(RPCError::map_internal("invalid peers list length"))?, ); for (i, peer) in self.peers.iter().enumerate() { let mut pi_builder = peers_builder.reborrow().get(i as u32); diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_find_node.rs b/veilid-core/src/rpc_processor/coders/operations/operation_find_node.rs index 0116f984..852700a0 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_find_node.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_find_node.rs @@ -10,7 +10,7 @@ impl RPCOperationFindNodeQ { pub fn decode( reader: &veilid_capnp::operation_find_node_q::Reader, ) -> Result { - let ni_reader = reader.get_node_id().map_err(map_error_capnp_error!())?; + let ni_reader = reader.get_node_id().map_err(RPCError::protocol)?; let node_id = decode_public_key(&ni_reader); Ok(RPCOperationFindNodeQ { node_id }) } @@ -33,12 +33,12 @@ impl RPCOperationFindNodeA { pub fn decode( reader: &veilid_capnp::operation_find_node_a::Reader, ) -> Result { - let peers_reader = reader.get_peers().map_err(map_error_capnp_error!())?; + let peers_reader = reader.get_peers().map_err(RPCError::protocol)?; let mut peers = Vec::::with_capacity( peers_reader .len() .try_into() - .map_err(map_error_internal!("too many peers"))?, + .map_err(RPCError::map_internal("too many peers"))?, ); for p in peers_reader.iter() { let peer_info = decode_peer_info(&p, true)?; @@ -55,7 +55,7 @@ impl RPCOperationFindNodeA { self.peers .len() .try_into() - .map_err(map_error_internal!("invalid closest nodes list length"))?, + .map_err(RPCError::map_internal("invalid closest nodes list length"))?, ); for (i, peer) in self.peers.iter().enumerate() { let mut pi_builder = peers_builder.reborrow().get(i as u32); diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_get_value.rs b/veilid-core/src/rpc_processor/coders/operations/operation_get_value.rs index 11b14a17..9ac5f9f6 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_get_value.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_get_value.rs @@ -10,7 +10,7 @@ impl RPCOperationGetValueQ { pub fn decode( reader: &veilid_capnp::operation_get_value_q::Reader, ) -> Result { - let k_reader = reader.get_key().map_err(map_error_capnp_error!())?; + let k_reader = reader.get_key().map_err(RPCError::protocol)?; let key = decode_value_key(&k_reader)?; Ok(RPCOperationGetValueQ { key }) } @@ -34,18 +34,18 @@ impl RPCOperationGetValueA { pub fn decode( reader: &veilid_capnp::operation_get_value_a::Reader, ) -> Result { - match reader.which().map_err(map_error_capnp_notinschema!())? { + match reader.which().map_err(RPCError::protocol)? { veilid_capnp::operation_get_value_a::Which::Data(r) => { - let data = decode_value_data(&r.map_err(map_error_capnp_error!())?)?; + let data = decode_value_data(&r.map_err(RPCError::protocol)?)?; Ok(RPCOperationGetValueA::Data(data)) } veilid_capnp::operation_get_value_a::Which::Peers(r) => { - let peers_reader = r.map_err(map_error_capnp_error!())?; + let peers_reader = r.map_err(RPCError::protocol)?; let mut peers = Vec::::with_capacity( peers_reader .len() .try_into() - .map_err(map_error_internal!("too many peers"))?, + .map_err(RPCError::map_internal("too many peers"))?, ); for p in peers_reader.iter() { let peer_info = decode_peer_info(&p, true)?; @@ -70,7 +70,7 @@ impl RPCOperationGetValueA { peers .len() .try_into() - .map_err(map_error_internal!("invalid peers list length"))?, + .map_err(RPCError::map_internal("invalid peers list length"))?, ); for (i, peer) in peers.iter().enumerate() { let mut pi_builder = peers_builder.reborrow().get(i as u32); diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_node_info_update.rs b/veilid-core/src/rpc_processor/coders/operations/operation_node_info_update.rs index 121e8b78..00c5943a 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_node_info_update.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_node_info_update.rs @@ -11,9 +11,7 @@ impl RPCOperationNodeInfoUpdate { reader: &veilid_capnp::operation_node_info_update::Reader, sender_node_id: &DHTKey, ) -> Result { - let sni_reader = reader - .get_signed_node_info() - .map_err(map_error_capnp_error!())?; + let sni_reader = reader.get_signed_node_info().map_err(RPCError::protocol)?; let signed_node_info = decode_signed_node_info(&sni_reader, sender_node_id, true)?; Ok(RPCOperationNodeInfoUpdate { signed_node_info }) diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_return_receipt.rs b/veilid-core/src/rpc_processor/coders/operations/operation_return_receipt.rs index 70acb47a..31c1d213 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_return_receipt.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_return_receipt.rs @@ -10,7 +10,7 @@ impl RPCOperationReturnReceipt { pub fn decode( reader: &veilid_capnp::operation_return_receipt::Reader, ) -> Result { - let rcpt_reader = reader.get_receipt().map_err(map_error_capnp_error!())?; + let rcpt_reader = reader.get_receipt().map_err(RPCError::protocol)?; let receipt = rcpt_reader.to_vec(); Ok(RPCOperationReturnReceipt { receipt }) diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_route.rs b/veilid-core/src/rpc_processor/coders/operations/operation_route.rs index af18d29f..7ded216d 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_route.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_route.rs @@ -20,24 +20,21 @@ impl RoutedOperation { pub fn decode( reader: &veilid_capnp::routed_operation::Reader, ) -> Result { - let sigs_reader = reader.get_signatures().map_err(map_error_capnp_error!())?; + let sigs_reader = reader.get_signatures().map_err(RPCError::protocol)?; let mut signatures = Vec::::with_capacity( sigs_reader .len() .try_into() - .map_err(map_error_internal!("too many signatures"))?, + .map_err(RPCError::map_internal("too many signatures"))?, ); for s in sigs_reader.iter() { let sig = decode_signature(&s); signatures.push(sig); } - let n_reader = reader.get_nonce().map_err(map_error_capnp_error!())?; + let n_reader = reader.get_nonce().map_err(RPCError::protocol)?; let nonce = decode_nonce(&n_reader); - let data = reader - .get_data() - .map_err(map_error_capnp_error!())? - .to_vec(); + let data = reader.get_data().map_err(RPCError::protocol)?.to_vec(); Ok(RoutedOperation { signatures, @@ -54,7 +51,7 @@ impl RoutedOperation { self.signatures .len() .try_into() - .map_err(map_error_internal!("invalid signatures list length"))?, + .map_err(RPCError::map_internal("invalid signatures list length"))?, ); for (i, sig) in self.signatures.iter().enumerate() { let mut sig_builder = sigs_builder.reborrow().get(i as u32); @@ -78,12 +75,10 @@ impl RPCOperationRoute { pub fn decode( reader: &veilid_capnp::operation_route::Reader, ) -> Result { - let sr_reader = reader - .get_safety_route() - .map_err(map_error_capnp_error!())?; + let sr_reader = reader.get_safety_route().map_err(RPCError::protocol)?; let safety_route = decode_safety_route(&sr_reader)?; - let o_reader = reader.get_operation().map_err(map_error_capnp_error!())?; + let o_reader = reader.get_operation().map_err(RPCError::protocol)?; let operation = RoutedOperation::decode(&o_reader)?; Ok(RPCOperationRoute { diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_set_value.rs b/veilid-core/src/rpc_processor/coders/operations/operation_set_value.rs index 3ab35193..af5c5350 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_set_value.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_set_value.rs @@ -11,9 +11,9 @@ impl RPCOperationSetValueQ { pub fn decode( reader: &veilid_capnp::operation_set_value_q::Reader, ) -> Result { - let k_reader = reader.get_key().map_err(map_error_capnp_error!())?; + let k_reader = reader.get_key().map_err(RPCError::protocol)?; let key = decode_value_key(&k_reader)?; - let v_reader = reader.get_value().map_err(map_error_capnp_error!())?; + let v_reader = reader.get_value().map_err(RPCError::protocol)?; let value = decode_value_data(&v_reader)?; Ok(RPCOperationSetValueQ { key, value }) } @@ -39,18 +39,18 @@ impl RPCOperationSetValueA { pub fn decode( reader: &veilid_capnp::operation_set_value_a::Reader, ) -> Result { - match reader.which().map_err(map_error_capnp_notinschema!())? { + match reader.which().map_err(RPCError::protocol)? { veilid_capnp::operation_set_value_a::Which::Data(r) => { - let data = decode_value_data(&r.map_err(map_error_capnp_error!())?)?; + let data = decode_value_data(&r.map_err(RPCError::protocol)?)?; Ok(RPCOperationSetValueA::Data(data)) } veilid_capnp::operation_set_value_a::Which::Peers(r) => { - let peers_reader = r.map_err(map_error_capnp_error!())?; + let peers_reader = r.map_err(RPCError::protocol)?; let mut peers = Vec::::with_capacity( peers_reader .len() .try_into() - .map_err(map_error_internal!("too many peers"))?, + .map_err(RPCError::map_internal("too many peers"))?, ); for p in peers_reader.iter() { let peer_info = decode_peer_info(&p, true)?; @@ -75,7 +75,7 @@ impl RPCOperationSetValueA { peers .len() .try_into() - .map_err(map_error_internal!("invalid peers list length"))?, + .map_err(RPCError::map_internal("invalid peers list length"))?, ); for (i, peer) in peers.iter().enumerate() { let mut pi_builder = peers_builder.reborrow().get(i as u32); diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_start_tunnel.rs b/veilid-core/src/rpc_processor/coders/operations/operation_start_tunnel.rs index ccac6e82..08c1982b 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_start_tunnel.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_start_tunnel.rs @@ -13,10 +13,7 @@ impl RPCOperationStartTunnelQ { reader: &veilid_capnp::operation_start_tunnel_q::Reader, ) -> Result { let id = reader.get_id(); - let local_mode = match reader - .get_local_mode() - .map_err(map_error_capnp_notinschema!())? - { + let local_mode = match reader.get_local_mode().map_err(RPCError::protocol)? { veilid_capnp::TunnelEndpointMode::Raw => TunnelMode::Raw, veilid_capnp::TunnelEndpointMode::Turn => TunnelMode::Turn, }; @@ -53,14 +50,14 @@ impl RPCOperationStartTunnelA { pub fn decode( reader: &veilid_capnp::operation_start_tunnel_a::Reader, ) -> Result { - match reader.which().map_err(map_error_capnp_notinschema!())? { + match reader.which().map_err(RPCError::protocol)? { veilid_capnp::operation_start_tunnel_a::Which::Partial(r) => { - let pt_reader = r.map_err(map_error_capnp_error!())?; + let pt_reader = r.map_err(RPCError::protocol)?; let partial_tunnel = decode_partial_tunnel(&pt_reader)?; Ok(RPCOperationStartTunnelA::Partial(partial_tunnel)) } veilid_capnp::operation_start_tunnel_a::Which::Error(r) => { - let tunnel_error = decode_tunnel_error(r.map_err(map_error_capnp_notinschema!())?); + let tunnel_error = decode_tunnel_error(r.map_err(RPCError::protocol)?); Ok(RPCOperationStartTunnelA::Error(tunnel_error)) } } diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_status.rs b/veilid-core/src/rpc_processor/coders/operations/operation_status.rs index 0e07163c..7f4d3da7 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_status.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_status.rs @@ -10,7 +10,7 @@ impl RPCOperationStatusQ { pub fn decode( reader: &veilid_capnp::operation_status_q::Reader, ) -> Result { - let ns_reader = reader.get_node_status().map_err(map_error_capnp_error!())?; + let ns_reader = reader.get_node_status().map_err(RPCError::protocol)?; let node_status = decode_node_status(&ns_reader)?; Ok(RPCOperationStatusQ { node_status }) } @@ -34,10 +34,10 @@ impl RPCOperationStatusA { pub fn decode( reader: &veilid_capnp::operation_status_a::Reader, ) -> Result { - let ns_reader = reader.get_node_status().map_err(map_error_capnp_error!())?; + let ns_reader = reader.get_node_status().map_err(RPCError::protocol)?; let node_status = decode_node_status(&ns_reader)?; - let si_reader = reader.get_sender_info().map_err(map_error_capnp_error!())?; + let si_reader = reader.get_sender_info().map_err(RPCError::protocol)?; let sender_info = decode_sender_info(&si_reader)?; Ok(RPCOperationStatusA { diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_supply_block.rs b/veilid-core/src/rpc_processor/coders/operations/operation_supply_block.rs index 5d10a82f..0e496417 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_supply_block.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_supply_block.rs @@ -10,7 +10,7 @@ impl RPCOperationSupplyBlockQ { pub fn decode( reader: &veilid_capnp::operation_supply_block_q::Reader, ) -> Result { - let bi_reader = reader.get_block_id().map_err(map_error_capnp_error!())?; + let bi_reader = reader.get_block_id().map_err(RPCError::protocol)?; let block_id = decode_block_id(&bi_reader); Ok(RPCOperationSupplyBlockQ { block_id }) @@ -36,17 +36,17 @@ impl RPCOperationSupplyBlockA { pub fn decode( reader: &veilid_capnp::operation_supply_block_a::Reader, ) -> Result { - match reader.which().map_err(map_error_capnp_notinschema!())? { + match reader.which().map_err(RPCError::protocol)? { veilid_capnp::operation_supply_block_a::Which::Expiration(r) => { Ok(RPCOperationSupplyBlockA::Expiration(r)) } veilid_capnp::operation_supply_block_a::Which::Peers(r) => { - let peers_reader = r.map_err(map_error_capnp_error!())?; + let peers_reader = r.map_err(RPCError::protocol)?; let mut peers = Vec::::with_capacity( peers_reader .len() .try_into() - .map_err(map_error_internal!("too many peers"))?, + .map_err(RPCError::map_internal("too many peers"))?, ); for p in peers_reader.iter() { let peer_info = decode_peer_info(&p, true)?; @@ -70,7 +70,7 @@ impl RPCOperationSupplyBlockA { peers .len() .try_into() - .map_err(map_error_internal!("invalid peers list length"))?, + .map_err(RPCError::map_internal("invalid peers list length"))?, ); for (i, peer) in peers.iter().enumerate() { let mut pi_builder = peers_builder.reborrow().get(i as u32); diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_validate_dial_info.rs b/veilid-core/src/rpc_processor/coders/operations/operation_validate_dial_info.rs index 65629bb8..a11f2501 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_validate_dial_info.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_validate_dial_info.rs @@ -12,9 +12,9 @@ impl RPCOperationValidateDialInfo { pub fn decode( reader: &veilid_capnp::operation_validate_dial_info::Reader, ) -> Result { - let di_reader = reader.get_dial_info().map_err(map_error_capnp_error!())?; + let di_reader = reader.get_dial_info().map_err(RPCError::protocol)?; let dial_info = decode_dial_info(&di_reader)?; - let rcpt_reader = reader.get_receipt().map_err(map_error_capnp_error!())?; + let rcpt_reader = reader.get_receipt().map_err(RPCError::protocol)?; let receipt = rcpt_reader.to_vec(); let redirect = reader.get_redirect(); diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_value_changed.rs b/veilid-core/src/rpc_processor/coders/operations/operation_value_changed.rs index fe1473f9..c1847118 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_value_changed.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_value_changed.rs @@ -11,9 +11,9 @@ impl RPCOperationValueChanged { pub fn decode( reader: &veilid_capnp::operation_value_changed::Reader, ) -> Result { - let k_reader = reader.get_key().map_err(map_error_capnp_error!())?; + let k_reader = reader.get_key().map_err(RPCError::protocol)?; let key = decode_value_key(&k_reader)?; - let v_reader = reader.get_value().map_err(map_error_capnp_error!())?; + let v_reader = reader.get_value().map_err(RPCError::protocol)?; let value = decode_value_data(&v_reader)?; Ok(RPCOperationValueChanged { key, value }) } diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_watch_value.rs b/veilid-core/src/rpc_processor/coders/operations/operation_watch_value.rs index a5b8bca6..48d7d864 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_watch_value.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_watch_value.rs @@ -10,7 +10,7 @@ impl RPCOperationWatchValueQ { pub fn decode( reader: &veilid_capnp::operation_watch_value_q::Reader, ) -> Result { - let k_reader = reader.get_key().map_err(map_error_capnp_error!())?; + let k_reader = reader.get_key().map_err(RPCError::protocol)?; let key = decode_value_key(&k_reader)?; Ok(RPCOperationWatchValueQ { key }) } @@ -35,12 +35,12 @@ impl RPCOperationWatchValueA { reader: &veilid_capnp::operation_watch_value_a::Reader, ) -> Result { let expiration = reader.get_expiration(); - let peers_reader = reader.get_peers().map_err(map_error_capnp_error!())?; + let peers_reader = reader.get_peers().map_err(RPCError::protocol)?; let mut peers = Vec::::with_capacity( peers_reader .len() .try_into() - .map_err(map_error_internal!("too many peers"))?, + .map_err(RPCError::map_internal("too many peers"))?, ); for p in peers_reader.iter() { let peer_info = decode_peer_info(&p, true)?; @@ -59,7 +59,7 @@ impl RPCOperationWatchValueA { self.peers .len() .try_into() - .map_err(map_error_internal!("invalid peers list length"))?, + .map_err(RPCError::map_internal("invalid peers list length"))?, ); for (i, peer) in self.peers.iter().enumerate() { let mut pi_builder = peers_builder.reborrow().get(i as u32); diff --git a/veilid-core/src/rpc_processor/coders/operations/question.rs b/veilid-core/src/rpc_processor/coders/operations/question.rs index 90fa282d..5287cfa1 100644 --- a/veilid-core/src/rpc_processor/coders/operations/question.rs +++ b/veilid-core/src/rpc_processor/coders/operations/question.rs @@ -78,55 +78,55 @@ impl RPCQuestionDetail { pub fn decode( reader: &veilid_capnp::question::detail::Reader, ) -> Result { - let which_reader = reader.which().map_err(map_error_capnp_notinschema!())?; + let which_reader = reader.which().map_err(RPCError::protocol)?; let out = match which_reader { veilid_capnp::question::detail::StatusQ(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationStatusQ::decode(&op_reader)?; RPCQuestionDetail::StatusQ(out) } veilid_capnp::question::detail::FindNodeQ(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationFindNodeQ::decode(&op_reader)?; RPCQuestionDetail::FindNodeQ(out) } veilid_capnp::question::detail::GetValueQ(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationGetValueQ::decode(&op_reader)?; RPCQuestionDetail::GetValueQ(out) } veilid_capnp::question::detail::SetValueQ(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationSetValueQ::decode(&op_reader)?; RPCQuestionDetail::SetValueQ(out) } veilid_capnp::question::detail::WatchValueQ(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationWatchValueQ::decode(&op_reader)?; RPCQuestionDetail::WatchValueQ(out) } veilid_capnp::question::detail::SupplyBlockQ(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationSupplyBlockQ::decode(&op_reader)?; RPCQuestionDetail::SupplyBlockQ(out) } veilid_capnp::question::detail::FindBlockQ(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationFindBlockQ::decode(&op_reader)?; RPCQuestionDetail::FindBlockQ(out) } veilid_capnp::question::detail::StartTunnelQ(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationStartTunnelQ::decode(&op_reader)?; RPCQuestionDetail::StartTunnelQ(out) } veilid_capnp::question::detail::CompleteTunnelQ(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationCompleteTunnelQ::decode(&op_reader)?; RPCQuestionDetail::CompleteTunnelQ(out) } veilid_capnp::question::detail::CancelTunnelQ(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationCancelTunnelQ::decode(&op_reader)?; RPCQuestionDetail::CancelTunnelQ(out) } diff --git a/veilid-core/src/rpc_processor/coders/operations/respond_to.rs b/veilid-core/src/rpc_processor/coders/operations/respond_to.rs index 1a80b4b4..40e50247 100644 --- a/veilid-core/src/rpc_processor/coders/operations/respond_to.rs +++ b/veilid-core/src/rpc_processor/coders/operations/respond_to.rs @@ -32,25 +32,18 @@ impl RespondTo { reader: &veilid_capnp::question::respond_to::Reader, sender_node_id: &DHTKey, ) -> Result { - let respond_to = match reader.which().map_err(map_error_capnp_notinschema!())? { - veilid_capnp::question::respond_to::Sender(_) => RespondTo::Sender(None), - veilid_capnp::question::respond_to::SenderWithInfo(Ok(sender_ni_reader)) => { + let respond_to = match reader.which().map_err(RPCError::protocol)? { + veilid_capnp::question::respond_to::Sender(()) => RespondTo::Sender(None), + veilid_capnp::question::respond_to::SenderWithInfo(sender_ni_reader) => { + let sender_ni_reader = sender_ni_reader.map_err(RPCError::protocol)?; let sni = decode_signed_node_info(&sender_ni_reader, sender_node_id, true)?; RespondTo::Sender(Some(sni)) } - veilid_capnp::question::respond_to::SenderWithInfo(Err(e)) => { - return Err(rpc_error_protocol(format!( - "invalid signed node info: {}", - e - ))) - } - veilid_capnp::question::respond_to::PrivateRoute(Ok(pr_reader)) => { + veilid_capnp::question::respond_to::PrivateRoute(pr_reader) => { + let pr_reader = pr_reader.map_err(RPCError::protocol)?; let pr = decode_private_route(&pr_reader)?; RespondTo::PrivateRoute(pr) } - veilid_capnp::question::respond_to::PrivateRoute(Err(e)) => { - return Err(rpc_error_protocol(format!("invalid private route: {}", e))); - } }; Ok(respond_to) } diff --git a/veilid-core/src/rpc_processor/coders/operations/statement.rs b/veilid-core/src/rpc_processor/coders/operations/statement.rs index d53c39a6..4eb75f5c 100644 --- a/veilid-core/src/rpc_processor/coders/operations/statement.rs +++ b/veilid-core/src/rpc_processor/coders/operations/statement.rs @@ -59,35 +59,35 @@ impl RPCStatementDetail { reader: &veilid_capnp::statement::detail::Reader, sender_node_id: &DHTKey, ) -> Result { - let which_reader = reader.which().map_err(map_error_capnp_notinschema!())?; + let which_reader = reader.which().map_err(RPCError::protocol)?; let out = match which_reader { veilid_capnp::statement::detail::ValidateDialInfo(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationValidateDialInfo::decode(&op_reader)?; RPCStatementDetail::ValidateDialInfo(out) } veilid_capnp::statement::detail::Route(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationRoute::decode(&op_reader)?; RPCStatementDetail::Route(out) } veilid_capnp::statement::detail::NodeInfoUpdate(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationNodeInfoUpdate::decode(&op_reader, sender_node_id)?; RPCStatementDetail::NodeInfoUpdate(out) } veilid_capnp::statement::detail::ValueChanged(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationValueChanged::decode(&op_reader)?; RPCStatementDetail::ValueChanged(out) } veilid_capnp::statement::detail::Signal(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationSignal::decode(&op_reader)?; RPCStatementDetail::Signal(out) } veilid_capnp::statement::detail::ReturnReceipt(r) => { - let op_reader = r.map_err(map_error_capnp_error!())?; + let op_reader = r.map_err(RPCError::protocol)?; let out = RPCOperationReturnReceipt::decode(&op_reader)?; RPCStatementDetail::ReturnReceipt(out) } diff --git a/veilid-core/src/rpc_processor/coders/peer_info.rs b/veilid-core/src/rpc_processor/coders/peer_info.rs index d775527b..043fe761 100644 --- a/veilid-core/src/rpc_processor/coders/peer_info.rs +++ b/veilid-core/src/rpc_processor/coders/peer_info.rs @@ -21,11 +21,11 @@ pub fn decode_peer_info( let nid_reader = reader .reborrow() .get_node_id() - .map_err(map_error_capnp_error!())?; + .map_err(RPCError::protocol)?; let sni_reader = reader .reborrow() .get_signed_node_info() - .map_err(map_error_capnp_error!())?; + .map_err(RPCError::protocol)?; let node_id = NodeId::new(decode_public_key(&nid_reader)); let signed_node_info = decode_signed_node_info(&sni_reader, &node_id.key, allow_relay_peer_info)?; diff --git a/veilid-core/src/rpc_processor/coders/private_safety_route.rs b/veilid-core/src/rpc_processor/coders/private_safety_route.rs index 4de50cc5..6c3c70f6 100644 --- a/veilid-core/src/rpc_processor/coders/private_safety_route.rs +++ b/veilid-core/src/rpc_processor/coders/private_safety_route.rs @@ -83,13 +83,17 @@ pub fn encode_route_hop_data( // let mut nonce_builder = builder.reborrow().init_nonce(); encode_nonce(&route_hop_data.nonce, &mut nonce_builder); - let blob_builder = builder.reborrow().init_blob( - route_hop_data - .blob - .len() - .try_into() - .map_err(map_error_protocol!("invalid blob length in route hop data"))?, - ); + let blob_builder = builder + .reborrow() + .init_blob( + route_hop_data + .blob + .len() + .try_into() + .map_err(RPCError::map_protocol( + "invalid blob length in route hop data", + ))?, + ); blob_builder.copy_from_slice(route_hop_data.blob.as_slice()); Ok(()) } @@ -157,13 +161,13 @@ pub fn decode_route_hop_data( &reader .reborrow() .get_nonce() - .map_err(map_error_protocol!("invalid nonce in route hop data"))?, + .map_err(RPCError::map_protocol("invalid nonce in route hop data"))?, ); let blob = reader .reborrow() .get_blob() - .map_err(map_error_protocol!("invalid blob in route hop data"))? + .map_err(RPCError::map_protocol("invalid blob in route hop data"))? .to_vec(); Ok(RouteHopData { nonce, blob }) @@ -174,13 +178,13 @@ pub fn decode_route_hop(reader: &veilid_capnp::route_hop::Reader) -> Result Result Result { - let public_key = decode_public_key( - &reader - .get_public_key() - .map_err(map_error_protocol!("invalid public key in private route"))?, - ); + let public_key = decode_public_key(&reader.get_public_key().map_err( + RPCError::map_protocol("invalid public key in private route"), + )?); let hop_count = reader.get_hop_count(); let hops = if reader.has_first_hop() { let rh_reader = reader .get_first_hop() - .map_err(map_error_protocol!("invalid first hop in private route"))?; + .map_err(RPCError::map_protocol("invalid first hop in private route"))?; Some(decode_route_hop(&rh_reader)?) } else { None @@ -223,19 +225,18 @@ pub fn decode_safety_route( let public_key = decode_public_key( &reader .get_public_key() - .map_err(map_error_protocol!("invalid public key in safety route"))?, + .map_err(RPCError::map_protocol("invalid public key in safety route"))?, ); let hop_count = reader.get_hop_count(); - let hops = match reader.get_hops().which() { - Ok(veilid_capnp::safety_route::hops::Which::Data(Ok(rhd_reader))) => { + let hops = match reader.get_hops().which().map_err(RPCError::protocol)? { + veilid_capnp::safety_route::hops::Which::Data(rhd_reader) => { + let rhd_reader = rhd_reader.map_err(RPCError::protocol)?; SafetyRouteHops::Data(decode_route_hop_data(&rhd_reader)?) } - Ok(veilid_capnp::safety_route::hops::Which::Private(Ok(pr_reader))) => { + veilid_capnp::safety_route::hops::Which::Private(pr_reader) => { + let pr_reader = pr_reader.map_err(RPCError::protocol)?; SafetyRouteHops::Private(decode_private_route(&pr_reader)?) } - _ => { - return Err(rpc_error_protocol("invalid hops in safety route")); - } }; Ok(SafetyRoute { diff --git a/veilid-core/src/rpc_processor/coders/public_key.rs b/veilid-core/src/rpc_processor/coders/public_key.rs index ffd0531e..d80d9401 100644 --- a/veilid-core/src/rpc_processor/coders/public_key.rs +++ b/veilid-core/src/rpc_processor/coders/public_key.rs @@ -23,27 +23,27 @@ pub fn encode_public_key( builder: &mut veilid_capnp::curve25519_public_key::Builder, ) -> Result<(), RPCError> { if !key.valid { - return Err(rpc_error_protocol("invalid key")); + return Err(RPCError::protocol("invalid key")); } builder.set_u0(u64::from_be_bytes( key.bytes[0..8] .try_into() - .map_err(map_error_protocol!("slice with incorrect length"))?, + .map_err(RPCError::map_protocol("slice with incorrect length"))?, )); builder.set_u1(u64::from_be_bytes( key.bytes[8..16] .try_into() - .map_err(map_error_protocol!("slice with incorrect length"))?, + .map_err(RPCError::map_protocol("slice with incorrect length"))?, )); builder.set_u2(u64::from_be_bytes( key.bytes[16..24] .try_into() - .map_err(map_error_protocol!("slice with incorrect length"))?, + .map_err(RPCError::map_protocol("slice with incorrect length"))?, )); builder.set_u3(u64::from_be_bytes( key.bytes[24..32] .try_into() - .map_err(map_error_protocol!("slice with incorrect length"))?, + .map_err(RPCError::map_protocol("slice with incorrect length"))?, )); Ok(()) } diff --git a/veilid-core/src/rpc_processor/coders/sender_info.rs b/veilid-core/src/rpc_processor/coders/sender_info.rs index 39173980..ffea5be8 100644 --- a/veilid-core/src/rpc_processor/coders/sender_info.rs +++ b/veilid-core/src/rpc_processor/coders/sender_info.rs @@ -16,14 +16,16 @@ pub fn decode_sender_info( reader: &veilid_capnp::sender_info::Reader, ) -> Result { if !reader.has_socket_address() { - return Err(rpc_error_internal("invalid socket address type")); + return Err(RPCError::internal("invalid socket address type")); } let socket_address = if reader.has_socket_address() { Some(decode_socket_address( &reader .reborrow() .get_socket_address() - .map_err(map_error_internal!("invalid socket address in sender_info"))?, + .map_err(RPCError::map_internal( + "invalid socket address in sender_info", + ))?, )?) } else { None diff --git a/veilid-core/src/rpc_processor/coders/signal_info.rs b/veilid-core/src/rpc_processor/coders/signal_info.rs index 901fe83e..d07ff7d4 100644 --- a/veilid-core/src/rpc_processor/coders/signal_info.rs +++ b/veilid-core/src/rpc_processor/coders/signal_info.rs @@ -10,8 +10,8 @@ pub fn encode_signal_info( let mut hp_builder = builder.reborrow().init_hole_punch(); let r_builder = hp_builder .reborrow() - .init_receipt(receipt.len().try_into().map_err(map_error_protocol!( - "invalid receipt length in encode_signal_info" + .init_receipt(receipt.len().try_into().map_err(RPCError::map_protocol( + "invalid receipt length in encode_signal_info", ))?); r_builder.copy_from_slice(receipt); let mut pi_builder = hp_builder.init_peer_info(); @@ -21,8 +21,8 @@ pub fn encode_signal_info( let mut rc_builder = builder.reborrow().init_reverse_connect(); let r_builder = rc_builder .reborrow() - .init_receipt(receipt.len().try_into().map_err(map_error_protocol!( - "invalid receipt length in encode_signal_info" + .init_receipt(receipt.len().try_into().map_err(RPCError::map_protocol( + "invalid receipt length in encode_signal_info", ))?); r_builder.copy_from_slice(receipt); let mut pi_builder = rc_builder.init_peer_info(); @@ -39,22 +39,19 @@ pub fn decode_signal_info( Ok( match reader .which() - .map_err(map_error_internal!("invalid signal operation"))? + .map_err(RPCError::map_internal("invalid signal operation"))? { veilid_capnp::operation_signal::HolePunch(r) => { // Extract hole punch reader - let r = match r { - Ok(r) => r, - Err(_) => return Err(rpc_error_internal("invalid hole punch")), - }; + let r = r.map_err(RPCError::protocol)?; let receipt = r .get_receipt() - .map_err(map_error_protocol!( - "invalid receipt in hole punch signal info" + .map_err(RPCError::map_protocol( + "invalid receipt in hole punch signal info", ))? .to_vec(); - let pi_reader = r.get_peer_info().map_err(map_error_protocol!( - "invalid peer info in hole punch signal info" + let pi_reader = r.get_peer_info().map_err(RPCError::map_protocol( + "invalid peer info in hole punch signal info", ))?; let peer_info = decode_peer_info(&pi_reader, true)?; @@ -62,18 +59,15 @@ pub fn decode_signal_info( } veilid_capnp::operation_signal::ReverseConnect(r) => { // Extract reverse connect reader - let r = match r { - Ok(r) => r, - Err(_) => return Err(rpc_error_internal("invalid reverse connect")), - }; + let r = r.map_err(RPCError::protocol)?; let receipt = r .get_receipt() - .map_err(map_error_protocol!( - "invalid receipt in hole punch signal info" + .map_err(RPCError::map_protocol( + "invalid receipt in hole punch signal info", ))? .to_vec(); - let pi_reader = r.get_peer_info().map_err(map_error_protocol!( - "invalid peer info in reverse connect signal info" + let pi_reader = r.get_peer_info().map_err(RPCError::map_protocol( + "invalid peer info in reverse connect signal info", ))?; let peer_info = decode_peer_info(&pi_reader, true)?; diff --git a/veilid-core/src/rpc_processor/coders/signed_node_info.rs b/veilid-core/src/rpc_processor/coders/signed_node_info.rs index f9ec7b91..11c9d51c 100644 --- a/veilid-core/src/rpc_processor/coders/signed_node_info.rs +++ b/veilid-core/src/rpc_processor/coders/signed_node_info.rs @@ -25,17 +25,17 @@ pub fn decode_signed_node_info( let ni_reader = reader .reborrow() .get_node_info() - .map_err(map_error_capnp_error!())?; + .map_err(RPCError::protocol)?; let node_info = decode_node_info(&ni_reader, allow_relay_peer_info)?; let sig_reader = reader .reborrow() .get_signature() - .map_err(map_error_capnp_error!())?; + .map_err(RPCError::protocol)?; let signature = decode_signature(&sig_reader); let timestamp = reader.reborrow().get_timestamp(); SignedNodeInfo::new(node_info, NodeId::new(*node_id), signature, timestamp) - .map_err(map_error_string!()) + .map_err(RPCError::protocol) } diff --git a/veilid-core/src/rpc_processor/coders/socket_address.rs b/veilid-core/src/rpc_processor/coders/socket_address.rs index ec9ae510..3a9c2a42 100644 --- a/veilid-core/src/rpc_processor/coders/socket_address.rs +++ b/veilid-core/src/rpc_processor/coders/socket_address.rs @@ -17,7 +17,7 @@ pub fn decode_socket_address( let ar = reader .reborrow() .get_address() - .map_err(map_error_internal!("missing socketAddress"))?; + .map_err(RPCError::map_internal("missing socketAddress"))?; let address = decode_address(&ar)?; let port = reader.get_port(); diff --git a/veilid-core/src/rpc_processor/coders/tunnel.rs b/veilid-core/src/rpc_processor/coders/tunnel.rs index 3c80f10d..da12781c 100644 --- a/veilid-core/src/rpc_processor/coders/tunnel.rs +++ b/veilid-core/src/rpc_processor/coders/tunnel.rs @@ -46,10 +46,10 @@ pub fn encode_tunnel_endpoint( pub fn decode_tunnel_endpoint( reader: &veilid_capnp::tunnel_endpoint::Reader, ) -> Result { - let mode = decode_tunnel_mode(reader.get_mode().map_err(map_error_capnp_notinschema!())?); + let mode = decode_tunnel_mode(reader.get_mode().map_err(RPCError::protocol)?); let description = reader .get_description() - .map_err(map_error_capnp_error!())? + .map_err(RPCError::protocol)? .to_owned(); Ok(TunnelEndpoint { mode, description }) @@ -73,9 +73,9 @@ pub fn decode_full_tunnel( ) -> Result { let id = reader.get_id(); let timeout = reader.get_timeout(); - let l_reader = reader.get_local().map_err(map_error_capnp_error!())?; + let l_reader = reader.get_local().map_err(RPCError::protocol)?; let local = decode_tunnel_endpoint(&l_reader)?; - let r_reader = reader.get_remote().map_err(map_error_capnp_error!())?; + let r_reader = reader.get_remote().map_err(RPCError::protocol)?; let remote = decode_tunnel_endpoint(&r_reader)?; Ok(FullTunnel { @@ -102,7 +102,7 @@ pub fn decode_partial_tunnel( ) -> Result { let id = reader.get_id(); let timeout = reader.get_timeout(); - let l_reader = reader.get_local().map_err(map_error_capnp_error!())?; + let l_reader = reader.get_local().map_err(RPCError::protocol)?; let local = decode_tunnel_endpoint(&l_reader)?; Ok(PartialTunnel { id, timeout, local }) diff --git a/veilid-core/src/rpc_processor/coders/value_data.rs b/veilid-core/src/rpc_processor/coders/value_data.rs index 759cb7c3..cd3ad900 100644 --- a/veilid-core/src/rpc_processor/coders/value_data.rs +++ b/veilid-core/src/rpc_processor/coders/value_data.rs @@ -11,10 +11,7 @@ pub fn encode_value_data( } pub fn decode_value_data(reader: &veilid_capnp::value_data::Reader) -> Result { - let data = reader - .get_data() - .map_err(map_error_capnp_error!())? - .to_vec(); + let data = reader.get_data().map_err(RPCError::protocol)?.to_vec(); let seq = reader.get_seq(); Ok(ValueData { data, seq }) } diff --git a/veilid-core/src/rpc_processor/coders/value_key.rs b/veilid-core/src/rpc_processor/coders/value_key.rs index 4acdb1e5..035ab998 100644 --- a/veilid-core/src/rpc_processor/coders/value_key.rs +++ b/veilid-core/src/rpc_processor/coders/value_key.rs @@ -14,12 +14,12 @@ pub fn encode_value_key( } pub fn decode_value_key(reader: &veilid_capnp::value_key::Reader) -> Result { - let pk_reader = reader.get_public_key().map_err(map_error_capnp_error!())?; + let pk_reader = reader.get_public_key().map_err(RPCError::protocol)?; let key = decode_public_key(&pk_reader); let subkey = if !reader.has_subkey() { None } else { - let subkey = reader.get_subkey().map_err(map_error_capnp_error!())?; + let subkey = reader.get_subkey().map_err(RPCError::protocol)?; Some(subkey.to_owned()) }; Ok(ValueKey { key, subkey }) diff --git a/veilid-core/src/rpc_processor/debug.rs b/veilid-core/src/rpc_processor/debug.rs deleted file mode 100644 index 27780e1c..00000000 --- a/veilid-core/src/rpc_processor/debug.rs +++ /dev/null @@ -1,92 +0,0 @@ -use super::*; - -#[derive(Debug, Clone, PartialOrd, PartialEq, Eq, Ord)] -pub enum RPCError { - Timeout, - InvalidFormat(String), - Unreachable(DHTKey), - Unimplemented(String), - Protocol(String), - Internal(String), -} - -pub fn rpc_error_internal(x: T) -> RPCError { - let x = x.to_string(); - error!("RPCError Internal: {}", x); - RPCError::Internal(x) -} -pub fn rpc_error_invalid_format(x: T) -> RPCError { - let x = x.to_string(); - error!("RPCError Invalid Format: {}", x); - RPCError::InvalidFormat(x) -} -pub fn rpc_error_protocol(x: T) -> RPCError { - let x = x.to_string(); - error!("RPCError Protocol: {}", x); - RPCError::Protocol(x) -} -pub fn rpc_error_capnp_error(e: capnp::Error) -> RPCError { - error!("RPCError Protocol: capnp error: {}", &e.description); - RPCError::Protocol(e.description) -} -pub fn rpc_error_capnp_notinschema(e: capnp::NotInSchema) -> RPCError { - error!("RPCError Protocol: not in schema: {}", &e.0); - RPCError::Protocol(format!("not in schema: {}", &e.0)) -} -pub fn rpc_error_unimplemented(x: T) -> RPCError { - let x = x.to_string(); - error!("RPCError Unimplemented: {}", x); - RPCError::Unimplemented(x) -} - -impl fmt::Display for RPCError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - RPCError::Timeout => write!(f, "[RPCError: Timeout]"), - RPCError::InvalidFormat(s) => write!(f, "[RPCError: InvalidFormat({})]", s), - RPCError::Unreachable(k) => write!(f, "[RPCError: Unreachable({})]", k), - RPCError::Unimplemented(s) => write!(f, "[RPCError: Unimplemented({})]", s), - RPCError::Protocol(s) => write!(f, "[RPCError: Protocol({})]", s), - RPCError::Internal(s) => write!(f, "[RPCError: Internal({})]", s), - } - } -} - -#[macro_export] -macro_rules! map_error_internal { - ($x:expr) => { - |_| rpc_error_internal($x) - }; -} -#[macro_export] -macro_rules! map_error_protocol { - ($x:expr) => { - |_| rpc_error_protocol($x) - }; -} -#[macro_export] -macro_rules! map_error_string { - () => { - |s| rpc_error_internal(&s) - }; -} -#[macro_export] -macro_rules! map_error_capnp_error { - () => { - |e| rpc_error_capnp_error(e) - }; -} - -#[macro_export] -macro_rules! map_error_capnp_notinschema { - () => { - |e| rpc_error_capnp_notinschema(e) - }; -} - -#[macro_export] -macro_rules! map_error_panic { - () => { - |_| panic!("oops") - }; -} diff --git a/veilid-core/src/rpc_processor/mod.rs b/veilid-core/src/rpc_processor/mod.rs index 2dce63aa..25e8e1c0 100644 --- a/veilid-core/src/rpc_processor/mod.rs +++ b/veilid-core/src/rpc_processor/mod.rs @@ -1,8 +1,8 @@ mod coders; -mod debug; mod private_route; mod rpc_cancel_tunnel; mod rpc_complete_tunnel; +mod rpc_error; mod rpc_find_block; mod rpc_find_node; mod rpc_get_value; @@ -18,8 +18,8 @@ mod rpc_validate_dial_info; mod rpc_value_changed; mod rpc_watch_value; -pub use debug::*; pub use private_route::*; +pub use rpc_error::*; use super::*; use crate::dht::*; @@ -101,21 +101,22 @@ where let wordvec = builder .into_reader() .canonicalize() - .map_err(map_error_capnp_error!()) - .map_err(logthru_rpc!())?; - Ok(capnp::Word::words_to_bytes(wordvec.as_slice()).to_vec()) -} -fn reader_to_vec<'a, T>(reader: &capnp::message::Reader) -> Result, RPCError> -where - T: capnp::message::ReaderSegments + 'a, -{ - let wordvec = reader - .canonicalize() - .map_err(map_error_capnp_error!()) + .map_err(RPCError::protocol) .map_err(logthru_rpc!())?; Ok(capnp::Word::words_to_bytes(wordvec.as_slice()).to_vec()) } +// fn reader_to_vec<'a, T>(reader: &capnp::message::Reader) -> Result, RPCError> +// where +// T: capnp::message::ReaderSegments + 'a, +// { +// let wordvec = reader +// .canonicalize() +// .map_err(RPCError::protocol) +// .map_err(logthru_rpc!())?; +// Ok(capnp::Word::words_to_bytes(wordvec.as_slice()).to_vec()) +// } + #[derive(Debug)] struct WaitableReply { op_id: OperationId, @@ -243,16 +244,16 @@ impl RPCProcessor { // Search the DHT for a single node closest to a key and add it to the routing table and return the node reference pub async fn search_dht_single_key( &self, - node_id: DHTKey, + _node_id: DHTKey, _count: u32, _fanout: u32, _timeout: Option, ) -> Result { - let routing_table = self.routing_table(); + //let routing_table = self.routing_table(); // xxx find node but stop if we find the exact node we want // xxx return whatever node is closest after the timeout - Err(rpc_error_unimplemented("search_dht_single_key")).map_err(logthru_rpc!(error)) + Err(RPCError::unimplemented("search_dht_single_key")).map_err(logthru_rpc!(error)) } // Search the DHT for the 'count' closest nodes to a key, adding them all to the routing table if they are not there and returning their node references @@ -264,7 +265,7 @@ impl RPCProcessor { _timeout: Option, ) -> Result, RPCError> { // xxx return closest nodes after the timeout - Err(rpc_error_unimplemented("search_dht_multi_key")).map_err(logthru_rpc!(error)) + Err(RPCError::unimplemented("search_dht_multi_key")).map_err(logthru_rpc!(error)) } // Search the DHT for a specific node corresponding to a key unless we have that node in our routing table already, and return the node reference @@ -328,7 +329,7 @@ impl RPCProcessor { inner .waiting_rpc_table .remove(&op_id) - .ok_or_else(|| rpc_error_internal("Unmatched operation id"))? + .ok_or_else(RPCError::else_internal("Unmatched operation id"))? }; eventual.resolve(msg).await; Ok(()) @@ -340,7 +341,7 @@ impl RPCProcessor { waitable_reply: &WaitableReply, ) -> Result<(RPCMessage, u64), RPCError> { let timeout_ms = u32::try_from(waitable_reply.timeout / 1000u64) - .map_err(map_error_internal!("invalid timeout"))?; + .map_err(RPCError::map_internal("invalid timeout"))?; // wait for eventualvalue let start_ts = intf::get_timestamp(); let res = intf::timeout(timeout_ms, waitable_reply.eventual.instance()) @@ -459,7 +460,7 @@ impl RPCProcessor { out_node_id = sr .hops .first() - .ok_or_else(|| rpc_error_internal("no hop in safety route"))? + .ok_or_else(RPCError::else_internal("no hop in safety route"))? .dial_info .node_id .key; @@ -478,7 +479,7 @@ impl RPCProcessor { out_hop_count = private_route.hop_count as usize; let out_node_id = match &private_route.hops { Some(rh) => rh.dial_info.node_id.key, - _ => return Err(rpc_error_internal("private route has no hops")), + _ => return Err(RPCError::internal("private route has no hops")), }; out_message = self.wrap_with_route(None, private_route, message_vec)?; out_node_id @@ -489,7 +490,7 @@ impl RPCProcessor { let out_node_id = sr .hops .first() - .ok_or_else(|| rpc_error_internal("no hop in safety route"))? + .ok_or_else(RPCError::else_internal("no hop in safety route"))? .dial_info .node_id .key; @@ -502,7 +503,7 @@ impl RPCProcessor { // Verify hop count isn't larger than out maximum routed hop count if out_hop_count > self.inner.lock().max_route_hop_count { - return Err(rpc_error_internal("hop count too long for route")) + return Err(RPCError::internal("hop count too long for route")) .map_err(logthru_rpc!(warn)); } @@ -565,7 +566,7 @@ impl RPCProcessor { .network_manager() .send_envelope(node_ref.clone(), Some(node_id), message) .await - .map_err(RPCError::Internal) + .map_err(RPCError::internal) { Ok(v) => v, Err(e) => { @@ -637,7 +638,7 @@ impl RPCProcessor { .network_manager() .send_envelope(node_ref.clone(), Some(node_id), message) .await - .map_err(RPCError::Internal) + .map_err(RPCError::network) { Ok(v) => v, Err(e) => { @@ -729,7 +730,7 @@ impl RPCProcessor { self.network_manager() .send_envelope(node_ref.clone(), Some(node_id), message) .await - .map_err(RPCError::Internal) + .map_err(RPCError::network) .map_err(|e| { self.routing_table() .stats_failed_to_send(node_ref.clone(), send_ts, false); @@ -763,7 +764,7 @@ impl RPCProcessor { let reader = capnp::message::Reader::new(encoded_msg.data, Default::default()); let op_reader = reader .get_root::() - .map_err(map_error_capnp_error!()) + .map_err(RPCError::protocol) .map_err(logthru_rpc!())?; RPCOperation::decode(&op_reader, &sender_node_id)? }; @@ -776,13 +777,14 @@ impl RPCProcessor { RespondTo::Sender(Some(sender_ni)) => { // Sender NodeInfo was specified, update our routing table with it if !self.filter_peer_scope(&sender_ni.node_info) { - return Err(rpc_error_invalid_format( + return Err(RPCError::invalid_format( "respond_to_sender_signed_node_info has invalid peer scope", )); } let nr = self .routing_table() .register_node_with_signed_node_info(sender_node_id, sender_ni.clone()) + .map_err(map_to_string) .map_err(RPCError::Internal)?; opt_sender_nr = Some(nr); } @@ -883,7 +885,7 @@ impl RPCProcessor { } #[instrument(level = "debug", skip_all, err)] - pub async fn startup(&self) -> Result<(), String> { + pub async fn startup(&self) -> EyreResult<()> { trace!("startup rpc processor"); let mut inner = self.inner.lock(); // make local copy of node id for easy access @@ -966,7 +968,7 @@ impl RPCProcessor { envelope: Envelope, body: Vec, peer_noderef: NodeRef, - ) -> Result<(), String> { + ) -> EyreResult<()> { let msg = RPCMessageEncoded { header: RPCMessageHeader { timestamp: intf::get_timestamp(), @@ -982,7 +984,7 @@ impl RPCProcessor { }; send_channel .try_send(msg) - .map_err(|e| format!("failed to enqueue received RPC message: {:?}", e))?; + .wrap_err("failed to enqueue received RPC message")?; Ok(()) } } diff --git a/veilid-core/src/rpc_processor/private_route.rs b/veilid-core/src/rpc_processor/private_route.rs index 089906a5..d5a59991 100644 --- a/veilid-core/src/rpc_processor/private_route.rs +++ b/veilid-core/src/rpc_processor/private_route.rs @@ -12,7 +12,7 @@ impl RPCProcessor { let sr_hopcount = safety_route_spec.hops.len(); let hopcount = 1 + sr_hopcount + pr_hopcount; if hopcount > self.inner.lock().max_route_hop_count { - return Err(rpc_error_internal("hop count too long for route")); + return Err(RPCError::internal("hop count too long for route")); } // Create hops @@ -47,10 +47,10 @@ impl RPCProcessor { &safety_route_spec.hops[h].dial_info.node_id.key, &safety_route_spec.secret_key, ) - .map_err(map_error_internal!("dh failed"))?; + .map_err(RPCError::map_internal("dh failed"))?; let enc_msg_data = Crypto::encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None) - .map_err(map_error_internal!("encryption failed"))?; + .map_err(RPCError::map_internal("encryption failed"))?; // Make route hop data let route_hop_data = RouteHopData { @@ -86,9 +86,9 @@ impl RPCProcessor { &safety_route_spec.hops[0].dial_info.node_id.key, &safety_route_spec.secret_key, ) - .map_err(map_error_internal!("dh failed"))?; + .map_err(RPCError::map_internal("dh failed"))?; let enc_msg_data = Crypto::encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None) - .map_err(map_error_internal!("encryption failed"))?; + .map_err(RPCError::map_internal("encryption failed"))?; let route_hop_data = RouteHopData { nonce, @@ -123,9 +123,9 @@ impl RPCProcessor { let dh_secret = self .crypto .cached_dh(&private_route.public_key, &safety_route_spec.secret_key) - .map_err(map_error_internal!("dh failed"))?; + .map_err(RPCError::map_internal("dh failed"))?; let enc_msg_data = Crypto::encrypt_aead(&message_data, &nonce, &dh_secret, None) - .map_err(map_error_internal!("encryption failed"))?; + .map_err(RPCError::map_internal("encryption failed"))?; // Compile the safety route with the private route let safety_route = self.compile_safety_route(safety_route_spec, private_route)?; diff --git a/veilid-core/src/rpc_processor/rpc_cancel_tunnel.rs b/veilid-core/src/rpc_processor/rpc_cancel_tunnel.rs index 62ff55b9..bc4b1cc2 100644 --- a/veilid-core/src/rpc_processor/rpc_cancel_tunnel.rs +++ b/veilid-core/src/rpc_processor/rpc_cancel_tunnel.rs @@ -2,6 +2,6 @@ use super::*; impl RPCProcessor { pub(crate) async fn process_cancel_tunnel_q(&self, msg: RPCMessage) -> Result<(), RPCError> { - Err(rpc_error_unimplemented("process_cancel_tunnel_q")) + Err(RPCError::unimplemented("process_cancel_tunnel_q")) } } diff --git a/veilid-core/src/rpc_processor/rpc_complete_tunnel.rs b/veilid-core/src/rpc_processor/rpc_complete_tunnel.rs index aa73f303..04d10e76 100644 --- a/veilid-core/src/rpc_processor/rpc_complete_tunnel.rs +++ b/veilid-core/src/rpc_processor/rpc_complete_tunnel.rs @@ -2,6 +2,6 @@ use super::*; impl RPCProcessor { pub(crate) async fn process_complete_tunnel_q(&self, msg: RPCMessage) -> Result<(), RPCError> { - Err(rpc_error_unimplemented("process_complete_tunnel_q")) + Err(RPCError::unimplemented("process_complete_tunnel_q")) } } diff --git a/veilid-core/src/rpc_processor/rpc_error.rs b/veilid-core/src/rpc_processor/rpc_error.rs new file mode 100644 index 00000000..16288a17 --- /dev/null +++ b/veilid-core/src/rpc_processor/rpc_error.rs @@ -0,0 +1,58 @@ +use super::*; + +#[derive(ThisError, Debug, Clone, PartialOrd, PartialEq, Eq, Ord)] +pub enum RPCError { + #[error("[RPCError: Timeout]")] + Timeout, + #[error("[RPCError: Unreachable({0})]")] + Unreachable(DHTKey), + #[error("[RPCError: Unimplemented({0})]")] + Unimplemented(String), + #[error("[RPCError: InvalidFormat({0})]")] + InvalidFormat(String), + #[error("[RPCError: Protocol({0})]")] + Protocol(String), + #[error("[RPCError: Internal({0})]")] + Internal(String), + #[error("[RPCError: Network({0})]")] + Network(String), +} + +impl RPCError { + pub fn timeout() -> Self { + Self::Timeout + } + pub fn unreachable(key: DHTKey) -> Self { + Self::Unreachable(key) + } + pub fn unimplemented(x: X) -> Self { + Self::Unimplemented(x.to_string()) + } + pub fn invalid_format(x: X) -> Self { + Self::InvalidFormat(x.to_string()) + } + pub fn map_invalid_format(message: M) -> impl FnOnce(X) -> Self { + move |x| Self::InvalidFormat(format!("{}: {}", message.to_string(), x.to_string())) + } + pub fn protocol(x: X) -> Self { + Self::Protocol(x.to_string()) + } + pub fn map_protocol(message: M) -> impl FnOnce(X) -> Self { + move |x| Self::Protocol(format!("{}: {}", message.to_string(), x.to_string())) + } + pub fn internal(x: X) -> Self { + Self::Internal(x.to_string()) + } + pub fn map_internal(message: M) -> impl FnOnce(X) -> Self { + move |x| Self::Internal(format!("{}: {}", message.to_string(), x.to_string())) + } + pub fn else_internal(message: M) -> impl FnOnce() -> Self { + move || Self::Internal(format!("{}", message.to_string())) + } + pub fn network(x: X) -> Self { + Self::Network(x.to_string()) + } + pub fn map_network(message: M) -> impl FnOnce(X) -> Self { + move |x| Self::Network(format!("{}: {}", message.to_string(), x.to_string())) + } +} diff --git a/veilid-core/src/rpc_processor/rpc_find_block.rs b/veilid-core/src/rpc_processor/rpc_find_block.rs index 2a4c4eff..97b4e61b 100644 --- a/veilid-core/src/rpc_processor/rpc_find_block.rs +++ b/veilid-core/src/rpc_processor/rpc_find_block.rs @@ -2,6 +2,6 @@ use super::*; impl RPCProcessor { pub(crate) async fn process_find_block_q(&self, msg: RPCMessage) -> Result<(), RPCError> { - Err(rpc_error_unimplemented("process_find_block_q")) + Err(RPCError::unimplemented("process_find_block_q")) } } diff --git a/veilid-core/src/rpc_processor/rpc_find_node.rs b/veilid-core/src/rpc_processor/rpc_find_node.rs index a61ade81..472c2a1c 100644 --- a/veilid-core/src/rpc_processor/rpc_find_node.rs +++ b/veilid-core/src/rpc_processor/rpc_find_node.rs @@ -23,15 +23,15 @@ impl RPCProcessor { let find_node_a = match msg.operation.into_kind() { RPCOperationKind::Answer(a) => match a.into_detail() { RPCAnswerDetail::FindNodeA(a) => a, - _ => return Err(rpc_error_invalid_format("not a find_node answer")), + _ => return Err(RPCError::invalid_format("not a find_node answer")), }, - _ => return Err(rpc_error_invalid_format("not an answer")), + _ => return Err(RPCError::invalid_format("not an answer")), }; // Verify peers are in the correct peer scope for peer_info in &find_node_a.peers { if !self.filter_peer_scope(&peer_info.signed_node_info.node_info) { - return Err(rpc_error_invalid_format( + return Err(RPCError::invalid_format( "find_node response has invalid peer scope", )); } diff --git a/veilid-core/src/rpc_processor/rpc_get_value.rs b/veilid-core/src/rpc_processor/rpc_get_value.rs index dfc0a7c2..c72e7092 100644 --- a/veilid-core/src/rpc_processor/rpc_get_value.rs +++ b/veilid-core/src/rpc_processor/rpc_get_value.rs @@ -2,6 +2,6 @@ use super::*; impl RPCProcessor { pub(crate) async fn process_get_value_q(&self, msg: RPCMessage) -> Result<(), RPCError> { - Err(rpc_error_unimplemented("process_get_value_q")) + Err(RPCError::unimplemented("process_get_value_q")) } } diff --git a/veilid-core/src/rpc_processor/rpc_node_info_update.rs b/veilid-core/src/rpc_processor/rpc_node_info_update.rs index 84e7e5a2..5893f940 100644 --- a/veilid-core/src/rpc_processor/rpc_node_info_update.rs +++ b/veilid-core/src/rpc_processor/rpc_node_info_update.rs @@ -32,13 +32,14 @@ impl RPCProcessor { // Update our routing table with signed node info if !self.filter_peer_scope(&node_info_update.signed_node_info.node_info) { - return Err(rpc_error_invalid_format( + return Err(RPCError::invalid_format( "node_info_update has invalid peer scope", )); } let _ = self .routing_table() .register_node_with_signed_node_info(sender_node_id, node_info_update.signed_node_info) + .map_err(map_to_string) .map_err(RPCError::Internal)?; Ok(()) diff --git a/veilid-core/src/rpc_processor/rpc_return_receipt.rs b/veilid-core/src/rpc_processor/rpc_return_receipt.rs index 2166f4e8..0a962081 100644 --- a/veilid-core/src/rpc_processor/rpc_return_receipt.rs +++ b/veilid-core/src/rpc_processor/rpc_return_receipt.rs @@ -35,6 +35,6 @@ impl RPCProcessor { network_manager .handle_in_band_receipt(receipt, msg.header.peer_noderef) .await - .map_err(map_error_string!()) + .map_err(RPCError::network) } } diff --git a/veilid-core/src/rpc_processor/rpc_route.rs b/veilid-core/src/rpc_processor/rpc_route.rs index a211c3b9..00f12eb9 100644 --- a/veilid-core/src/rpc_processor/rpc_route.rs +++ b/veilid-core/src/rpc_processor/rpc_route.rs @@ -5,6 +5,6 @@ impl RPCProcessor { pub(crate) async fn process_route(&self, _rpcreader: RPCMessage) -> Result<(), RPCError> { // xxx do not process latency for routed messages - Err(rpc_error_unimplemented("process_route")) + Err(RPCError::unimplemented("process_route")) } } diff --git a/veilid-core/src/rpc_processor/rpc_set_value.rs b/veilid-core/src/rpc_processor/rpc_set_value.rs index f3d37041..5e1b2661 100644 --- a/veilid-core/src/rpc_processor/rpc_set_value.rs +++ b/veilid-core/src/rpc_processor/rpc_set_value.rs @@ -2,6 +2,6 @@ use super::*; impl RPCProcessor { pub(crate) async fn process_set_value_q(&self, msg: RPCMessage) -> Result<(), RPCError> { - Err(rpc_error_unimplemented("process_set_value_q")) + Err(RPCError::unimplemented("process_set_value_q")) } } diff --git a/veilid-core/src/rpc_processor/rpc_signal.rs b/veilid-core/src/rpc_processor/rpc_signal.rs index c764b621..8c7362fc 100644 --- a/veilid-core/src/rpc_processor/rpc_signal.rs +++ b/veilid-core/src/rpc_processor/rpc_signal.rs @@ -34,6 +34,6 @@ impl RPCProcessor { network_manager .handle_signal(signal.signal_info) .await - .map_err(map_error_string!()) + .map_err(RPCError::network) } } diff --git a/veilid-core/src/rpc_processor/rpc_start_tunnel.rs b/veilid-core/src/rpc_processor/rpc_start_tunnel.rs index 13b6d55d..5ac8630b 100644 --- a/veilid-core/src/rpc_processor/rpc_start_tunnel.rs +++ b/veilid-core/src/rpc_processor/rpc_start_tunnel.rs @@ -2,6 +2,6 @@ use super::*; impl RPCProcessor { pub(crate) async fn process_start_tunnel_q(&self, msg: RPCMessage) -> Result<(), RPCError> { - Err(rpc_error_unimplemented("process_start_tunnel_q")) + Err(RPCError::unimplemented("process_start_tunnel_q")) } } diff --git a/veilid-core/src/rpc_processor/rpc_status.rs b/veilid-core/src/rpc_processor/rpc_status.rs index 37cc49a5..7a2385ef 100644 --- a/veilid-core/src/rpc_processor/rpc_status.rs +++ b/veilid-core/src/rpc_processor/rpc_status.rs @@ -24,9 +24,9 @@ impl RPCProcessor { let status_a = match msg.operation.into_kind() { RPCOperationKind::Answer(a) => match a.into_detail() { RPCAnswerDetail::StatusA(a) => a, - _ => return Err(rpc_error_invalid_format("not a status answer")), + _ => return Err(RPCError::invalid_format("not a status answer")), }, - _ => return Err(rpc_error_invalid_format("not an answer")), + _ => return Err(RPCError::invalid_format("not an answer")), }; // Update latest node status in routing table diff --git a/veilid-core/src/rpc_processor/rpc_supply_block.rs b/veilid-core/src/rpc_processor/rpc_supply_block.rs index a187817e..2d46ae53 100644 --- a/veilid-core/src/rpc_processor/rpc_supply_block.rs +++ b/veilid-core/src/rpc_processor/rpc_supply_block.rs @@ -2,6 +2,6 @@ use super::*; impl RPCProcessor { pub(crate) async fn process_supply_block_q(&self, msg: RPCMessage) -> Result<(), RPCError> { - Err(rpc_error_unimplemented("process_supply_block_q")) + Err(RPCError::unimplemented("process_supply_block_q")) } } diff --git a/veilid-core/src/rpc_processor/rpc_validate_dial_info.rs b/veilid-core/src/rpc_processor/rpc_validate_dial_info.rs index 6fb56e6a..02e64de3 100644 --- a/veilid-core/src/rpc_processor/rpc_validate_dial_info.rs +++ b/veilid-core/src/rpc_processor/rpc_validate_dial_info.rs @@ -20,7 +20,7 @@ impl RPCProcessor { // Generate receipt and waitable eventual so we can see if we get the receipt back let (receipt, eventual_value) = network_manager .generate_single_shot_receipt(receipt_time, []) - .map_err(map_error_string!())?; + .map_err(RPCError::internal)?; let validate_dial_info = RPCOperationValidateDialInfo { dial_info, @@ -36,7 +36,7 @@ impl RPCProcessor { // Wait for receipt match eventual_value.await.take_value().unwrap() { - ReceiptEvent::ReturnedInBand { inbound_noderef: _ } => Err(rpc_error_internal( + ReceiptEvent::ReturnedInBand { inbound_noderef: _ } => Err(RPCError::internal( "validate_dial_info receipt should be returned out-of-band", )), ReceiptEvent::ReturnedOutOfBand => { @@ -48,7 +48,7 @@ impl RPCProcessor { Ok(false) } ReceiptEvent::Cancelled => { - Err(rpc_error_internal("receipt was dropped before expiration")) + Err(RPCError::internal("receipt was dropped before expiration")) } } } @@ -82,7 +82,7 @@ impl RPCProcessor { }; let peers = routing_table.find_fast_public_nodes_filtered(node_count, &filter); if peers.is_empty() { - return Err(rpc_error_internal(format!( + return Err(RPCError::internal(format!( "no peers matching filter '{:?}'", filter ))); @@ -148,10 +148,7 @@ impl RPCProcessor { network_manager .send_out_of_band_receipt(dial_info.clone(), receipt) .await - .map_err(map_error_string!()) - .map_err( - logthru_net!(error "failed to send direct receipt to dial info: {}", dial_info), - )?; + .map_err(RPCError::network)?; Ok(()) } diff --git a/veilid-core/src/rpc_processor/rpc_value_changed.rs b/veilid-core/src/rpc_processor/rpc_value_changed.rs index 2cfa185d..80a47658 100644 --- a/veilid-core/src/rpc_processor/rpc_value_changed.rs +++ b/veilid-core/src/rpc_processor/rpc_value_changed.rs @@ -2,6 +2,6 @@ use super::*; impl RPCProcessor { pub(crate) async fn process_value_changed(&self, msg: RPCMessage) -> Result<(), RPCError> { - Err(rpc_error_unimplemented("process_value_changed")) + Err(RPCError::unimplemented("process_value_changed")) } } diff --git a/veilid-core/src/rpc_processor/rpc_watch_value.rs b/veilid-core/src/rpc_processor/rpc_watch_value.rs index 1d5c9a04..67151b14 100644 --- a/veilid-core/src/rpc_processor/rpc_watch_value.rs +++ b/veilid-core/src/rpc_processor/rpc_watch_value.rs @@ -2,6 +2,6 @@ use super::*; impl RPCProcessor { pub(crate) async fn process_watch_value_q(&self, msg: RPCMessage) -> Result<(), RPCError> { - Err(rpc_error_unimplemented("process_watch_value_q")) + Err(RPCError::unimplemented("process_watch_value_q")) } } diff --git a/veilid-core/src/tests/common/test_protected_store.rs b/veilid-core/src/tests/common/test_protected_store.rs index ef95d208..ef48c11a 100644 --- a/veilid-core/src/tests/common/test_protected_store.rs +++ b/veilid-core/src/tests/common/test_protected_store.rs @@ -25,55 +25,59 @@ pub async fn test_protected_store(ps: ProtectedStore) { let d1: [u8; 0] = []; assert_eq!( - ps.save_user_secret("_test_key", &[2u8, 3u8, 4u8]).await, - Ok(false) + ps.save_user_secret("_test_key", &[2u8, 3u8, 4u8]) + .await + .unwrap(), + false ); info!("testing saving user secret"); - assert_eq!(ps.save_user_secret("_test_key", &d1).await, Ok(true)); + assert_eq!(ps.save_user_secret("_test_key", &d1).await.unwrap(), true); info!("testing loading user secret"); assert_eq!( - ps.load_user_secret("_test_key").await, - Ok(Some(d1.to_vec())) + ps.load_user_secret("_test_key").await.unwrap(), + Some(d1.to_vec()) ); info!("testing loading user secret again"); assert_eq!( - ps.load_user_secret("_test_key").await, - Ok(Some(d1.to_vec())) + ps.load_user_secret("_test_key").await.unwrap(), + Some(d1.to_vec()) ); info!("testing loading broken user secret"); - assert_eq!(ps.load_user_secret("_test_broken").await, Ok(None)); + assert_eq!(ps.load_user_secret("_test_broken").await.unwrap(), None); info!("testing loading broken user secret again"); - assert_eq!(ps.load_user_secret("_test_broken").await, Ok(None)); + assert_eq!(ps.load_user_secret("_test_broken").await.unwrap(), None); info!("testing remove user secret"); - assert_eq!(ps.remove_user_secret("_test_key").await, Ok(true)); + assert_eq!(ps.remove_user_secret("_test_key").await.unwrap(), true); info!("testing remove user secret again"); - assert_eq!(ps.remove_user_secret("_test_key").await, Ok(false)); + assert_eq!(ps.remove_user_secret("_test_key").await.unwrap(), false); info!("testing remove broken user secret"); - assert_eq!(ps.remove_user_secret("_test_broken").await, Ok(false)); + assert_eq!(ps.remove_user_secret("_test_broken").await.unwrap(), false); info!("testing remove broken user secret again"); - assert_eq!(ps.remove_user_secret("_test_broken").await, Ok(false)); + assert_eq!(ps.remove_user_secret("_test_broken").await.unwrap(), false); let d2: [u8; 10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; assert_eq!( - ps.save_user_secret("_test_key", &[2u8, 3u8, 4u8]).await, - Ok(false) + ps.save_user_secret("_test_key", &[2u8, 3u8, 4u8]) + .await + .unwrap(), + false ); - assert_eq!(ps.save_user_secret("_test_key", &d2).await, Ok(true)); + assert_eq!(ps.save_user_secret("_test_key", &d2).await.unwrap(), true); assert_eq!( - ps.load_user_secret("_test_key").await, - Ok(Some(d2.to_vec())) + ps.load_user_secret("_test_key").await.unwrap(), + Some(d2.to_vec()) ); assert_eq!( - ps.load_user_secret("_test_key").await, - Ok(Some(d2.to_vec())) + ps.load_user_secret("_test_key").await.unwrap(), + Some(d2.to_vec()) ); - assert_eq!(ps.load_user_secret("_test_broken").await, Ok(None)); - assert_eq!(ps.load_user_secret("_test_broken").await, Ok(None)); - assert_eq!(ps.remove_user_secret("_test_key").await, Ok(true)); - assert_eq!(ps.remove_user_secret("_test_key").await, Ok(false)); - assert_eq!(ps.remove_user_secret("_test_broken").await, Ok(false)); - assert_eq!(ps.remove_user_secret("_test_broken").await, Ok(false)); + assert_eq!(ps.load_user_secret("_test_broken").await.unwrap(), None); + assert_eq!(ps.load_user_secret("_test_broken").await.unwrap(), None); + assert_eq!(ps.remove_user_secret("_test_key").await.unwrap(), true); + assert_eq!(ps.remove_user_secret("_test_key").await.unwrap(), false); + assert_eq!(ps.remove_user_secret("_test_broken").await.unwrap(), false); + assert_eq!(ps.remove_user_secret("_test_broken").await.unwrap(), false); let _ = ps.remove_user_secret("_test_key").await; let _ = ps.remove_user_secret("_test_broken").await; diff --git a/veilid-core/src/tests/common/test_table_store.rs b/veilid-core/src/tests/common/test_table_store.rs index ad58d834..9a4b73a9 100644 --- a/veilid-core/src/tests/common/test_table_store.rs +++ b/veilid-core/src/tests/common/test_table_store.rs @@ -59,8 +59,8 @@ pub async fn test_store_delete_load(ts: TableStore) { ); assert_eq!( - db.load(0, b"foo").await, - Ok(None), + db.load(0, b"foo").await.unwrap(), + None, "should not load missing key" ); assert!( @@ -68,11 +68,14 @@ pub async fn test_store_delete_load(ts: TableStore) { "should store new key" ); assert_eq!( - db.load(0, b"foo").await, - Ok(None), + db.load(0, b"foo").await.unwrap(), + None, "should not load missing key" ); - assert_eq!(db.load(1, b"foo").await, Ok(Some(b"1234567890".to_vec()))); + assert_eq!( + db.load(1, b"foo").await.unwrap(), + Some(b"1234567890".to_vec()) + ); assert!( db.store(1, b"bar", b"FNORD").await.is_ok(), @@ -97,16 +100,19 @@ pub async fn test_store_delete_load(ts: TableStore) { "should store new key" ); - assert_eq!(db.load(1, b"bar").await, Ok(Some(b"FNORD".to_vec()))); + assert_eq!(db.load(1, b"bar").await.unwrap(), Some(b"FNORD".to_vec())); assert_eq!( - db.load(0, b"bar").await, - Ok(Some(b"ABCDEFGHIJKLMNOPQRSTUVWXYZ".to_vec())) + db.load(0, b"bar").await.unwrap(), + Some(b"ABCDEFGHIJKLMNOPQRSTUVWXYZ".to_vec()) ); - assert_eq!(db.load(2, b"bar").await, Ok(Some(b"QWERTYUIOP".to_vec()))); - assert_eq!(db.load(2, b"baz").await, Ok(Some(b"QWERTY".to_vec()))); + assert_eq!( + db.load(2, b"bar").await.unwrap(), + Some(b"QWERTYUIOP".to_vec()) + ); + assert_eq!(db.load(2, b"baz").await.unwrap(), Some(b"QWERTY".to_vec())); - assert_eq!(db.delete(1, b"bar").await, Ok(true)); - assert_eq!(db.delete(1, b"bar").await, Ok(false)); + assert_eq!(db.delete(1, b"bar").await.unwrap(), true); + assert_eq!(db.delete(1, b"bar").await.unwrap(), false); assert!( db.delete(4, b"bar").await.is_err(), "can't delete from column that doesn't exist" @@ -115,13 +121,16 @@ pub async fn test_store_delete_load(ts: TableStore) { drop(db); let db = ts.open("test", 3).await.expect("should have opened"); - assert_eq!(db.load(1, b"bar").await, Ok(None)); + assert_eq!(db.load(1, b"bar").await.unwrap(), None); assert_eq!( - db.load(0, b"bar").await, - Ok(Some(b"ABCDEFGHIJKLMNOPQRSTUVWXYZ".to_vec())) + db.load(0, b"bar").await.unwrap(), + Some(b"ABCDEFGHIJKLMNOPQRSTUVWXYZ".to_vec()) ); - assert_eq!(db.load(2, b"bar").await, Ok(Some(b"QWERTYUIOP".to_vec()))); - assert_eq!(db.load(2, b"baz").await, Ok(Some(b"QWERTY".to_vec()))); + assert_eq!( + db.load(2, b"bar").await.unwrap(), + Some(b"QWERTYUIOP".to_vec()) + ); + assert_eq!(db.load(2, b"baz").await.unwrap(), Some(b"QWERTY".to_vec())); } pub async fn test_cbor(ts: TableStore) { @@ -133,7 +142,7 @@ pub async fn test_cbor(ts: TableStore) { assert!(db.store_cbor(0, b"asdf", &dht_key).await.is_ok()); - assert_eq!(db.load_cbor::(0, b"qwer").await, Ok(None)); + assert_eq!(db.load_cbor::(0, b"qwer").await.unwrap(), None); let d = match db.load_cbor::(0, b"asdf").await { Ok(x) => x, diff --git a/veilid-core/src/veilid_api/mod.rs b/veilid-core/src/veilid_api/mod.rs index 025c5852..52db566f 100644 --- a/veilid-core/src/veilid_api/mod.rs +++ b/veilid-core/src/veilid_api/mod.rs @@ -87,44 +87,39 @@ macro_rules! apibail_parse { }; } -#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)] +#[derive(ThisError, Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)] #[serde(tag = "kind")] pub enum VeilidAPIError { + #[error("Not initialized")] NotInitialized, + #[error("Already initialized")] AlreadyInitialized, + #[error("Timeout")] Timeout, + #[error("Shutdown")] Shutdown, - NodeNotFound { - node_id: NodeId, - }, - NoDialInfo { - node_id: NodeId, - }, - NoPeerInfo { - node_id: NodeId, - }, - Internal { - message: String, - }, - Unimplemented { - message: String, - }, - ParseError { - message: String, - value: String, - }, + #[error("Node not found: {node_id}")] + NodeNotFound { node_id: NodeId }, + #[error("No dial info: {node_id}")] + NoDialInfo { node_id: NodeId }, + #[error("No peer info: {node_id}")] + NoPeerInfo { node_id: NodeId }, + #[error("Internal: {message}")] + Internal { message: String }, + #[error("Unimplemented: {message}")] + Unimplemented { message: String }, + #[error("Parse error: '{message}' with value '{value}'")] + ParseError { message: String, value: String }, + #[error("Invalid argument: '{argument}' for '{context}' with value '{value}'")] InvalidArgument { context: String, argument: String, value: String, }, - MissingArgument { - context: String, - argument: String, - }, - Generic { - message: String, - }, + #[error("Missing argument: '{argument}' for '{context}'")] + MissingArgument { context: String, argument: String }, + #[error("Generic: {message}")] + Generic { message: String }, } impl VeilidAPIError { @@ -177,79 +172,6 @@ impl VeilidAPIError { } } -impl std::error::Error for VeilidAPIError {} - -impl fmt::Display for VeilidAPIError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - match self { - VeilidAPIError::NotInitialized => write!(f, "VeilidAPIError::NotInitialized"), - VeilidAPIError::AlreadyInitialized => write!(f, "VeilidAPIError::AlreadyInitialized"), - VeilidAPIError::Timeout => write!(f, "VeilidAPIError::Timeout"), - VeilidAPIError::Shutdown => write!(f, "VeilidAPIError::Shutdown"), - VeilidAPIError::NodeNotFound { node_id } => { - write!(f, "VeilidAPIError::NodeNotFound({})", node_id) - } - VeilidAPIError::NoDialInfo { node_id } => { - write!(f, "VeilidAPIError::NoDialInfo({})", node_id) - } - VeilidAPIError::NoPeerInfo { node_id } => { - write!(f, "VeilidAPIError::NoPeerInfo({})", node_id) - } - VeilidAPIError::Internal { message } => { - write!(f, "VeilidAPIError::Internal({})", message) - } - VeilidAPIError::Unimplemented { message } => { - write!(f, "VeilidAPIError::Unimplemented({})", message) - } - VeilidAPIError::ParseError { message, value } => { - write!(f, "VeilidAPIError::ParseError({}: {})", message, value) - } - VeilidAPIError::InvalidArgument { - context, - argument, - value, - } => { - write!( - f, - "VeilidAPIError::InvalidArgument({}: {} = {})", - context, argument, value - ) - } - VeilidAPIError::MissingArgument { context, argument } => { - write!( - f, - "VeilidAPIError::MissingArgument({}: {})", - context, argument - ) - } - VeilidAPIError::Generic { message } => { - write!(f, "VeilidAPIError::Generic({})", message) - } - } - } -} - -// fn convert_rpc_error(x: RPCError) -> VeilidAPIError { -// match x { -// RPCError::Timeout => VeilidAPIError::Timeout, -// RPCError::Unreachable(n) => VeilidAPIError::NodeNotFound { -// node_id: NodeId::new(n), -// }, -// RPCError::Unimplemented(s) => VeilidAPIError::Unimplemented { message: s }, -// RPCError::Internal(s) => VeilidAPIError::Internal { message: s }, -// RPCError::Protocol(s) => VeilidAPIError::Internal { message: s }, -// RPCError::InvalidFormat(s) => VeilidAPIError::Internal { -// message: format!("Invalid RPC format: {}", s), -// }, -// } -// } - -// macro_rules! map_rpc_error { -// () => { -// |x| convert_rpc_error(x) -// }; -// } - macro_rules! parse_error { ($msg:expr, $val:expr) => { VeilidAPIError::ParseError { diff --git a/veilid-core/src/xx/mod.rs b/veilid-core/src/xx/mod.rs index ec679466..434a926a 100644 --- a/veilid-core/src/xx/mod.rs +++ b/veilid-core/src/xx/mod.rs @@ -15,9 +15,12 @@ mod mutable_future; mod single_shot_eventual; mod split_url; mod tick_task; +mod timeout_or; mod tools; pub use cfg_if::*; +#[allow(unused_imports)] +pub use eyre::{bail, ensure, eyre, Report as EyreReport, Result as EyreResult, WrapErr}; pub use futures_util::future::{select, Either}; pub use futures_util::select; pub use futures_util::stream::FuturesUnordered; @@ -28,6 +31,7 @@ pub use parking_lot::*; pub use split_url::*; pub use static_assertions::*; pub use stop_token::*; +pub use thiserror::Error as ThisError; pub use tracing::*; pub type PinBox = Pin>; @@ -124,4 +128,5 @@ pub use mutable_future::*; // pub use single_future::*; pub use single_shot_eventual::*; pub use tick_task::*; +pub use timeout_or::*; pub use tools::*; diff --git a/veilid-core/src/xx/split_url.rs b/veilid-core/src/xx/split_url.rs index 22b516f5..076f7212 100644 --- a/veilid-core/src/xx/split_url.rs +++ b/veilid-core/src/xx/split_url.rs @@ -7,7 +7,7 @@ // URLs must convert to UTF8 // Only IP address and DNS hostname host fields are supported -use super::{IpAddr, Ipv4Addr, Ipv6Addr}; +use super::*; use alloc::borrow::ToOwned; use alloc::string::String; use alloc::vec::Vec; @@ -62,12 +62,14 @@ fn is_valid_scheme>(host: H) -> bool { true } -fn hex_decode(h: u8) -> Result { +fn hex_decode(h: u8) -> Result { match h { b'0'..=b'9' => Ok(h - b'0'), b'A'..=b'F' => Ok(h - b'A' + 10), b'a'..=b'f' => Ok(h - b'a' + 10), - _ => Err("Unexpected character in percent encoding".to_owned()), + _ => Err(SplitUrlError::new( + "Unexpected character in percent encoding", + )), } } @@ -88,10 +90,10 @@ fn hex_encode(c: u8) -> (char, char) { ) } -fn url_decode>(s: S) -> Result { +fn url_decode>(s: S) -> Result { let url = s.as_ref().to_owned(); if !url.is_ascii() { - return Err("URL is not in ASCII encoding".to_owned()); + return Err(SplitUrlError::new("URL is not in ASCII encoding")); } let url_bytes = url.as_bytes(); let mut dec_bytes: Vec = Vec::with_capacity(url_bytes.len()); @@ -102,14 +104,15 @@ fn url_decode>(s: S) -> Result { i += 1; if b == b'%' { if (i + 1) >= end { - return Err("Invalid URL encoding".to_owned()); + return Err(SplitUrlError::new("Invalid URL encoding")); } b = hex_decode(url_bytes[i])? << 4 | hex_decode(url_bytes[i + 1])?; i += 2; } dec_bytes.push(b); } - String::from_utf8(dec_bytes).map_err(|e| format!("Decoded URL is not valid UTF-8: {}", e)) + String::from_utf8(dec_bytes) + .map_err(|e| SplitUrlError::new(format!("Decoded URL is not valid UTF-8: {}", e))) } fn url_encode>(s: S, must_encode: impl Fn(u8) -> bool) -> String { @@ -128,14 +131,25 @@ fn url_encode>(s: S, must_encode: impl Fn(u8) -> bool) -> String { out } -fn convert_port(port_str: N) -> Result +fn convert_port(port_str: N) -> Result where N: AsRef, { port_str .as_ref() .parse::() - .map_err(|e| format!("Invalid port: {}", e)) + .map_err(|e| SplitUrlError::new(format!("Invalid port: {}", e))) +} + +/////////////////////////////////////////////////////////////////////////////// +#[derive(ThisError, Debug, Clone, Eq, PartialEq)] +#[error("SplitUrlError: {0}")] +pub struct SplitUrlError(String); + +impl SplitUrlError { + pub fn new(message: T) -> Self { + SplitUrlError(message.to_string()) + } } /////////////////////////////////////////////////////////////////////////////// @@ -163,7 +177,7 @@ impl SplitUrlPath { } impl FromStr for SplitUrlPath { - type Err = String; + type Err = SplitUrlError; fn from_str(s: &str) -> Result { Ok(if let Some((p, q)) = s.split_once('?') { if let Some((p, f)) = p.split_once('#') { @@ -213,17 +227,17 @@ pub enum SplitUrlHost { } impl SplitUrlHost { - pub fn new>(s: S) -> Result { + pub fn new>(s: S) -> Result { Self::from_str(s.as_ref()) } } impl FromStr for SplitUrlHost { - type Err = String; + type Err = SplitUrlError; fn from_str(s: &str) -> Result { if s.is_empty() { - return Err("Host is empty".to_owned()); + return Err(SplitUrlError::new("Host is empty")); } if let Ok(v4) = Ipv4Addr::from_str(s) { return Ok(SplitUrlHost::IpAddr(IpAddr::V4(v4))); @@ -232,13 +246,13 @@ impl FromStr for SplitUrlHost { if let Ok(v6) = Ipv6Addr::from_str(&s[1..s.len() - 1]) { return Ok(SplitUrlHost::IpAddr(IpAddr::V6(v6))); } - return Err("Invalid ipv6 address".to_owned()); + return Err(SplitUrlError::new("Invalid ipv6 address")); } for ch in s.chars() { if !matches!(ch, 'A'..='Z' | 'a'..='z' | '0'..='9' | '-' | '.' ) { - return Err("Invalid hostname".to_owned()); + return Err(SplitUrlError::new("Invalid hostname")); } } Ok(SplitUrlHost::Hostname(s.to_owned())) @@ -311,11 +325,11 @@ fn split_host_with_port(s: &str) -> Option<(&str, &str)> { } impl FromStr for SplitUrl { - type Err = String; + type Err = SplitUrlError; fn from_str(s: &str) -> Result { if let Some((scheme, mut rest)) = s.split_once("://") { if !is_valid_scheme(scheme) { - return Err("Invalid scheme specified".to_owned()); + return Err(SplitUrlError::new("Invalid scheme specified")); } let userinfo = { if let Some((userinfo_str, after)) = rest.split_once('@') { @@ -350,7 +364,7 @@ impl FromStr for SplitUrl { Ok(SplitUrl::new(scheme, userinfo, host, None, None)) } } else { - Err("No scheme specified".to_owned()) + Err(SplitUrlError::new("No scheme specified")) } } } diff --git a/veilid-core/src/xx/tick_task.rs b/veilid-core/src/xx/tick_task.rs index 339a11ff..1b8ed84d 100644 --- a/veilid-core/src/xx/tick_task.rs +++ b/veilid-core/src/xx/tick_task.rs @@ -5,26 +5,33 @@ use once_cell::sync::OnceCell; cfg_if! { if #[cfg(target_arch = "wasm32")] { - type TickTaskRoutine = - dyn Fn(StopToken, u64, u64) -> PinBoxFuture> + 'static; + type TickTaskRoutine = + dyn Fn(StopToken, u64, u64) -> PinBoxFuture> + 'static; } else { - type TickTaskRoutine = - dyn Fn(StopToken, u64, u64) -> SendPinBoxFuture> + Send + Sync + 'static; + type TickTaskRoutine = + dyn Fn(StopToken, u64, u64) -> SendPinBoxFuture> + Send + Sync + 'static; } } /// Runs a single-future background processing task, attempting to run it once every 'tick period' microseconds. /// If the prior tick is still running, it will allow it to finish, and do another tick when the timer comes around again. /// One should attempt to make tasks short-lived things that run in less than the tick period if you want things to happen with regular periodicity. -pub struct TickTask { +pub struct TickTask< + #[cfg(target_arch = "wasm32")] E: 'static, + #[cfg(not(target_arch = "wasm32"))] E: Send + 'static, +> { last_timestamp_us: AtomicU64, tick_period_us: u64, - routine: OnceCell>, + routine: OnceCell>>, stop_source: AsyncMutex>, - single_future: MustJoinSingleFuture>, + single_future: MustJoinSingleFuture>, } -impl TickTask { +impl< + #[cfg(target_arch = "wasm32")] E: 'static, + #[cfg(not(target_arch = "wasm32"))] E: Send + 'static, + > TickTask +{ pub fn new_us(tick_period_us: u64) -> Self { Self { last_timestamp_us: AtomicU64::new(0), @@ -53,25 +60,14 @@ impl TickTask { } } - cfg_if! { - if #[cfg(target_arch = "wasm32")] { - pub fn set_routine( - &self, - routine: impl Fn(StopToken, u64, u64) -> PinBoxFuture> + 'static, - ) { - self.routine.set(Box::new(routine)).map_err(drop).unwrap(); - } - } else { - pub fn set_routine( - &self, - routine: impl Fn(StopToken, u64, u64) -> SendPinBoxFuture> + Send + Sync + 'static, - ) { - self.routine.set(Box::new(routine)).map_err(drop).unwrap(); - } - } + pub fn set_routine( + &self, + routine: impl Fn(StopToken, u64, u64) -> SendPinBoxFuture> + Send + Sync + 'static, + ) { + self.routine.set(Box::new(routine)).map_err(drop).unwrap(); } - pub async fn stop(&self) -> Result<(), String> { + pub async fn stop(&self) -> Result<(), E> { // drop the stop source if we have one let opt_stop_source = &mut *self.stop_source.lock().await; if opt_stop_source.is_none() { @@ -89,7 +85,7 @@ impl TickTask { } } - pub async fn tick(&self) -> Result<(), String> { + pub async fn tick(&self) -> Result<(), E> { let now = intf::get_timestamp(); let last_timestamp_us = self.last_timestamp_us.load(Ordering::Acquire); diff --git a/veilid-core/src/xx/timeout_or.rs b/veilid-core/src/xx/timeout_or.rs new file mode 100644 index 00000000..b433824d --- /dev/null +++ b/veilid-core/src/xx/timeout_or.rs @@ -0,0 +1,98 @@ +use super::*; +use cfg_if::*; +use core::fmt::{Debug, Display}; +use core::result::Result; +use std::error::Error; +use std::io; + +#[derive(ThisError, Debug, Clone, Copy, Eq, PartialEq)] +#[error("Timeout")] +pub struct TimeoutError(); + +impl TimeoutError { + pub fn to_io(self) -> io::Error { + io::Error::new(io::ErrorKind::TimedOut, self) + } +} + +cfg_if! { + if #[cfg(feature="rt-async-std")] { + impl From for TimeoutError { + fn from(_: async_std::future::TimeoutError) -> Self { + Self() + } + } + } else if #[cfg(feature="rt-tokio")] { + impl From for TimeoutError { + fn from(_: tokio::time::error::Elapsed) -> Self { + Self() + } + } + } +} + +////////////////////////////////////////////////////////////////// + +pub enum TimeoutOr { + Timeout, + Value(T), +} + +impl TimeoutOr { + pub fn timeout() -> Self { + Self::Timeout + } + pub fn value(value: T) -> Self { + Self::Value(value) + } + + pub fn is_timeout(&self) -> bool { + matches!(self, Self::Timeout) + } + + pub fn is_value(&self) -> bool { + matches!(self, Self::Value(_)) + } + + pub fn ok(self) -> Result { + match self { + Self::Timeout => Err(TimeoutError {}), + Self::Value(v) => Ok(v), + } + } +} + +impl From> for Option { + fn from(t: TimeoutOr) -> Self { + match t { + TimeoutOr::::Timeout => None, + TimeoutOr::::Value(v) => Some(v), + } + } +} + +impl Clone for TimeoutOr { + fn clone(&self) -> Self { + match self { + Self::Timeout => Self::Timeout, + Self::Value(t) => Self::Value(t.clone()), + } + } +} +impl Debug for TimeoutOr { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::Timeout => write!(f, "Timeout"), + Self::Value(arg0) => f.debug_tuple("Value").field(arg0).finish(), + } + } +} +impl Display for TimeoutOr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Timeout => write!(f, ""), + Self::Value(arg0) => write!(f, "{}", arg0), + } + } +} +impl Error for TimeoutOr {} diff --git a/veilid-core/src/xx/tools.rs b/veilid-core/src/xx/tools.rs index 8a267020..c1f12266 100644 --- a/veilid-core/src/xx/tools.rs +++ b/veilid-core/src/xx/tools.rs @@ -1,5 +1,6 @@ use crate::xx::*; use alloc::string::ToString; +use std::io; use std::path::Path; #[macro_export] @@ -11,6 +12,24 @@ macro_rules! assert_err { }; } +#[macro_export] +macro_rules! io_error_other { + ($msg:expr) => { + io::Error::new(io::ErrorKind::Other, $msg.to_string()) + }; +} + +pub fn to_io_error_other(x: E) -> io::Error { + io::Error::new(io::ErrorKind::Other, x) +} + +#[macro_export] +macro_rules! bail_io_error_other { + ($msg:expr) => { + return io::Result::Err(io::Error::new(io::ErrorKind::Other, $msg.to_string())) + }; +} + pub fn split_port(name: &str) -> Result<(String, Option), String> { if let Some(split) = name.rfind(':') { let hoststr = &name[0..split]; @@ -129,7 +148,7 @@ where } } -pub fn listen_address_to_socket_addrs(listen_address: &str) -> Result, String> { +pub fn listen_address_to_socket_addrs(listen_address: &str) -> EyreResult> { // If no address is specified, but the port is, use ipv4 and ipv6 unspecified // If the address is specified, only use the specified port and fail otherwise let ip_addrs = vec![ @@ -138,12 +157,9 @@ pub fn listen_address_to_socket_addrs(listen_address: &str) -> Result().map_err(|_| { - format!( - "Invalid port format in udp listen address: {}", - listen_address - ) - })?; + let port = portstr + .parse::() + .wrap_err("Invalid port format in udp listen address")?; ip_addrs.iter().map(|a| SocketAddr::new(*a, port)).collect() } else if let Ok(port) = listen_address.parse::() { ip_addrs.iter().map(|a| SocketAddr::new(*a, port)).collect() @@ -151,11 +167,11 @@ pub fn listen_address_to_socket_addrs(listen_address: &str) -> Result>(path: P) -> Result<(), String> + pub fn ensure_file_private_owner>(path: P) -> EyreResult<()> { let path = path.as_ref(); if !path.exists() { @@ -194,13 +210,13 @@ cfg_if::cfg_if! { let uid = Uid::effective(); let gid = Gid::effective(); - let meta = std::fs::metadata(path).map_err(|e| format!("unable to get metadata for path '{:?}': {}",path, e))?; + let meta = std::fs::metadata(path).wrap_err("unable to get metadata for path")?; if meta.mode() != 0o600 { - std::fs::set_permissions(path,std::fs::Permissions::from_mode(0o600)).map_err(|e| format!("unable to set correct permissions on path '{:?}': {}", path, e))?; + std::fs::set_permissions(path,std::fs::Permissions::from_mode(0o600)).wrap_err("unable to set correct permissions on path")?; } if meta.uid() != uid.as_raw() || meta.gid() != gid.as_raw() { - return Err(format!("path has incorrect owner/group: {:?}", path)); + bail!("path has incorrect owner/group"); } Ok(()) } @@ -208,24 +224,13 @@ cfg_if::cfg_if! { //use std::os::windows::fs::MetadataExt; //use windows_permissions::*; - pub fn ensure_file_private_owner>(path: P) -> Result<(),String> + pub fn ensure_file_private_owner>(path: P) -> EyreResult<()> { let path = path.as_ref(); if !path.exists() { return Ok(()); } - // let uid = Uid::effective(); - // let gid = Gid::effective(); - //let meta = std::fs::metadata(path).map_err(|e| format!("unable to get metadata for path '{:?}': {}",path, e))?; - - //if meta.mode() != 0o600 { - // std::fs::set_permissions(path,std::fs::Permissions::from_mode(0o600)).map_err(|e| format!("unable to set correct permissions on path '{:?}': {}", path, e))?; - //} - - //if meta.uid() != uid.as_raw() || meta.gid() != gid.as_raw() { - // chown(path, Some(uid), Some(gid)).map_err(|e| format!("unable to set correct owner on path '{:?}': {}", path, e))?; - //} Ok(()) } } else { diff --git a/veilid-flutter/rust/src/tools.rs b/veilid-flutter/rust/src/tools.rs index ccac253b..a42f10d0 100644 --- a/veilid-flutter/rust/src/tools.rs +++ b/veilid-flutter/rust/src/tools.rs @@ -5,7 +5,7 @@ cfg_if! { if #[cfg(feature="rt-async-std")] { pub use async_std::task::JoinHandle; pub use async_std::net::TcpStream; - pub use async_std::future::TimeoutError; + //pub use async_std::future::TimeoutError; pub use async_std::sync::Mutex as AsyncMutex; pub fn spawn + Send + 'static, T: Send + 'static>(f: F) -> JoinHandle { @@ -17,7 +17,7 @@ cfg_if! { } else if #[cfg(feature="rt-tokio")] { pub use tokio::task::JoinHandle; pub use tokio::net::TcpStream; - pub use tokio::time::error::Elapsed as TimeoutError; + //pub use tokio::time::error::Elapsed as TimeoutError; pub use tokio::sync::Mutex as AsyncMutex; pub fn spawn + Send + 'static, T: Send + 'static>(f: F) -> JoinHandle { GLOBAL_RUNTIME.spawn(f) diff --git a/veilid-server/src/settings.rs b/veilid-server/src/settings.rs index 5ede034c..c101ed06 100644 --- a/veilid-server/src/settings.rs +++ b/veilid-server/src/settings.rs @@ -1,7 +1,5 @@ #![allow(clippy::bool_assert_comparison)] -use crate::*; - use directories::*; use parking_lot::*; diff --git a/veilid-server/src/tools.rs b/veilid-server/src/tools.rs index 6793d342..0e7b51e3 100644 --- a/veilid-server/src/tools.rs +++ b/veilid-server/src/tools.rs @@ -26,7 +26,7 @@ cfg_if! { pub use tokio::net::TcpListener; //pub use tokio::net::TcpStream; //pub use tokio_util::compat::*; - pub use tokio::time::error::Elapsed as TimeoutError; + //pub use tokio::time::error::Elapsed as TimeoutError; pub fn spawn + Send + 'static, T: Send + 'static>(f: F) -> JoinHandle { tokio::task::spawn(f) }