From 5552d9af12be738c66d50e3385edf41104c2b7aa Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 12:33:07 +0200 Subject: [PATCH 01/58] refactor: convert iroh-base to n0-error --- Cargo.lock | 79 ++++++++++++++++++++++++++++++++++++-- iroh-base/Cargo.toml | 6 +-- iroh-base/src/key.rs | 32 +++++++-------- iroh-base/src/relay_url.rs | 17 ++++---- iroh-base/src/ticket.rs | 32 ++++++--------- 5 files changed, 113 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 075589ee87f..8047c611320 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -915,6 +915,41 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.106", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.106", +] + [[package]] name = "dashmap" version = "6.1.0" @@ -2081,6 +2116,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "1.1.0" @@ -2291,8 +2332,7 @@ dependencies = [ "data-encoding", "derive_more 2.0.1", "ed25519-dalek", - "n0-snafu", - "nested_enum_utils", + "n0-error", "postcard", "proptest", "rand 0.9.2", @@ -2301,7 +2341,6 @@ dependencies = [ "serde", "serde_json", "serde_test", - "snafu", "url", "zeroize", "zeroize_derive", @@ -2787,6 +2826,29 @@ dependencies = [ "uuid", ] +[[package]] +name = "n0-error" +version = "0.1.0" +source = "git+https://github.com/n0-computer/n0-error#5e50fb8cbf50d98808ffc276850d2756a2c42f00" +dependencies = [ + "anyhow", + "derive_more 2.0.1", + "n0-error-macros", + "spez", +] + +[[package]] +name = "n0-error-macros" +version = "0.1.0" +source = "git+https://github.com/n0-computer/n0-error#5e50fb8cbf50d98808ffc276850d2756a2c42f00" +dependencies = [ + "darling", + "heck", + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "n0-future" version = "0.1.3" @@ -4517,6 +4579,17 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "spez" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c87e960f4dca2788eeb86bbdde8dd246be8948790b7618d656e68f9b720a86e8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "spin" version = "0.9.8" diff --git a/iroh-base/Cargo.toml b/iroh-base/Cargo.toml index e3e01416575..4ea900d4514 100644 --- a/iroh-base/Cargo.toml +++ b/iroh-base/Cargo.toml @@ -23,9 +23,7 @@ url = { version = "2.5.3", features = ["serde"], optional = true } postcard = { version = "1", default-features = false, features = ["alloc", "use-std", "experimental-derive"], optional = true } rand_core = { version = "0.9.3", optional = true } serde = { version = "1", features = ["derive", "rc"] } -snafu = { version = "0.8.5", features = ["rust_1_81"], optional = true } -n0-snafu = "0.2.2" -nested_enum_utils = "0.2.0" +n0-error = { git = "https://github.com/n0-computer/n0-error" } zeroize = { version = "1.8.2", optional = true, features = ["derive"] } zeroize_derive = { version = "1.4.2", optional = true } # needed for minimal versions @@ -46,7 +44,6 @@ key = [ "dep:ed25519-dalek", "dep:url", "dep:derive_more", - "dep:snafu", "dep:data-encoding", "dep:rand_core", "dep:zeroize", @@ -56,7 +53,6 @@ key = [ relay = [ "dep:url", "dep:derive_more", - "dep:snafu", ] [package.metadata.docs.rs] diff --git a/iroh-base/src/key.rs b/iroh-base/src/key.rs index 58739020fad..691ec877c73 100644 --- a/iroh-base/src/key.rs +++ b/iroh-base/src/key.rs @@ -11,10 +11,9 @@ use std::{ use curve25519_dalek::edwards::CompressedEdwardsY; use ed25519_dalek::{SigningKey, VerifyingKey}; -use nested_enum_utils::common_fields; +use n0_error::{Err, Error, add_meta, e}; use rand_core::CryptoRng; use serde::{Deserialize, Serialize}; -use snafu::{Backtrace, Snafu}; /// A public key. /// @@ -128,7 +127,7 @@ impl PublicKey { pub fn verify(&self, message: &[u8], signature: &Signature) -> Result<(), SignatureError> { self.as_verifying_key() .verify_strict(message, &signature.0) - .map_err(|_| SignatureSnafu.build()) + .map_err(|_| e!(SignatureError)) } /// Convert to a hex string limited to the first 5 bytes for a friendly string @@ -204,25 +203,21 @@ impl Display for PublicKey { } /// Error when deserialising a [`PublicKey`] or a [`SecretKey`]. -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] -#[derive(Snafu, Debug)] +#[add_meta] +#[derive(Error)] +#[error(from_sources, std_sources)] #[allow(missing_docs)] -#[snafu(visibility(pub(crate)))] pub enum KeyParsingError { /// Error when decoding. - #[snafu(transparent)] + #[error(transparent)] Decode { source: data_encoding::DecodeError }, /// Error when decoding the public key. - #[snafu(transparent)] + #[error(transparent)] Key { source: ed25519_dalek::SignatureError, }, /// The encoded information had the wrong length. - #[snafu(display("invalid length"))] + #[display("invalid length")] DecodeInvalidLength {}, } @@ -370,9 +365,10 @@ impl Signature { } /// Verification of a signature failed. -#[derive(Debug, Snafu)] -#[snafu(display("Invalid signature"))] -pub struct SignatureError; +#[add_meta] +#[derive(Error)] +#[display("Invalid signature")] +pub struct SignatureError {} fn decode_base32_hex(s: &str) -> Result<[u8; 32], KeyParsingError> { let mut bytes = [0u8; 32]; @@ -384,14 +380,14 @@ fn decode_base32_hex(s: &str) -> Result<[u8; 32], KeyParsingError> { let input = s.to_ascii_uppercase(); let input = input.as_bytes(); if data_encoding::BASE32_NOPAD.decode_len(input.len())? != bytes.len() { - return Err(DecodeInvalidLengthSnafu.build()); + return Err!(KeyParsingError::DecodeInvalidLength); } data_encoding::BASE32_NOPAD.decode_mut(input, &mut bytes) }; match res { Ok(len) => { if len != PublicKey::LENGTH { - return Err(DecodeInvalidLengthSnafu.build()); + return Err!(KeyParsingError::DecodeInvalidLength); } } Err(partial) => return Err(partial.error.into()), diff --git a/iroh-base/src/relay_url.rs b/iroh-base/src/relay_url.rs index b1aef365282..f7139494c99 100644 --- a/iroh-base/src/relay_url.rs +++ b/iroh-base/src/relay_url.rs @@ -1,7 +1,7 @@ use std::{fmt, ops::Deref, str::FromStr, sync::Arc}; +use n0_error::{Error, add_meta}; use serde::{Deserialize, Serialize}; -use snafu::{Backtrace, ResultExt, Snafu}; use url::Url; /// A URL identifying a relay server. @@ -39,11 +39,14 @@ impl From for RelayUrl { } /// Can occur when parsing a string into a [`RelayUrl`]. -#[derive(Debug, Snafu)] -#[snafu(display("Failed to parse"))] -pub struct RelayUrlParseError { - source: url::ParseError, - backtrace: Option, +#[add_meta] +#[derive(Error)] +#[error(from_sources, std_sources)] +#[allow(missing_docs)] +pub enum RelayUrlParseError { + /// Parsing the URL failed. + #[display("Failed to parse")] + Parse { source: url::ParseError }, } /// Support for parsing strings directly. @@ -54,7 +57,7 @@ impl FromStr for RelayUrl { type Err = RelayUrlParseError; fn from_str(s: &str) -> Result { - let inner = Url::from_str(s).context(RelayUrlParseSnafu)?; + let inner = Url::from_str(s)?; Ok(RelayUrl::from(inner)) } } diff --git a/iroh-base/src/ticket.rs b/iroh-base/src/ticket.rs index 58cc3571f75..fcdd33441d3 100644 --- a/iroh-base/src/ticket.rs +++ b/iroh-base/src/ticket.rs @@ -5,9 +5,8 @@ use std::{collections::BTreeSet, net::SocketAddr}; -use nested_enum_utils::common_fields; +use n0_error::{Error, add_meta, e}; use serde::{Deserialize, Serialize}; -use snafu::{Backtrace, Snafu}; use crate::{key::EndpointId, relay_url::RelayUrl}; @@ -50,7 +49,7 @@ pub trait Ticket: Sized { fn deserialize(str: &str) -> Result { let expected = Self::KIND; let Some(rest) = str.strip_prefix(expected) else { - return Err(KindSnafu { expected }.build()); + return Err(ParseError::wrong_prefix(expected)); }; let bytes = data_encoding::BASE32_NOPAD.decode(rest.to_ascii_uppercase().as_bytes())?; let ticket = Self::from_bytes(&bytes)?; @@ -59,30 +58,23 @@ pub trait Ticket: Sized { } /// An error deserializing an iroh ticket. -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] +#[error(from_sources, std_sources)] #[allow(missing_docs)] -#[snafu(visibility(pub(crate)))] #[non_exhaustive] pub enum ParseError { /// Found a ticket with the wrong prefix, indicating the wrong kind. - #[snafu(display("wrong prefix, expected {expected}"))] - Kind { - /// The expected prefix. - expected: &'static str, - }, + #[display("wrong prefix, expected {expected}")] + Kind { expected: &'static str }, /// This looks like a ticket, but postcard deserialization failed. - #[snafu(transparent)] + #[error(transparent)] Postcard { source: postcard::Error }, /// This looks like a ticket, but base32 decoding failed. - #[snafu(transparent)] + #[error(transparent)] Encoding { source: data_encoding::DecodeError }, /// Verification of the deserialized bytes failed. - #[snafu(display("verification failed: {message}"))] + #[display("verification failed: {message}")] Verify { message: &'static str }, } @@ -92,13 +84,13 @@ impl ParseError { /// /// Indicate the expected prefix. pub fn wrong_prefix(expected: &'static str) -> Self { - KindSnafu { expected }.build() + e!(ParseError::Kind { expected }) } /// Return a `ParseError` variant that indicates verification of the /// deserialized bytes failed. pub fn verification_failed(message: &'static str) -> Self { - VerifySnafu { message }.build() + e!(ParseError::Verify { message }) } } From 93fb21cb6e2da894a93b0a36592c0932c5e95205 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 12:36:10 +0200 Subject: [PATCH 02/58] fixup --- iroh-base/src/ticket.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/iroh-base/src/ticket.rs b/iroh-base/src/ticket.rs index fcdd33441d3..2fac5c8c4d2 100644 --- a/iroh-base/src/ticket.rs +++ b/iroh-base/src/ticket.rs @@ -83,12 +83,14 @@ impl ParseError { /// prefix. /// /// Indicate the expected prefix. + #[track_caller] pub fn wrong_prefix(expected: &'static str) -> Self { e!(ParseError::Kind { expected }) } /// Return a `ParseError` variant that indicates verification of the /// deserialized bytes failed. + #[track_caller] pub fn verification_failed(message: &'static str) -> Self { e!(ParseError::Verify { message }) } From 82f4bbd7e966f7c09fc1cacb1687863a081c8552 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 13:34:49 +0200 Subject: [PATCH 03/58] refactor: convert iroh-relay --- Cargo.lock | 5 +- iroh-relay/Cargo.toml | 4 +- iroh-relay/src/client.rs | 107 +++++++--------- iroh-relay/src/client/conn.rs | 35 +++--- iroh-relay/src/client/tls.rs | 42 +++---- iroh-relay/src/dns.rs | 157 ++++++++++-------------- iroh-relay/src/endpoint_info.rs | 115 +++++++----------- iroh-relay/src/main.rs | 35 +++--- iroh-relay/src/protos/common.rs | 27 ++--- iroh-relay/src/protos/handshake.rs | 105 +++++++--------- iroh-relay/src/protos/relay.rs | 86 ++++++------- iroh-relay/src/quic.rs | 75 +++++------- iroh-relay/src/server.rs | 73 +++++------ iroh-relay/src/server/client.rs | 174 +++++++++++---------------- iroh-relay/src/server/clients.rs | 10 +- iroh-relay/src/server/http_server.rs | 165 +++++++++---------------- iroh-relay/src/server/streams.rs | 42 +++---- iroh/Cargo.toml | 1 + 18 files changed, 501 insertions(+), 757 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8047c611320..a1a4492bf81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2281,6 +2281,7 @@ dependencies = [ "iroh-quinn-proto", "iroh-quinn-udp", "iroh-relay", + "n0-error", "n0-future 0.3.0", "n0-snafu", "n0-watcher", @@ -2532,9 +2533,8 @@ dependencies = [ "iroh-quinn", "iroh-quinn-proto", "lru 0.16.1", + "n0-error", "n0-future 0.3.0", - "n0-snafu", - "nested_enum_utils", "num_enum", "pin-project", "pkarr", @@ -2557,7 +2557,6 @@ dependencies = [ "serde_json", "sha1", "simdutf8", - "snafu", "strum", "time", "tokio", diff --git a/iroh-relay/Cargo.toml b/iroh-relay/Cargo.toml index d9a5399092b..5dc241c073f 100644 --- a/iroh-relay/Cargo.toml +++ b/iroh-relay/Cargo.toml @@ -71,9 +71,7 @@ webpki_types = { package = "rustls-pki-types", version = "1.12" } data-encoding = "2.6.0" lru = "0.16" z32 = "1.0.3" -snafu = { version = "0.8.5", features = ["rust_1_81"] } -n0-snafu = "0.2.2" -nested_enum_utils = "0.2.0" +n0-error = { git = "https://github.com/n0-computer/n0-error" } # server feature clap = { version = "4", features = ["derive"], optional = true } diff --git a/iroh-relay/src/client.rs b/iroh-relay/src/client.rs index e398b2fa401..11d734f8a2f 100644 --- a/iroh-relay/src/client.rs +++ b/iroh-relay/src/client.rs @@ -16,8 +16,7 @@ use n0_future::{ split::{SplitSink, SplitStream, split}, time, }; -use nested_enum_utils::common_fields; -use snafu::{Backtrace, Snafu}; +use n0_error::{add_meta, Error, e, Err}; #[cfg(any(test, feature = "test-utils"))] use tracing::warn; use tracing::{Level, debug, event, trace}; @@ -47,75 +46,71 @@ mod util; /// /// `ConnectError` contains `DialError`, errors that can occur while dialing the /// relay, as well as errors that occur while creating or maintaining a connection. -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] +#[add_meta] +#[derive(Error)] +#[error(from_sources)] #[allow(missing_docs)] -#[derive(Debug, Snafu)] #[non_exhaustive] pub enum ConnectError { - #[snafu(display("Invalid URL for websocket: {url}"))] + #[display("Invalid URL for websocket: {url}")] InvalidWebsocketUrl { url: Url }, - #[snafu(display("Invalid relay URL: {url}"))] + #[display("Invalid relay URL: {url}")] InvalidRelayUrl { url: Url }, - #[snafu(transparent)] + #[error(transparent)] Websocket { #[cfg(not(wasm_browser))] + #[error(std_err)] source: tokio_websockets::Error, #[cfg(wasm_browser)] + #[error(std_err)] source: ws_stream_wasm::WsErr, }, - #[snafu(transparent)] - Handshake { source: handshake::Error }, - #[snafu(transparent)] + #[error(transparent)] + Handshake { #[error(std_err)] source: handshake::Error }, + #[error(transparent)] Dial { source: DialError }, - #[snafu(display("Unexpected status during upgrade: {code}"))] + #[display("Unexpected status during upgrade: {code}")] UnexpectedUpgradeStatus { code: hyper::StatusCode }, - #[snafu(display("Failed to upgrade response"))] - Upgrade { source: hyper::Error }, - #[snafu(display("Invalid TLS servername"))] + #[display("Failed to upgrade response")] + Upgrade { #[error(std_err)] source: hyper::Error }, + #[display("Invalid TLS servername")] InvalidTlsServername {}, - #[snafu(display("No local address available"))] + #[display("No local address available")] NoLocalAddr {}, - #[snafu(display("tls connection failed"))] - Tls { source: std::io::Error }, + #[display("tls connection failed")] + Tls { #[error(std_err)] source: std::io::Error }, #[cfg(wasm_browser)] - #[snafu(display("The relay protocol is not available in browsers"))] + #[display("The relay protocol is not available in browsers")] RelayProtoNotAvailable {}, } /// Errors that can occur while dialing the relay server. -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] +#[add_meta] +#[derive(Error)] +#[error(from_sources)] #[allow(missing_docs)] -#[derive(Debug, Snafu)] #[non_exhaustive] pub enum DialError { - #[snafu(display("Invliad target port"))] + #[display("Invliad target port")] InvalidTargetPort {}, - #[snafu(transparent)] + #[error(transparent)] #[cfg(not(wasm_browser))] - Dns { source: DnsError }, - #[snafu(transparent)] - Timeout { source: time::Elapsed }, - #[snafu(transparent)] - Io { source: std::io::Error }, - #[snafu(display("Invalid URL: {url}"))] + Dns { #[error(std_err)] source: DnsError }, + #[error(transparent)] + Timeout { #[error(std_err)] source: time::Elapsed }, + #[error(transparent)] + Io { #[error(std_err)] source: std::io::Error }, + #[display("Invalid URL: {url}")] InvalidUrl { url: Url }, - #[snafu(display("Failed proxy connection: {status}"))] + #[display("Failed proxy connection: {status}")] ProxyConnectInvalidStatus { status: hyper::StatusCode }, - #[snafu(display("Invalid Proxy URL {proxy_url}"))] + #[display("Invalid Proxy URL {proxy_url}")] ProxyInvalidUrl { proxy_url: Url }, - #[snafu(display("failed to establish proxy connection"))] - ProxyConnect { source: hyper::Error }, - #[snafu(display("Invalid proxy TLS servername: {proxy_hostname}"))] + #[display("failed to establish proxy connection")] + ProxyConnect { #[error(std_err)] source: hyper::Error }, + #[display("Invalid proxy TLS servername: {proxy_hostname}")] ProxyInvalidTlsServername { proxy_hostname: String }, - #[snafu(display("Invalid proxy target port"))] + #[display("Invalid proxy target port")] ProxyInvalidTargetPort {}, } @@ -219,12 +214,7 @@ impl ClientBuilder { "ws" => "ws", _ => "wss", }) - .map_err(|_| { - InvalidWebsocketUrlSnafu { - url: dial_url.clone(), - } - .build() - })?; + .map_err(|_| e!(ConnectError::InvalidWebsocketUrl { url: dial_url.clone() }))?; debug!(%dial_url, "Dialing relay by websocket"); @@ -242,15 +232,10 @@ impl ClientBuilder { let local_addr = stream .as_ref() .local_addr() - .map_err(|_| NoLocalAddrSnafu.build())?; + .map_err(|_| e!(ConnectError::NoLocalAddr))?; let mut builder = tokio_websockets::ClientBuilder::new() .uri(dial_url.as_str()) - .map_err(|_| { - InvalidRelayUrlSnafu { - url: dial_url.clone(), - } - .build() - })? + .map_err(|_| e!(ConnectError::InvalidRelayUrl { url: dial_url.clone() }))? .add_header( SEC_WEBSOCKET_PROTOCOL, http::HeaderValue::from_static(RELAY_PROTOCOL_VERSION), @@ -272,10 +257,7 @@ impl ClientBuilder { let (conn, response) = builder.connect_on(stream).await?; if response.status() != hyper::StatusCode::SWITCHING_PROTOCOLS { - UnexpectedUpgradeStatusSnafu { - code: response.status(), - } - .fail()?; + return Err!(ConnectError::UnexpectedUpgradeStatus { code: response.status() }); } let conn = Conn::new(conn, self.key_cache.clone(), &self.secret_key).await?; @@ -322,12 +304,7 @@ impl ClientBuilder { "ws" => "ws", _ => "wss", }) - .map_err(|_| { - InvalidWebsocketUrlSnafu { - url: dial_url.clone(), - } - .build() - })?; + .map_err(|_| e!(ConnectError::InvalidWebsocketUrl { url: dial_url.clone() }))?; debug!(%dial_url, "Dialing relay by websocket"); diff --git a/iroh-relay/src/client/conn.rs b/iroh-relay/src/client/conn.rs index 7a76bcff21a..6d5d76eb75a 100644 --- a/iroh-relay/src/client/conn.rs +++ b/iroh-relay/src/client/conn.rs @@ -9,8 +9,7 @@ use std::{ use iroh_base::SecretKey; use n0_future::{Sink, Stream}; -use nested_enum_utils::common_fields; -use snafu::{Backtrace, Snafu}; +use n0_error::{add_meta, Error}; use tracing::debug; use super::KeyCache; @@ -26,41 +25,35 @@ use crate::{ }; /// Error for sending messages to the relay server. -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] +#[add_meta] +#[derive(Error)] +#[error(from_sources, std_sources)] #[allow(missing_docs)] -#[derive(Debug, Snafu)] #[non_exhaustive] pub enum SendError { - #[snafu(transparent)] + #[error(transparent)] StreamError { #[cfg(not(wasm_browser))] source: tokio_websockets::Error, #[cfg(wasm_browser)] source: ws_stream_wasm::WsErr, }, - #[snafu(display("Exceeds max packet size ({MAX_PACKET_SIZE}): {size}"))] + #[display("Exceeds max packet size ({MAX_PACKET_SIZE}): {size}")] ExceedsMaxPacketSize { size: usize }, - #[snafu(display("Attempted to send empty packet"))] + #[display("Attempted to send empty packet")] EmptyPacket {}, } /// Errors when receiving messages from the relay server. -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] +#[add_meta] +#[derive(Error)] +#[error(from_sources, std_sources)] #[allow(missing_docs)] -#[derive(Debug, Snafu)] #[non_exhaustive] pub enum RecvError { - #[snafu(transparent)] + #[error(transparent)] Protocol { source: ProtoError }, - #[snafu(transparent)] + #[error(transparent)] StreamError { #[cfg(not(wasm_browser))] source: tokio_websockets::Error, @@ -146,9 +139,9 @@ impl Sink for Conn { fn start_send(mut self: Pin<&mut Self>, frame: ClientToRelayMsg) -> Result<(), Self::Error> { let size = frame.encoded_len(); - snafu::ensure!(size <= MAX_PACKET_SIZE, ExceedsMaxPacketSizeSnafu { size }); + n0_error::ensure!(size <= MAX_PACKET_SIZE, n0_error::e!(SendError::ExceedsMaxPacketSize { size })); if let ClientToRelayMsg::Datagrams { datagrams, .. } = &frame { - snafu::ensure!(!datagrams.contents.is_empty(), EmptyPacketSnafu); + n0_error::ensure!(!datagrams.contents.is_empty(), n0_error::e!(SendError::EmptyPacket)); } Pin::new(&mut self.conn) diff --git a/iroh-relay/src/client/tls.rs b/iroh-relay/src/client/tls.rs index ba62e9cc28a..084718c4ce5 100644 --- a/iroh-relay/src/client/tls.rs +++ b/iroh-relay/src/client/tls.rs @@ -12,7 +12,7 @@ use http_body_util::Empty; use hyper::{Request, upgrade::Parts}; use n0_future::{task, time}; use rustls::client::Resumption; -use snafu::{OptionExt, ResultExt}; +use n0_error::{e, Err}; use tracing::error; use super::{ @@ -84,7 +84,7 @@ impl MaybeTlsStreamBuilder { let local_addr = tcp_stream .local_addr() - .map_err(|_| NoLocalAddrSnafu.build())?; + .map_err(|_| e!(ConnectError::NoLocalAddr))?; debug!(server_addr = ?tcp_stream.peer_addr(), %local_addr, "TCP stream connected"); @@ -92,13 +92,13 @@ impl MaybeTlsStreamBuilder { debug!("Starting TLS handshake"); let hostname = self .tls_servername() - .ok_or_else(|| InvalidTlsServernameSnafu.build())?; + .ok_or_else(|| e!(ConnectError::InvalidTlsServername))?; let hostname = hostname.to_owned(); let tls_stream = tls_connector .connect(hostname, tcp_stream) .await - .context(TlsSnafu)?; + .map_err(|err| e!(ConnectError::Tls, err))?; debug!("tls_connector connect success"); Ok(MaybeTlsStream::Tls(tls_stream)) } else { @@ -144,14 +144,14 @@ impl MaybeTlsStreamBuilder { .resolve_host(&self.url, self.prefer_ipv6, DNS_TIMEOUT) .await?; - let port = url_port(&self.url).context(InvalidTargetPortSnafu)?; + let port = url_port(&self.url).ok_or_else(|| e!(DialError::InvalidTargetPort))?; let addr = SocketAddr::new(dst_ip, port); debug!("connecting to {}", addr); let tcp_stream = time::timeout(DIAL_ENDPOINT_TIMEOUT, async move { TcpStream::connect(addr).await }) - .await??; + .await.map_err(|err| e!(DialError::Timeout, err))??; tcp_stream.set_nodelay(true)?; @@ -174,7 +174,7 @@ impl MaybeTlsStreamBuilder { .resolve_host(&proxy_url, self.prefer_ipv6, DNS_TIMEOUT) .await?; - let proxy_port = url_port(&proxy_url).context(ProxyInvalidTargetPortSnafu)?; + let proxy_port = url_port(&proxy_url).ok_or_else(|| e!(DialError::ProxyInvalidTargetPort))?; let proxy_addr = SocketAddr::new(proxy_ip, proxy_port); debug!(%proxy_addr, "connecting to proxy"); @@ -190,26 +190,17 @@ impl MaybeTlsStreamBuilder { let io = if proxy_url.scheme() == "http" { MaybeTlsStream::Raw(tcp_stream) } else { - let hostname = proxy_url.host_str().context(ProxyInvalidUrlSnafu { - proxy_url: proxy_url.clone(), - })?; + let hostname = proxy_url.host_str().ok_or_else(|| e!(DialError::ProxyInvalidUrl { proxy_url: proxy_url.clone() }))?; let hostname = - rustls::pki_types::ServerName::try_from(hostname.to_string()).map_err(|_| { - ProxyInvalidTlsServernameSnafu { - proxy_hostname: hostname.to_string(), - } - .build() - })?; + rustls::pki_types::ServerName::try_from(hostname.to_string()).map_err(|_| e!(DialError::ProxyInvalidTlsServername { proxy_hostname: hostname.to_string() }))?; let tls_stream = tls_connector.connect(hostname, tcp_stream).await?; MaybeTlsStream::Tls(tls_stream) }; let io = TokioIo::new(io); - let target_host = self.url.host_str().context(InvalidUrlSnafu { - url: self.url.clone(), - })?; + let target_host = self.url.host_str().ok_or_else(|| e!(DialError::InvalidUrl { url: self.url.clone() }))?; - let port = url_port(&self.url).context(InvalidTargetPortSnafu)?; + let port = url_port(&self.url).ok_or_else(|| e!(DialError::InvalidTargetPort))?; // Establish Proxy Tunnel let mut req_builder = Request::builder() @@ -240,22 +231,19 @@ impl MaybeTlsStreamBuilder { let (mut sender, conn) = hyper::client::conn::http1::handshake(io) .await - .context(ProxyConnectSnafu)?; + .map_err(|err| e!(DialError::ProxyConnect, err))?; task::spawn(async move { if let Err(err) = conn.with_upgrades().await { error!("Proxy connection failed: {:?}", err); } }); - let res = sender.send_request(req).await.context(ProxyConnectSnafu)?; + let res = sender.send_request(req).await.map_err(|err| e!(DialError::ProxyConnect, err))?; if !res.status().is_success() { - return Err(ProxyConnectInvalidStatusSnafu { - status: res.status(), - } - .build()); + return Err!(DialError::ProxyConnectInvalidStatus { status: res.status() }); } - let upgraded = hyper::upgrade::on(res).await.context(ProxyConnectSnafu)?; + let upgraded = hyper::upgrade::on(res).await.map_err(|err| e!(DialError::ProxyConnect, err))?; let Parts { io, read_buf, .. } = upgraded .downcast::>>() .expect("only this upgrade used"); diff --git a/iroh-relay/src/dns.rs b/iroh-relay/src/dns.rs index d9bdfd13505..ece0c0f04e0 100644 --- a/iroh-relay/src/dns.rs +++ b/iroh-relay/src/dns.rs @@ -18,8 +18,7 @@ use n0_future::{ boxed::BoxFuture, time::{self, Duration}, }; -use nested_enum_utils::common_fields; -use snafu::{Backtrace, GenerateImplicitData, OptionExt, ResultExt, Snafu}; +use n0_error::{add_meta, Error, e}; use tokio::sync::RwLock; use tracing::debug; use url::Url; @@ -62,80 +61,56 @@ pub trait Resolver: fmt::Debug + Send + Sync + 'static { pub type BoxIter = Box + Send + 'static>; /// Potential errors related to dns. -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] #[allow(missing_docs)] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] +#[error(from_sources, std_sources)] #[non_exhaustive] -#[snafu(visibility(pub(crate)))] pub enum DnsError { - #[snafu(transparent)] - Timeout { source: tokio::time::error::Elapsed }, - #[snafu(display("No response"))] + #[error(transparent)] + Timeout { #[error(std_err)] source: tokio::time::error::Elapsed }, + #[display("No response")] NoResponse {}, - #[snafu(display("Resolve failed ipv4: {ipv4}, ipv6 {ipv6}"))] - ResolveBoth { - ipv4: Box, - ipv6: Box, - }, - #[snafu(display("missing host"))] + #[display("Resolve failed ipv4: {ipv4}, ipv6 {ipv6}")] + ResolveBoth { ipv4: Box, ipv6: Box }, + #[display("missing host")] MissingHost {}, - #[snafu(transparent)] - Resolve { - source: hickory_resolver::ResolveError, - }, - #[snafu(display("invalid DNS response: not a query for _iroh.z32encodedpubkey"))] + #[error(transparent)] + Resolve { #[error(std_err)] source: hickory_resolver::ResolveError }, + #[display("invalid DNS response: not a query for _iroh.z32encodedpubkey")] InvalidResponse {}, } #[cfg(not(wasm_browser))] -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] #[allow(missing_docs)] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] -#[snafu(visibility(pub(crate)))] pub enum LookupError { - #[snafu(display("Malformed txt from lookup"))] - ParseError { - #[snafu(source(from(ParseError, Box::new)))] - source: Box, - }, - #[snafu(display("Failed to resolve TXT record"))] - LookupFailed { - #[snafu(source(from(DnsError, Box::new)))] - source: Box, - }, + #[display("Malformed txt from lookup")] + ParseError { #[error(std_err)] source: Box }, + #[display("Failed to resolve TXT record")] + LookupFailed { source: DnsError }, } /// Error returned when an input value is too long for [`crate::endpoint_info::UserData`]. -#[allow(missing_docs)] -#[derive(Debug, Snafu)] -#[snafu(module)] -#[snafu(display("no calls succeeded: [{}]", errors.iter().map(|e| e.to_string()).collect::>().join("")))] -pub struct StaggeredError { - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - errors: Vec, +#[add_meta] +#[derive(Error)] +pub struct DnsStaggeredError { + #[display("no calls succeeded: [{}]", errors.iter().map(|e| e.to_string()).collect::>().join(""))] + errors: Vec, } -impl StaggeredError { - pub(crate) fn new(errors: Vec) -> Self { - Self { - errors, - backtrace: GenerateImplicitData::generate(), - span_trace: n0_snafu::SpanTrace::generate(), - } - } +/// Aggregates all the lookup errors when all staggered attempts fail. +#[add_meta] +#[derive(Error)] +pub struct LookupStaggeredError { + #[display("no calls succeeded: [{}]", errors.iter().map(|e| e.to_string()).collect::>().join(""))] + errors: Vec, } +// no manual new; use e!(Type { errors }) + /// Builder for [`DnsResolver`]. #[derive(Debug, Clone, Default)] pub struct Builder { @@ -267,7 +242,9 @@ impl DnsResolver { timeout: Duration, ) -> Result, DnsError> { let host = host.to_string(); - let res = time::timeout(timeout, self.0.lookup_txt(host)).await??; + let res = time::timeout(timeout, self.0.lookup_txt(host)) + .await + .map_err(|err| e!(DnsError::Timeout, err))??; Ok(res) } @@ -278,7 +255,9 @@ impl DnsResolver { timeout: Duration, ) -> Result + use, DnsError> { let host = host.to_string(); - let addrs = time::timeout(timeout, self.0.lookup_ipv4(host)).await??; + let addrs = time::timeout(timeout, self.0.lookup_ipv4(host)) + .await + .map_err(|err| e!(DnsError::Timeout, err))??; Ok(addrs.into_iter().map(IpAddr::V4)) } @@ -289,7 +268,9 @@ impl DnsResolver { timeout: Duration, ) -> Result + use, DnsError> { let host = host.to_string(); - let addrs = time::timeout(timeout, self.0.lookup_ipv6(host)).await??; + let addrs = time::timeout(timeout, self.0.lookup_ipv6(host)) + .await + .map_err(|err| e!(DnsError::Timeout, err))??; Ok(addrs.into_iter().map(IpAddr::V6)) } @@ -313,11 +294,7 @@ impl DnsResolver { (Ok(ipv4), Ok(ipv6)) => Ok(LookupIter::Both(ipv4.chain(ipv6))), (Ok(ipv4), Err(_)) => Ok(LookupIter::Ipv4(ipv4)), (Err(_), Ok(ipv6)) => Ok(LookupIter::Ipv6(ipv6)), - (Err(ipv4_err), Err(ipv6_err)) => Err(ResolveBothSnafu { - ipv4: Box::new(ipv4_err), - ipv6: Box::new(ipv6_err), - } - .build()), + (Err(ipv4_err), Err(ipv6_err)) => Err(e!(DnsError::ResolveBoth { ipv4: Box::new(ipv4_err), ipv6: Box::new(ipv6_err) })), } } @@ -328,7 +305,7 @@ impl DnsResolver { prefer_ipv6: bool, timeout: Duration, ) -> Result { - let host = url.host().context(MissingHostSnafu)?; + let host = url.host().ok_or_else(|| e!(DnsError::MissingHost))?; match host { url::Host::Domain(domain) => { // Need to do a DNS lookup @@ -338,20 +315,16 @@ impl DnsResolver { ); let (v4, v6) = match lookup { (Err(ipv4_err), Err(ipv6_err)) => { - return Err(ResolveBothSnafu { - ipv4: Box::new(ipv4_err), - ipv6: Box::new(ipv6_err), - } - .build()); + return Err(e!(DnsError::ResolveBoth { ipv4: Box::new(ipv4_err), ipv6: Box::new(ipv6_err) })); } (Err(_), Ok(mut v6)) => (None, v6.next()), (Ok(mut v4), Err(_)) => (v4.next(), None), (Ok(mut v4), Ok(mut v6)) => (v4.next(), v6.next()), }; if prefer_ipv6 { - v6.or(v4).context(NoResponseSnafu) + v6.or(v4).ok_or_else(|| e!(DnsError::NoResponse)) } else { - v4.or(v6).context(NoResponseSnafu) + v4.or(v6).ok_or_else(|| e!(DnsError::NoResponse)) } } url::Host::Ipv4(ip) => Ok(IpAddr::V4(ip)), @@ -370,10 +343,10 @@ impl DnsResolver { host: impl ToString, timeout: Duration, delays_ms: &[u64], - ) -> Result, StaggeredError> { + ) -> Result, DnsStaggeredError> { let host = host.to_string(); let f = || self.lookup_ipv4(host.clone(), timeout); - stagger_call(f, delays_ms).await + stagger_call(f, delays_ms).await.map_err(|errors| e!(DnsStaggeredError { errors })) } /// Performs an IPv6 lookup with a timeout in a staggered fashion. @@ -387,10 +360,10 @@ impl DnsResolver { host: impl ToString, timeout: Duration, delays_ms: &[u64], - ) -> Result, StaggeredError> { + ) -> Result, DnsStaggeredError> { let host = host.to_string(); let f = || self.lookup_ipv6(host.clone(), timeout); - stagger_call(f, delays_ms).await + stagger_call(f, delays_ms).await.map_err(|errors| e!(DnsStaggeredError { errors })) } /// Races an IPv4 and IPv6 lookup with a timeout in a staggered fashion. @@ -405,10 +378,10 @@ impl DnsResolver { host: impl ToString, timeout: Duration, delays_ms: &[u64], - ) -> Result, StaggeredError> { + ) -> Result, DnsStaggeredError> { let host = host.to_string(); let f = || self.lookup_ipv4_ipv6(host.clone(), timeout); - stagger_call(f, delays_ms).await + stagger_call(f, delays_ms).await.map_err(|errors| e!(DnsStaggeredError { errors })) } /// Looks up endpoint info by [`EndpointId`] and origin domain name. @@ -425,8 +398,9 @@ impl DnsResolver { let lookup = self .lookup_txt(name.clone(), DNS_TIMEOUT) .await - .context(LookupFailedSnafu)?; - let info = EndpointInfo::from_txt_lookup(name, lookup).context(ParseSnafu)?; + .map_err(|err| e!(LookupError::LookupFailed { source: err }))?; + let info = EndpointInfo::from_txt_lookup(name, lookup) + .map_err(|err| e!(LookupError::ParseError { source: Box::new(err) }))?; Ok(info) } @@ -439,8 +413,9 @@ impl DnsResolver { let lookup = self .lookup_txt(name.clone(), DNS_TIMEOUT) .await - .context(LookupFailedSnafu)?; - let info = EndpointInfo::from_txt_lookup(name, lookup).context(ParseSnafu)?; + .map_err(|err| e!(LookupError::LookupFailed { source: err }))?; + let info = EndpointInfo::from_txt_lookup(name, lookup) + .map_err(|err| e!(LookupError::ParseError { source: Box::new(err) }))?; Ok(info) } @@ -454,9 +429,9 @@ impl DnsResolver { &self, name: &str, delays_ms: &[u64], - ) -> Result> { + ) -> Result { let f = || self.lookup_endpoint_by_domain_name(name); - stagger_call(f, delays_ms).await + stagger_call(f, delays_ms).await.map_err(|errors| e!(LookupStaggeredError { errors })) } /// Looks up endpoint info by [`EndpointId`] and origin domain name. @@ -470,9 +445,9 @@ impl DnsResolver { endpoint_id: &EndpointId, origin: &str, delays_ms: &[u64], - ) -> Result> { + ) -> Result { let f = || self.lookup_endpoint_by_id(endpoint_id, origin); - stagger_call(f, delays_ms).await + stagger_call(f, delays_ms).await.map_err(|errors| e!(LookupStaggeredError { errors })) } } @@ -771,7 +746,7 @@ async fn stagger_call< >( f: F, delays_ms: &[u64], -) -> Result> { +) -> Result> { let mut calls = n0_future::FuturesUnorderedBounded::new(delays_ms.len() + 1); // NOTE: we add the 0 delay here to have a uniform set of futures. This is more performant than // using alternatives that allow futures of different types. @@ -793,7 +768,7 @@ async fn stagger_call< } } - Err(StaggeredError::new(errors)) + Err(errors) } fn add_jitter(delay: &u64) -> Duration { @@ -826,7 +801,7 @@ pub(crate) mod tests { let r_pos = DONE_CALL.fetch_add(1, std::sync::atomic::Ordering::Relaxed); async move { tracing::info!(r_pos, "call"); - CALL_RESULTS[r_pos].map_err(|_| InvalidResponseSnafu.build()) + CALL_RESULTS[r_pos].map_err(|_| e!(DnsError::InvalidResponse)) } }; @@ -872,7 +847,7 @@ pub(crate) mod tests { let addr = if host == "foo.example" { Ipv4Addr::new(1, 1, 1, 1) } else { - return Err(NoResponseSnafu.build()); + return Err(e!(DnsError::NoResponse)); }; let iter: BoxIter = Box::new(vec![addr].into_iter()); Ok(iter) diff --git a/iroh-relay/src/endpoint_info.rs b/iroh-relay/src/endpoint_info.rs index 1e6b2c59cdd..7dd23e1b1ec 100644 --- a/iroh-relay/src/endpoint_info.rs +++ b/iroh-relay/src/endpoint_info.rs @@ -41,50 +41,35 @@ use std::{ }; use iroh_base::{EndpointAddr, EndpointId, KeyParsingError, RelayUrl, SecretKey}; -use nested_enum_utils::common_fields; -use snafu::{Backtrace, ResultExt, Snafu}; +use n0_error::{add_meta, Error, e}; +use n0_error::StdResultExt; use url::Url; /// The DNS name for the iroh TXT record. pub const IROH_TXT_NAME: &str = "_iroh"; -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] #[allow(missing_docs)] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] -#[snafu(visibility(pub(crate)))] pub enum EncodingError { - #[snafu(transparent)] - FailedBuildingPacket { - source: pkarr::errors::SignedPacketBuildError, - }, - #[snafu(display("invalid TXT entry"))] - InvalidTxtEntry { source: pkarr::dns::SimpleDnsError }, + #[error(transparent)] + FailedBuildingPacket { #[error(std_err)] source: pkarr::errors::SignedPacketBuildError }, + #[display("invalid TXT entry")] + InvalidTxtEntry { #[error(std_err)] source: pkarr::dns::SimpleDnsError }, } -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] #[allow(missing_docs)] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] -#[snafu(visibility(pub(crate)))] pub enum DecodingError { - #[snafu(display("endpoint id was not encoded in valid z32"))] - InvalidEncodingZ32 { source: z32::Z32Error }, - #[snafu(display("length must be 32 bytes, but got {len} byte(s)"))] + #[display("endpoint id was not encoded in valid z32")] + InvalidEncodingZ32 { #[error(std_err)] source: z32::Z32Error }, + #[display("length must be 32 bytes, but got {len} byte(s)")] InvalidLength { len: usize }, - #[snafu(display("endpoint id is not a valid public key"))] - InvalidKey { - #[snafu(source(from(KeyParsingError, Box::new)))] - source: Box, - }, + #[display("endpoint id is not a valid public key")] + InvalidKey { source: KeyParsingError }, } /// Extension methods for [`EndpointId`] to encode to and decode from [`z32`], @@ -107,11 +92,12 @@ impl EndpointIdExt for EndpointId { } fn from_z32(s: &str) -> Result { - let bytes = z32::decode(s.as_bytes()).context(InvalidEncodingZ32Snafu)?; + let bytes = z32::decode(s.as_bytes()).map_err(|err| e!(DecodingError::InvalidEncodingZ32, err))?; let bytes: &[u8; 32] = &bytes .try_into() - .map_err(|_| InvalidLengthSnafu { len: s.len() }.build())?; - let endpoint_id = EndpointId::from_bytes(bytes).context(InvalidKeySnafu)?; + .map_err(|_| e!(DecodingError::InvalidLength { len: s.len() }))?; + let endpoint_id = EndpointId::from_bytes(bytes) + .map_err(|err| e!(DecodingError::InvalidKey { source: err }))?; Ok(endpoint_id) } } @@ -230,18 +216,16 @@ impl UserData { /// Error returned when an input value is too long for [`UserData`]. #[allow(missing_docs)] -#[derive(Debug, Snafu)] -pub struct MaxLengthExceededError { - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -} +#[add_meta] +#[derive(Error)] +#[display("max length exceeded")] +pub struct MaxLengthExceededError {} impl TryFrom for UserData { type Error = MaxLengthExceededError; fn try_from(value: String) -> Result { - snafu::ensure!(value.len() <= Self::MAX_LENGTH, MaxLengthExceededSnafu); + n0_error::ensure!(value.len() <= Self::MAX_LENGTH, e!(MaxLengthExceededError)); Ok(Self(value)) } } @@ -250,7 +234,7 @@ impl FromStr for UserData { type Err = MaxLengthExceededError; fn from_str(s: &str) -> std::result::Result { - snafu::ensure!(s.len() <= Self::MAX_LENGTH, MaxLengthExceededSnafu); + n0_error::ensure!(s.len() <= Self::MAX_LENGTH, e!(MaxLengthExceededError)); Ok(Self(s.to_string())) } } @@ -413,31 +397,24 @@ impl EndpointInfo { } } -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] #[allow(missing_docs)] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] +#[error(from_sources)] #[non_exhaustive] -#[snafu(visibility(pub(crate)))] pub enum ParseError { - #[snafu(display("Expected format `key=value`, received `{s}`"))] + #[display("Expected format `key=value`, received `{s}`")] UnexpectedFormat { s: String }, - #[snafu(display("Could not convert key to Attr"))] + #[display("Could not convert key to Attr")] AttrFromString { key: String }, - #[snafu(display("Expected 2 labels, received {num_labels}"))] + #[display("Expected 2 labels, received {num_labels}")] NumLabels { num_labels: usize }, - #[snafu(display("Could not parse labels"))] - Utf8 { source: Utf8Error }, - #[snafu(display("Record is not an `iroh` record, expected `_iroh`, got `{label}`"))] + #[display("Could not parse labels")] + Utf8 { #[error(std_err)] source: Utf8Error }, + #[display("Record is not an `iroh` record, expected `_iroh`, got `{label}`")] NotAnIrohRecord { label: String }, - #[snafu(transparent)] - DecodingError { - #[snafu(source(from(DecodingError, Box::new)))] - source: Box, - }, + #[error(transparent)] + DecodingError { source: DecodingError }, } impl std::ops::Deref for EndpointInfo { @@ -462,12 +439,12 @@ impl std::ops::DerefMut for EndpointInfo { fn endpoint_id_from_txt_name(name: &str) -> Result { let num_labels = name.split(".").count(); if num_labels < 2 { - return Err(NumLabelsSnafu { num_labels }.build()); + return Err(e!(ParseError::NumLabels { num_labels })); } let mut labels = name.split("."); let label = labels.next().expect("checked above"); if label != IROH_TXT_NAME { - return Err(NotAnIrohRecordSnafu { label }.build()); + return Err(e!(ParseError::NotAnIrohRecord { label: label.to_string() })); } let label = labels.next().expect("checked above"); let endpoint_id = EndpointId::from_z32(label)?; @@ -539,9 +516,9 @@ impl TxtAttrs { for s in strings { let mut parts = s.split('='); let (Some(key), Some(value)) = (parts.next(), parts.next()) else { - return Err(UnexpectedFormatSnafu { s }.build()); + return Err(e!(ParseError::UnexpectedFormat { s })); }; - let attr = T::from_str(key).map_err(|_| AttrFromStringSnafu { key }.build())?; + let attr = T::from_str(key).map_err(|_| e!(ParseError::AttrFromString { key: key.to_string() }))?; attrs.entry(attr).or_default().push(value.to_string()); } Ok(Self { attrs, endpoint_id }) @@ -617,10 +594,10 @@ impl TxtAttrs { let mut builder = pkarr::SignedPacket::builder(); for s in self.to_txt_strings() { let mut txt = rdata::TXT::new(); - txt.add_string(&s).context(InvalidTxtEntrySnafu)?; + txt.add_string(&s).map_err(|err| e!(EncodingError::InvalidTxtEntry, err))?; builder = builder.txt(name.clone(), txt.into_owned(), ttl); } - let signed_packet = builder.build(&keypair)?; + let signed_packet = builder.build(&keypair).map_err(|err| e!(EncodingError::FailedBuildingPacket, err))?; Ok(signed_packet) } } @@ -656,7 +633,7 @@ mod tests { }, }; use iroh_base::{EndpointId, SecretKey}; - use n0_snafu::{Result, ResultExt}; + use n0_error::{Result, StdResultExt}; use super::{EndpointData, EndpointIdExt, EndpointInfo}; use crate::dns::TxtRecordData; @@ -703,7 +680,7 @@ mod tests { let name = Name::from_utf8( "_iroh.dgjpkxyn3zyrk3zfads5duwdgbqpkwbjxfj4yt7rezidr3fijccy.dns.iroh.link.", ) - .context("dns name")?; + .std_context("dns name")?; let query = Query::query(name.clone(), RecordType::TXT); let records = [ Record::from_rdata( @@ -728,7 +705,7 @@ mod tests { )? .to_z32() )) - .context("name")?, + .std_context("name")?, 30, RData::TXT(TXT::new(vec![ "relay=https://euw1-1.relay.iroh.network./".to_string(), @@ -736,7 +713,7 @@ mod tests { ), // Test a record with a completely different name Record::from_rdata( - Name::from_utf8("dns.iroh.link.").context("name")?, + Name::from_utf8("dns.iroh.link.").std_context("name")?, 30, RData::TXT(TXT::new(vec![ "relay=https://euw1-1.relay.iroh.network./".to_string(), diff --git a/iroh-relay/src/main.rs b/iroh-relay/src/main.rs index ef68a6e855d..af917fa72a8 100644 --- a/iroh-relay/src/main.rs +++ b/iroh-relay/src/main.rs @@ -19,10 +19,9 @@ use iroh_relay::{ }, server::{self as relay, ClientRateLimit, QuicConfig}, }; +use n0_error::{AnyError as Error, Result, StdResultExt, whatever}; use n0_future::FutureExt; -use n0_snafu::{Error, Result, ResultExt}; use serde::{Deserialize, Serialize}; -use snafu::whatever; use tokio_rustls_acme::{AcmeConfig, caches::DirCache}; use tracing::{debug, warn}; use tracing_subscriber::{EnvFilter, prelude::*}; @@ -62,11 +61,11 @@ enum CertMode { fn load_certs( filename: impl AsRef, ) -> Result>> { - let certfile = std::fs::File::open(filename).context("cannot open certificate file")?; + let certfile = std::fs::File::open(filename).std_context("cannot open certificate file")?; let mut reader = std::io::BufReader::new(certfile); let certs: Result, std::io::Error> = rustls_pemfile::certs(&mut reader).collect(); - let certs = certs.context("reading cert")?; + let certs = certs.std_context("reading cert")?; Ok(certs) } @@ -76,11 +75,11 @@ fn load_secret_key( ) -> Result> { let filename = filename.as_ref(); let keyfile = std::fs::File::open(filename) - .with_context(|| format!("cannot open secret key file {}", filename.display()))?; + .std_context(format!("cannot open secret key file {}", filename.display()))?; let mut reader = std::io::BufReader::new(keyfile); loop { - match rustls_pemfile::read_one(&mut reader).context("cannot parse secret key .pem file")? { + match rustls_pemfile::read_one(&mut reader).std_context("cannot parse secret key .pem file")? { Some(rustls_pemfile::Item::Pkcs1Key(key)) => { return Ok(rustls::pki_types::PrivateKeyDer::Pkcs1(key)); } @@ -292,12 +291,12 @@ async fn http_access_check_inner( match request.send().await { Err(err) => { warn!("Failed to retrieve response for HTTP access check: {err:#}"); - Err(err).context("Failed to fetch response") + Err(err).std_context("Failed to fetch response") } Ok(res) if res.status() == StatusCode::OK => match res.text().await { Ok(text) if text == "true" => Ok(()), Ok(_) => whatever!("Invalid response text (must be 'true')"), - Err(err) => Err(err).context("Failed to read response"), + Err(err) => Err(err).std_context("Failed to read response"), }, Ok(res) => whatever!("Received invalid status code ({})", res.status()), } @@ -499,7 +498,7 @@ impl Config { } fn from_str(config: &str) -> Result { - toml::from_str(config).context("config must be valid toml") + toml::from_str(config).std_context("config must be valid toml") } async fn read_from_file(path: impl AsRef) -> Result { @@ -508,7 +507,7 @@ impl Config { } let config_ser = tokio::fs::read_to_string(&path) .await - .context("unable to read config")?; + .std_context("unable to read config")?; Self::from_str(&config_ser) } } @@ -575,21 +574,21 @@ async fn maybe_load_tls( Ok::<_, Error>((key, certs)) }) .await - .context("join")??; + .std_context("join")??; let server_config = server_config .with_single_cert(certs.clone(), private_key) - .context("tls config")?; + .std_context("tls config")?; (relay::CertConfig::Manual { certs }, server_config) } CertMode::LetsEncrypt => { let hostname = tls .hostname .clone() - .context("LetsEncrypt needs a hostname")?; + .std_context("LetsEncrypt needs a hostname")?; let contact = tls .contact .clone() - .context("LetsEncrypt needs a contact email")?; + .std_context("LetsEncrypt needs a contact email")?; let config = AcmeConfig::new(vec![hostname.clone()]) .contact([format!("mailto:{contact}")]) .cache_option(Some(DirCache::new(tls.cert_dir()))) @@ -631,7 +630,7 @@ async fn maybe_load_tls( let resolver = Arc::new( relay::ReloadingResolver::init(loader, interval) .await - .context("cert loading")?, + .std_context("cert loading")?, ); let server_config = server_config.with_cert_resolver(resolver); (relay::CertConfig::Reloading, server_config) @@ -676,12 +675,12 @@ async fn build_relay_config(cfg: Config) -> Result Some(ClientRateLimit { bytes_per_second: TryInto::::try_into(bps) - .context("bytes_per_second must be non-zero u32")?, + .std_context("bytes_per_second must be non-zero u32")?, max_burst_bytes: rx .max_burst_bytes .map(|v| { TryInto::::try_into(v) - .context("max_burst_bytes must be non-zero u32") + .std_context("max_burst_bytes must be non-zero u32") }) .transpose()?, }), @@ -725,7 +724,7 @@ mod tests { use std::num::NonZeroU32; use iroh_base::SecretKey; - use n0_snafu::Result; + use n0_error::Result; use rand::SeedableRng; use rand_chacha::ChaCha8Rng; diff --git a/iroh-relay/src/protos/common.rs b/iroh-relay/src/protos/common.rs index 2434d112d1e..64f2fed4d1b 100644 --- a/iroh-relay/src/protos/common.rs +++ b/iroh-relay/src/protos/common.rs @@ -4,9 +4,8 @@ //! integers for different frames. use bytes::{Buf, BufMut}; -use nested_enum_utils::common_fields; -use quinn_proto::{VarInt, coding::Codec}; -use snafu::{Backtrace, OptionExt, Snafu}; +use quinn_proto::{VarInt, coding::{Codec, UnexpectedEnd}}; +use n0_error::{add_meta, Error, e}; /// Possible frame types during handshaking #[repr(u32)] @@ -53,18 +52,14 @@ pub enum FrameType { Restarting = 12, } -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] +#[add_meta] +#[derive(Error)] #[allow(missing_docs)] -#[derive(Debug, Snafu)] #[non_exhaustive] pub enum FrameTypeError { - #[snafu(display("not enough bytes to parse frame type"))] - UnexpectedEnd {}, - #[snafu(display("frame type unknown"))] + #[display("not enough bytes to parse frame type")] + UnexpectedEnd { #[error(std_err)] source: UnexpectedEnd }, + #[display("frame type unknown")] UnknownFrameType { tag: VarInt }, } @@ -93,13 +88,11 @@ impl FrameType { /// Parses the frame type (as a QUIC-encoded varint) from the first couple of bytes given /// and returns the frame type and the rest. pub(crate) fn from_bytes(buf: &mut impl Buf) -> Result { - let tag = VarInt::decode(buf).ok().context(UnexpectedEndSnafu)?; + let tag = VarInt::decode(buf).map_err(|err| e!(FrameTypeError::UnexpectedEnd, err))?; let tag_u32 = u32::try_from(u64::from(tag)) - .ok() - .context(UnknownFrameTypeSnafu { tag })?; + .map_err(|_| e!(FrameTypeError::UnknownFrameType { tag }))?; let frame_type = FrameType::try_from(tag_u32) - .ok() - .context(UnknownFrameTypeSnafu { tag })?; + .map_err(|_| e!(FrameTypeError::UnknownFrameType { tag }))?; Ok(frame_type) } } diff --git a/iroh-relay/src/protos/handshake.rs b/iroh-relay/src/protos/handshake.rs index 315ba197219..8266f188e9a 100644 --- a/iroh-relay/src/protos/handshake.rs +++ b/iroh-relay/src/protos/handshake.rs @@ -32,10 +32,10 @@ use http::HeaderValue; use iroh_base::Signature; use iroh_base::{PublicKey, SecretKey}; use n0_future::{SinkExt, TryStreamExt}; -use nested_enum_utils::common_fields; +use n0_error::{add_meta, Error, e, Err}; #[cfg(feature = "server")] use rand::CryptoRng; -use snafu::{Backtrace, ResultExt, Snafu}; + use tracing::trace; use super::{ @@ -133,36 +133,35 @@ impl Frame for ServerDeniesAuth { const TAG: FrameType = FrameType::ServerDeniesAuth; } -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] +#[add_meta] +#[derive(Error)] #[allow(missing_docs)] -#[derive(Debug, Snafu)] #[non_exhaustive] pub enum Error { - #[snafu(transparent)] + #[error(transparent)] Websocket { #[cfg(not(wasm_browser))] + #[error(std_err)] source: tokio_websockets::Error, #[cfg(wasm_browser)] + #[error(std_err)] source: ws_stream_wasm::WsErr, }, - #[snafu(display("Handshake stream ended prematurely"))] + #[display("Handshake stream ended prematurely")] UnexpectedEnd {}, - #[snafu(transparent)] + #[error(transparent)] FrameTypeError { source: FrameTypeError }, - #[snafu(display("The relay denied our authentication ({reason})"))] + #[display("The relay denied our authentication ({reason})")] ServerDeniedAuth { reason: String }, - #[snafu(display("Unexpected tag, got {frame_type:?}, but expected one of {expected_types:?}"))] + #[display("Unexpected tag, got {frame_type:?}, but expected one of {expected_types:?}")] UnexpectedFrameType { frame_type: FrameType, expected_types: Vec, }, - #[snafu(display("Handshake failed while deserializing {frame_type:?} frame"))] + #[display("Handshake failed while deserializing {frame_type:?} frame")] DeserializationError { frame_type: FrameType, + #[error(std_err)] source: postcard::Error, }, #[cfg(feature = "server")] @@ -171,20 +170,21 @@ pub enum Error { } #[cfg(feature = "server")] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] pub(crate) enum VerificationError { - #[snafu(display("Couldn't export TLS keying material on our end"))] + #[display("Couldn't export TLS keying material on our end")] NoKeyingMaterial, - #[snafu(display( + #[display( "Client didn't extract the same keying material, the suffix mismatched: expected {expected:X?} but got {actual:X?}" - ))] + )] MismatchedSuffix { expected: [u8; 16], actual: [u8; 16], }, - #[snafu(display( + #[display( "Client signature {signature:X?} for message {message:X?} invalid for public key {public_key}" - ))] + )] SignatureInvalid { source: iroh_base::SignatureError, message: Vec, @@ -231,11 +231,7 @@ impl ClientAuth { let message = challenge.message_to_sign(); self.public_key .verify(&message, &Signature::from_bytes(&self.signature)) - .with_context(|_| SignatureInvalidSnafu { - message: message.to_vec(), - signature: self.signature, - public_key: self.public_key, - }) + .map_err(|err| e!(VerificationError::SignatureInvalid { source: err, message: message.to_vec(), signature: self.signature, public_key: self.public_key })) .map_err(Box::new) } } @@ -282,15 +278,13 @@ impl KeyMaterialClientAuth { &self, io: &impl ExportKeyingMaterial, ) -> Result<(), Box> { - use snafu::OptionExt; - let key_material = io .export_keying_material( [0u8; 32], DOMAIN_SEP_TLS_EXPORT_LABEL, Some(self.public_key.as_bytes()), ) - .context(NoKeyingMaterialSnafu)?; + .ok_or_else(|| e!(VerificationError::NoKeyingMaterial))?; // We split the export and only sign the first 16 bytes, and // pass through the last 16 bytes. // Passing on the suffix helps the verifying end figure out what @@ -301,23 +295,16 @@ impl KeyMaterialClientAuth { // there must be something wrong with the client's secret key or signature. let (message, suffix) = key_material.split_at(16); let suffix: [u8; 16] = suffix.try_into().expect("hardcoded length"); - snafu::ensure!( + n0_error::ensure!( suffix == self.key_material_suffix, - MismatchedSuffixSnafu { - expected: self.key_material_suffix, - actual: suffix - } + e!(VerificationError::MismatchedSuffix { expected: self.key_material_suffix, actual: suffix }) ); // NOTE: We don't blake3-hash here as we do it in [`ServerChallenge::message_to_sign`], // because we already have a domain separation string and keyed hashing step in // the TLS export keying material above. self.public_key .verify(message, &Signature::from_bytes(&self.signature)) - .with_context(|_| SignatureInvalidSnafu { - message: message.to_vec(), - public_key: self.public_key, - signature: self.signature, - }) + .map_err(|err| e!(VerificationError::SignatureInvalid { source: err, message: message.to_vec(), public_key: self.public_key, signature: self.signature })) .map_err(Box::new) } } @@ -353,10 +340,7 @@ pub(crate) async fn clientside( } FrameType::ServerDeniesAuth => { let denial: ServerDeniesAuth = deserialize_frame(frame)?; - Err(ServerDeniedAuthSnafu { - reason: denial.reason, - } - .build()) + Err!(Error::ServerDeniedAuth { reason: denial.reason }) } _ => unreachable!(), } @@ -444,10 +428,7 @@ pub(crate) async fn serverside( reason: "signature invalid".into(), }; write_frame(io, denial.clone()).await?; - ServerDeniedAuthSnafu { - reason: denial.reason, - } - .fail() + Err!(Error::ServerDeniedAuth { reason: denial.reason }) } else { trace!(?client_auth.public_key, "authentication succeeded via challenge"); Ok(SuccessfulAuthentication { @@ -474,10 +455,7 @@ impl SuccessfulAuthentication { reason: "not authorized".into(), }; write_frame(io, denial.clone()).await?; - ServerDeniedAuthSnafu { - reason: denial.reason, - } - .fail() + Err!(Error::ServerDeniedAuth { reason: denial.reason }) } } } @@ -493,8 +471,8 @@ async fn write_frame( .expect("serialization failed") // buffer can't become "full" without being a critical failure, datastructures shouldn't ever fail serialization .into_inner() .freeze(); - io.send(bytes).await?; - io.flush().await?; + io.send(bytes).await.map_err(|err| e!(Error::Websocket, err))?; + io.flush().await.map_err(|err| e!(Error::Websocket, err))?; Ok(()) } @@ -504,32 +482,31 @@ async fn read_frame( ) -> Result<(FrameType, Bytes), Error> { let mut payload = io .try_next() - .await? - .ok_or_else(|| UnexpectedEndSnafu.build())?; + .await + .map_err(|err| e!(Error::Websocket, err))? + .ok_or_else(|| e!(Error::UnexpectedEnd))?; - let frame_type = FrameType::from_bytes(&mut payload)?; + let frame_type = FrameType::from_bytes(&mut payload) + .map_err(|err| e!(Error::FrameTypeError, err))?; trace!(?frame_type, "Reading frame"); - snafu::ensure!( + n0_error::ensure!( expected_types.contains(&frame_type), - UnexpectedFrameTypeSnafu { - frame_type, - expected_types: expected_types.to_vec() - } + e!(Error::UnexpectedFrameType { frame_type, expected_types: expected_types.to_vec() }) ); Ok((frame_type, payload)) } fn deserialize_frame(frame: Bytes) -> Result { - postcard::from_bytes(&frame).context(DeserializationSnafu { frame_type: F::TAG }) + postcard::from_bytes(&frame).map_err(|err| e!(Error::DeserializationError { frame_type: F::TAG, source: err })) } #[cfg(all(test, feature = "server"))] mod tests { use bytes::BytesMut; use iroh_base::{PublicKey, SecretKey}; + use n0_error::{Result, StdResultExt}; use n0_future::{Sink, SinkExt, Stream, TryStreamExt}; - use n0_snafu::{Result, ResultExt}; use rand::SeedableRng; use tokio_util::codec::{Framed, LengthDelimitedCodec}; use tracing::{Instrument, info_span}; @@ -643,13 +620,13 @@ mod tests { async { super::clientside(&mut client_io, secret_key) .await - .context("clientside") + .std_context("clientside") } .instrument(info_span!("clientside")), async { let auth_n = super::serverside(&mut server_io, client_auth_header) .await - .context("serverside")?; + .std_context("serverside")?; let mechanism = auth_n.mechanism; let is_authorized = restricted_to.is_none_or(|key| key == auth_n.client_key); let key = auth_n.authorize_if(is_authorized, &mut server_io).await?; diff --git a/iroh-relay/src/protos/relay.rs b/iroh-relay/src/protos/relay.rs index 26e60e0e669..242b6ed8052 100644 --- a/iroh-relay/src/protos/relay.rs +++ b/iroh-relay/src/protos/relay.rs @@ -12,8 +12,7 @@ use std::num::NonZeroU16; use bytes::{Buf, BufMut, Bytes, BytesMut}; use iroh_base::{EndpointId, KeyParsingError}; use n0_future::time::Duration; -use nested_enum_utils::common_fields; -use snafu::{Backtrace, ResultExt, Snafu}; +use n0_error::{add_meta, Error, e, Err}; use super::common::{FrameType, FrameTypeError}; use crate::KeyCache; @@ -41,32 +40,29 @@ pub(crate) const PING_INTERVAL: Duration = Duration::from_secs(15); pub(crate) const PER_CLIENT_SEND_QUEUE_DEPTH: usize = 512; /// Protocol send errors. -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] +#[add_meta] +#[derive(Error)] +#[error(from_sources)] #[allow(missing_docs)] -#[derive(Debug, Snafu)] #[non_exhaustive] pub enum Error { - #[snafu(display("unexpected frame: got {got:?}, expected {expected:?}"))] + #[display("unexpected frame: got {got:?}, expected {expected:?}")] UnexpectedFrame { got: FrameType, expected: FrameType }, - #[snafu(display("Frame is too large, has {frame_len} bytes"))] + #[display("Frame is too large, has {frame_len} bytes")] FrameTooLarge { frame_len: usize }, - #[snafu(transparent)] - SerDe { source: postcard::Error }, - #[snafu(transparent)] + #[error(transparent)] + SerDe { #[error(std_err)] source: postcard::Error }, + #[error(transparent)] FrameTypeError { source: FrameTypeError }, - #[snafu(display("Invalid public key"))] + #[display("Invalid public key")] InvalidPublicKey { source: KeyParsingError }, - #[snafu(display("Invalid frame encoding"))] + #[display("Invalid frame encoding")] InvalidFrame {}, - #[snafu(display("Invalid frame type: {frame_type:?}"))] + #[display("Invalid frame type: {frame_type:?}")] InvalidFrameType { frame_type: FrameType }, - #[snafu(display("Invalid protocol message encoding"))] - InvalidProtocolMessageEncoding { source: std::str::Utf8Error }, - #[snafu(display("Too few bytes"))] + #[display("Invalid protocol message encoding")] + InvalidProtocolMessageEncoding { #[error(std_err)] source: std::str::Utf8Error }, + #[display("Too few bytes")] TooSmall {}, } @@ -220,9 +216,9 @@ impl Datagrams { fn from_bytes(mut bytes: Bytes, is_batch: bool) -> Result { if is_batch { // 1 bytes ECN, 2 bytes segment size - snafu::ensure!(bytes.len() >= 3, InvalidFrameSnafu); + n0_error::ensure!(bytes.len() >= 3, e!(Error::InvalidFrame)); } else { - snafu::ensure!(bytes.len() >= 1, InvalidFrameSnafu); + n0_error::ensure!(bytes.len() >= 1, e!(Error::InvalidFrame)); } let ecn_byte = bytes.get_u8(); @@ -329,18 +325,16 @@ impl RelayToClientMsg { pub(crate) fn from_bytes(mut content: Bytes, cache: &KeyCache) -> Result { let frame_type = FrameType::from_bytes(&mut content)?; let frame_len = content.len(); - snafu::ensure!( + n0_error::ensure!( frame_len <= MAX_PACKET_SIZE, - FrameTooLargeSnafu { frame_len } + e!(Error::FrameTooLarge { frame_len }) ); let res = match frame_type { FrameType::RelayToClientDatagram | FrameType::RelayToClientDatagramBatch => { - snafu::ensure!(content.len() >= EndpointId::LENGTH, InvalidFrameSnafu); + n0_error::ensure!(content.len() >= EndpointId::LENGTH, e!(Error::InvalidFrame)); - let remote_endpoint_id = cache - .key_from_slice(&content[..EndpointId::LENGTH]) - .context(InvalidPublicKeySnafu)?; + let remote_endpoint_id = cache.key_from_slice(&content[..EndpointId::LENGTH])?; let datagrams = Datagrams::from_bytes( content.slice(EndpointId::LENGTH..), frame_type == FrameType::RelayToClientDatagramBatch, @@ -351,41 +345,37 @@ impl RelayToClientMsg { } } FrameType::EndpointGone => { - snafu::ensure!(content.len() == EndpointId::LENGTH, InvalidFrameSnafu); - let endpoint_id = cache - .key_from_slice(content.as_ref()) - .context(InvalidPublicKeySnafu)?; + n0_error::ensure!(content.len() == EndpointId::LENGTH, e!(Error::InvalidFrame)); + let endpoint_id = cache.key_from_slice(content.as_ref())?; Self::EndpointGone(endpoint_id) } FrameType::Ping => { - snafu::ensure!(content.len() == 8, InvalidFrameSnafu); + n0_error::ensure!(content.len() == 8, e!(Error::InvalidFrame)); let mut data = [0u8; 8]; data.copy_from_slice(&content[..8]); Self::Ping(data) } FrameType::Pong => { - snafu::ensure!(content.len() == 8, InvalidFrameSnafu); + n0_error::ensure!(content.len() == 8, e!(Error::InvalidFrame)); let mut data = [0u8; 8]; data.copy_from_slice(&content[..8]); Self::Pong(data) } FrameType::Health => { - let problem = std::str::from_utf8(&content) - .context(InvalidProtocolMessageEncodingSnafu)? - .to_owned(); + let problem = std::str::from_utf8(&content)?.to_owned(); Self::Health { problem } } FrameType::Restarting => { - snafu::ensure!(content.len() == 4 + 4, InvalidFrameSnafu); + n0_error::ensure!(content.len() == 4 + 4, e!(Error::InvalidFrame)); let reconnect_in = u32::from_be_bytes( content[..4] .try_into() - .map_err(|_| InvalidFrameSnafu.build())?, + .map_err(|_| e!(Error::InvalidFrame))?, ); let try_for = u32::from_be_bytes( content[4..] .try_into() - .map_err(|_| InvalidFrameSnafu.build())?, + .map_err(|_| e!(Error::InvalidFrame))?, ); let reconnect_in = Duration::from_millis(reconnect_in as u64); let try_for = Duration::from_millis(try_for as u64); @@ -395,7 +385,7 @@ impl RelayToClientMsg { } } _ => { - return Err(InvalidFrameTypeSnafu { frame_type }.build()); + return Err!(Error::InvalidFrameType { frame_type }); } }; Ok(res) @@ -463,16 +453,14 @@ impl ClientToRelayMsg { pub(crate) fn from_bytes(mut content: Bytes, cache: &KeyCache) -> Result { let frame_type = FrameType::from_bytes(&mut content)?; let frame_len = content.len(); - snafu::ensure!( + n0_error::ensure!( frame_len <= MAX_PACKET_SIZE, - FrameTooLargeSnafu { frame_len } + e!(Error::FrameTooLarge { frame_len }) ); let res = match frame_type { FrameType::ClientToRelayDatagram | FrameType::ClientToRelayDatagramBatch => { - let dst_endpoint_id = cache - .key_from_slice(&content[..EndpointId::LENGTH]) - .context(InvalidPublicKeySnafu)?; + let dst_endpoint_id = cache.key_from_slice(&content[..EndpointId::LENGTH])?; let datagrams = Datagrams::from_bytes( content.slice(EndpointId::LENGTH..), frame_type == FrameType::ClientToRelayDatagramBatch, @@ -483,19 +471,19 @@ impl ClientToRelayMsg { } } FrameType::Ping => { - snafu::ensure!(content.len() == 8, InvalidFrameSnafu); + n0_error::ensure!(content.len() == 8, e!(Error::InvalidFrame)); let mut data = [0u8; 8]; data.copy_from_slice(&content[..8]); Self::Ping(data) } FrameType::Pong => { - snafu::ensure!(content.len() == 8, InvalidFrameSnafu); + n0_error::ensure!(content.len() == 8, e!(Error::InvalidFrame)); let mut data = [0u8; 8]; data.copy_from_slice(&content[..8]); Self::Pong(data) } _ => { - return Err(InvalidFrameTypeSnafu { frame_type }.build()); + return Err!(Error::InvalidFrameType { frame_type }); } }; Ok(res) @@ -507,7 +495,7 @@ impl ClientToRelayMsg { mod tests { use data_encoding::HEXLOWER; use iroh_base::SecretKey; - use n0_snafu::Result; + use n0_error::Result; use super::*; diff --git a/iroh-relay/src/quic.rs b/iroh-relay/src/quic.rs index b634802dda0..d6d17cc985f 100644 --- a/iroh-relay/src/quic.rs +++ b/iroh-relay/src/quic.rs @@ -3,9 +3,9 @@ use std::{net::SocketAddr, sync::Arc}; use n0_future::time::Duration; -use nested_enum_utils::common_fields; +use n0_error::{add_meta, Error, e}; use quinn::{VarInt, crypto::rustls::QuicClientConfig}; -use snafu::{Backtrace, Snafu}; + use tokio::sync::watch; /// ALPN for our quic addr discovery @@ -21,7 +21,7 @@ pub(crate) mod server { ApplicationClose, ConnectionError, crypto::rustls::{NoInitialCipherSuite, QuicServerConfig}, }; - use snafu::ResultExt; + use n0_error::StdResultExt; use tokio::task::JoinSet; use tokio_util::{sync::CancellationToken, task::AbortOnDropHandle}; use tracing::{Instrument, debug, info, info_span}; @@ -37,30 +37,16 @@ pub(crate) mod server { /// Server spawn errors #[allow(missing_docs)] - #[derive(Debug, Snafu)] + #[add_meta] + #[derive(Error)] #[non_exhaustive] pub enum QuicSpawnError { - #[snafu(transparent)] - NoInitialCipherSuite { - source: NoInitialCipherSuite, - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(display("Unable to spawn a QUIC endpoint server"))] - EndpointServer { - source: std::io::Error, - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(display("Unable to get the local address from the endpoint"))] - LocalAddr { - source: std::io::Error, - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, + #[error(transparent)] + NoInitialCipherSuite { #[error(std_err)] source: NoInitialCipherSuite }, + #[display("Unable to spawn a QUIC endpoint server")] + EndpointServer { #[error(std_err)] source: std::io::Error }, + #[display("Unable to get the local address from the endpoint")] + LocalAddr { #[error(std_err)] source: std::io::Error }, } impl QuicServer { @@ -114,8 +100,8 @@ pub(crate) mod server { .send_observed_address_reports(true); let endpoint = quinn::Endpoint::server(server_config, quic_config.bind_addr) - .context(EndpointServerSnafu)?; - let bind_addr = endpoint.local_addr().context(LocalAddrSnafu)?; + .std_context("endpoint server")?; + let bind_addr = endpoint.local_addr().std_context("local addr")?; info!(?bind_addr, "QUIC server listening on"); @@ -228,21 +214,18 @@ pub(crate) mod server { } /// Quic client related errors. -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] #[allow(missing_docs)] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] +#[error(from_sources, std_sources)] #[non_exhaustive] pub enum Error { - #[snafu(transparent)] - Connect { source: quinn::ConnectError }, - #[snafu(transparent)] - Connection { source: quinn::ConnectionError }, - #[snafu(transparent)] - WatchRecv { source: watch::error::RecvError }, + #[error(transparent)] + Connect { #[error(std_err)] source: quinn::ConnectError }, + #[error(transparent)] + Connection { #[error(std_err)] source: quinn::ConnectionError }, + #[error(transparent)] + WatchRecv { #[error(std_err)] source: watch::error::RecvError }, } /// Handles the client side of QUIC address discovery. @@ -362,7 +345,7 @@ mod tests { task::AbortOnDropHandle, time::{self, Instant}, }; - use n0_snafu::{Error, Result, ResultExt}; + use n0_error::{Error, Result, StdResultExt}; use quinn::crypto::rustls::QuicServerConfig; use tracing::{Instrument, debug, info, info_span}; use tracing_test::traced_test; @@ -387,8 +370,8 @@ mod tests { // create a client-side endpoint let client_endpoint = - quinn::Endpoint::client(SocketAddr::new(host.into(), 0)).context("client")?; - let client_addr = client_endpoint.local_addr().context("local addr")?; + quinn::Endpoint::client(SocketAddr::new(host.into(), 0)).std_context("client")?; + let client_addr = client_endpoint.local_addr().std_context("local addr")?; // create the client configuration used for the client endpoint when they // initiate a connection with the server @@ -414,14 +397,14 @@ mod tests { // create a client-side endpoint let client_endpoint = quinn::Endpoint::client(SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0)) - .context("client")?; + .std_context("client")?; // create an socket that does not respond. let server_socket = tokio::net::UdpSocket::bind(SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0)) .await .context("bind")?; - let server_addr = server_socket.local_addr().context("local addr")?; + let server_addr = server_socket.local_addr().std_context("local addr")?; // create the client configuration used for the client endpoint when they // initiate a connection with the server @@ -466,7 +449,7 @@ mod tests { let socket = tokio::net::UdpSocket::bind(SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0)) .await .context("bind")?; - let server_addr = socket.local_addr().context("local addr")?; + let server_addr = socket.local_addr().std_context("local addr")?; info!(addr = ?server_addr, "server socket bound"); // Create a QAD server with a self-signed cert, all manually. @@ -521,7 +504,7 @@ mod tests { info!("starting client"); let client_endpoint = quinn::Endpoint::client(SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0)) - .context("client")?; + .std_context("client")?; // create the client configuration used for the client endpoint when they // initiate a connection with the server diff --git a/iroh-relay/src/server.rs b/iroh-relay/src/server.rs index 034ac46cac7..fab602bd971 100644 --- a/iroh-relay/src/server.rs +++ b/iroh-relay/src/server.rs @@ -27,8 +27,7 @@ use iroh_base::EndpointId; #[cfg(feature = "test-utils")] use iroh_base::RelayUrl; use n0_future::{StreamExt, future::Boxed}; -use nested_enum_utils::common_fields; -use snafu::{Backtrace, ResultExt, Snafu}; +use n0_error::{add_meta, Error, e, Err, StdResultExt}; use tokio::{ net::TcpListener, task::{JoinError, JoinSet}, @@ -265,48 +264,40 @@ pub struct Server { } /// Server spawn errors -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] #[allow(missing_docs)] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error, Debug)] #[non_exhaustive] pub enum SpawnError { - #[snafu(display("Unable to get local address"))] - LocalAddr { source: std::io::Error }, - #[snafu(display("Failed to bind QAD listener"))] - QuicSpawn { source: QuicSpawnError }, - #[snafu(display("Failed to parse TLS header"))] - TlsHeaderParse { source: InvalidHeaderValue }, - #[snafu(display("Failed to bind TcpListener"))] - BindTlsListener { source: std::io::Error }, - #[snafu(display("No local address"))] - NoLocalAddr { source: std::io::Error }, - #[snafu(display("Failed to bind server socket to {addr}"))] + #[display("Unable to get local address")] + LocalAddr { #[error(std_err)] source: std::io::Error }, + #[display("Failed to bind QAD listener")] + QuicSpawn { #[error(std_err)] source: QuicSpawnError }, + #[display("Failed to parse TLS header")] + TlsHeaderParse { #[error(std_err)] source: InvalidHeaderValue }, + #[display("Failed to bind TcpListener")] + BindTlsListener { #[error(std_err)] source: std::io::Error }, + #[display("No local address")] + NoLocalAddr { #[error(std_err)] source: std::io::Error }, + #[display("Failed to bind server socket to {addr}")] BindTcpListener { addr: SocketAddr }, } /// Server task errors -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] #[allow(missing_docs)] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error, Debug)] #[non_exhaustive] pub enum SupervisorError { - #[snafu(display("Error starting metrics server"))] - Metrics { source: std::io::Error }, - #[snafu(display("Acme event stream finished"))] + #[display("Error starting metrics server")] + Metrics { #[error(std_err)] source: std::io::Error }, + #[display("Acme event stream finished")] AcmeEventStreamFinished {}, - #[snafu(transparent)] - JoinError { source: JoinError }, - #[snafu(display("No relay services are enabled"))] + #[error(transparent)] + JoinError { #[error(std_err)] source: JoinError }, + #[display("No relay services are enabled")] NoRelayServicesEnabled {}, - #[snafu(display("Task cancelled"))] + #[display("Task cancelled")] TaskCancelled {}, } @@ -330,7 +321,7 @@ impl Server { async move { iroh_metrics::service::start_metrics_server(addr, Arc::new(registry)) .await - .context(MetricsSnafu) + .map_err(|err| e!(SupervisorError::Metrics, err)) } .instrument(info_span!("metrics-server")), ); @@ -348,7 +339,7 @@ impl Server { let quic_server = match config.quic { Some(quic_config) => { debug!("Starting QUIC server {}", quic_config.bind_addr); - Some(QuicServer::spawn(quic_config).context(QuicSpawnSnafu)?) + Some(QuicServer::spawn(quic_config).map_err(|err| e!(SpawnError::QuicSpawn, err))?) } None => None, }; @@ -360,7 +351,7 @@ impl Server { debug!("Starting Relay server"); let mut headers = HeaderMap::new(); for (name, value) in TLS_HEADERS.iter() { - headers.insert(*name, value.parse().context(TlsHeaderParseSnafu)?); + headers.insert(*name, value.parse().map_err(|err| e!(SpawnError::TlsHeaderParse, err))?); } let relay_bind_addr = match relay_config.tls { Some(ref tls) => tls.https_bind_addr, @@ -395,7 +386,7 @@ impl Server { Err(err) => error!("error: {err:?}"), } } - Err(AcmeEventStreamFinishedSnafu.build()) + Err(e!(SupervisorError::AcmeEventStreamFinished)) } .instrument(info_span!("acme")), ); @@ -421,8 +412,8 @@ impl Server { // these standalone. let http_listener = TcpListener::bind(&relay_config.http_bind_addr) .await - .context(BindTlsListenerSnafu)?; - let http_addr = http_listener.local_addr().context(NoLocalAddrSnafu)?; + .map_err(|err| e!(SpawnError::BindTlsListener, err))?; + let http_addr = http_listener.local_addr().map_err(|err| e!(SpawnError::NoLocalAddr, err))?; tasks.spawn( async move { run_captive_portal_service(http_listener).await; @@ -564,7 +555,7 @@ async fn relay_supervisor( Some(ret) = tasks.join_next() => ret, ret = &mut quic_fut, if quic_enabled => ret.map(Ok), ret = &mut relay_fut, if relay_enabled => ret.map(Ok), - else => Ok(Err(NoRelayServicesEnabledSnafu.build())), + else => Ok(Err(e!(SupervisorError::NoRelayServicesEnabled))), }; let ret = match res { Ok(Ok(())) => { @@ -581,7 +572,7 @@ async fn relay_supervisor( std::panic::resume_unwind(panic); } debug!("Task cancelled"); - Err(TaskCancelledSnafu.build()) + Err(e!(SupervisorError::TaskCancelled)) } }; @@ -751,7 +742,7 @@ mod tests { use http::StatusCode; use iroh_base::{EndpointId, RelayUrl, SecretKey}; use n0_future::{FutureExt, SinkExt, StreamExt}; - use n0_snafu::Result; + use n0_error::Result; use rand::SeedableRng; use tracing::{info, instrument}; use tracing_test::traced_test; diff --git a/iroh-relay/src/server/client.rs b/iroh-relay/src/server/client.rs index 21ec13bb634..e028f5d278e 100644 --- a/iroh-relay/src/server/client.rs +++ b/iroh-relay/src/server/client.rs @@ -4,9 +4,9 @@ use std::{collections::HashSet, sync::Arc, time::Duration}; use iroh_base::EndpointId; use n0_future::{SinkExt, StreamExt}; -use nested_enum_utils::common_fields; +use n0_error::{add_meta, Error, e, Err}; use rand::Rng; -use snafu::{Backtrace, GenerateImplicitData, Snafu}; + use time::{Date, OffsetDateTime}; use tokio::{ sync::mpsc::{self, error::TrySendError}, @@ -171,98 +171,63 @@ impl Client { } /// Error for [`Actor::handle_frame`] -#[common_fields({ - backtrace: Option, -})] +#[add_meta] +#[derive(Error)] +#[error(from_sources)] #[allow(missing_docs)] -#[derive(Debug, Snafu)] #[non_exhaustive] pub enum HandleFrameError { - #[snafu(transparent)] + #[error(transparent)] ForwardPacket { source: ForwardPacketError }, - #[snafu(display("Stream terminated"))] + #[display("Stream terminated")] StreamTerminated {}, - #[snafu(transparent)] + #[error(transparent)] Recv { source: RelayRecvError }, - #[snafu(transparent)] + #[error(transparent)] Send { source: WriteFrameError }, } /// Error for [`Actor::write_frame`] -#[common_fields({ - backtrace: Option, -})] +#[add_meta] +#[derive(Error)] +#[error(from_sources)] #[allow(missing_docs)] -#[derive(Debug, Snafu)] #[non_exhaustive] pub enum WriteFrameError { - #[snafu(transparent)] + #[error(transparent)] Stream { source: RelaySendError }, - #[snafu(transparent)] - Timeout { source: tokio::time::error::Elapsed }, + #[error(transparent)] + Timeout { #[error(std_err)] source: tokio::time::error::Elapsed }, } /// Run error -#[common_fields({ - backtrace: Option, -})] +#[add_meta] +#[derive(Error)] #[allow(missing_docs)] -#[derive(Debug, Snafu)] #[non_exhaustive] pub enum RunError { - #[snafu(transparent)] + #[error(transparent)] ForwardPacket { source: ForwardPacketError }, - #[snafu(display("Flush"))] - Flush { - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(transparent)] + #[display("Flush")] + Flush {}, + #[error(transparent)] HandleFrame { source: HandleFrameError }, - #[snafu(display("Server.disco_send_queue dropped"))] - DiscoSendQueuePacketDrop { - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(display("Failed to send disco packet"))] - DiscoPacketSend { - source: WriteFrameError, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(display("Server.send_queue dropped"))] - SendQueuePacketDrop { - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(display("Failed to send packet"))] - PacketSend { - source: WriteFrameError, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(display("Server.endpoint_gone dropped"))] - EndpointGoneDrop { - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(display("EndpointGone write frame failed"))] - EndpointGoneWriteFrame { - source: WriteFrameError, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(display("Keep alive write frame failed"))] - KeepAliveWriteFrame { - source: WriteFrameError, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(display("Tick flush"))] - TickFlush { - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, + #[display("Server.disco_send_queue dropped")] + DiscoSendQueuePacketDrop {}, + #[display("Failed to send disco packet")] + DiscoPacketSend { source: WriteFrameError }, + #[display("Server.send_queue dropped")] + SendQueuePacketDrop {}, + #[display("Failed to send packet")] + PacketSend { source: WriteFrameError }, + #[display("Server.endpoint_gone dropped")] + EndpointGoneDrop {}, + #[display("EndpointGone write frame failed")] + EndpointGoneWriteFrame { source: WriteFrameError }, + #[display("Keep alive write frame failed")] + KeepAliveWriteFrame { source: WriteFrameError }, + #[display("Tick flush")] + TickFlush {}, } /// Manages all the reads and writes to this client. It periodically sends a `KEEP_ALIVE` @@ -330,8 +295,7 @@ impl Actor { } async fn run_inner(&mut self, done: CancellationToken) -> Result<(), RunError> { - use snafu::ResultExt; - + // Add some jitter to ping pong interactions, to avoid all pings being sent at the same time let next_interval = || { let random_secs = rand::rng().random_range(1..=5); @@ -360,19 +324,22 @@ impl Actor { } // First priority, disco packets packet = self.disco_send_queue.recv() => { - let packet = packet.ok_or(DiscoSendQueuePacketDropSnafu.build())?; - self.send_disco_packet(packet).await.context(DiscoPacketSendSnafu)?; + let packet = packet.ok_or_else(|| e!(RunError::DiscoSendQueuePacketDrop))?; + self.send_disco_packet(packet).await + .map_err(|err| e!(RunError::DiscoPacketSend, err))?; } // Second priority, sending regular packets packet = self.send_queue.recv() => { - let packet = packet.ok_or(SendQueuePacketDropSnafu.build())?; - self.send_packet(packet).await.context(PacketSendSnafu)?; + let packet = packet.ok_or_else(|| e!(RunError::SendQueuePacketDrop))?; + self.send_packet(packet).await + .map_err(|err| e!(RunError::PacketSend, err))?; } // Last priority, sending left endpoints endpoint_id = self.endpoint_gone.recv() => { - let endpoint_id = endpoint_id.ok_or(EndpointGoneDropSnafu.build())?; + let endpoint_id = endpoint_id.ok_or_else(|| e!(RunError::EndpointGoneDrop))?; trace!("endpoint_id gone: {:?}", endpoint_id); - self.write_frame(RelayToClientMsg::EndpointGone(endpoint_id)).await.context(EndpointGoneWriteFrameSnafu)?; + self.write_frame(RelayToClientMsg::EndpointGone(endpoint_id)).await + .map_err(|err| e!(RunError::EndpointGoneWriteFrame, err))?; } _ = self.ping_tracker.timeout() => { trace!("pong timed out"); @@ -383,14 +350,16 @@ impl Actor { // new interval ping_interval.reset_after(next_interval()); let data = self.ping_tracker.new_ping(); - self.write_frame(RelayToClientMsg::Ping(data)).await.context(KeepAliveWriteFrameSnafu)?; + self.write_frame(RelayToClientMsg::Ping(data)) + .await + .map_err(|err| e!(RunError::KeepAliveWriteFrame, err))?; } } self.stream .flush() .await - .map_err(|_| TickFlushSnafu.build())?; + .map_err(|_| e!(RunError::TickFlush))?; } Ok(()) } @@ -399,7 +368,8 @@ impl Actor { /// /// Errors if the send does not happen within the `timeout` duration async fn write_frame(&mut self, frame: RelayToClientMsg) -> Result<(), WriteFrameError> { - tokio::time::timeout(self.timeout, self.stream.send(frame)).await??; + tokio::time::timeout(self.timeout, self.stream.send(frame)).await? + .map_err(|err| e!(WriteFrameError::Stream { source: err }))?; Ok(()) } @@ -457,7 +427,7 @@ impl Actor { trace!(?maybe_frame, "handle incoming frame"); let frame = match maybe_frame { Some(frame) => frame?, - None => return Err(StreamTerminatedSnafu.build()), + None => return Err!(HandleFrameError::StreamTerminated), }; match frame { @@ -516,22 +486,12 @@ pub(crate) enum SendError { Closed, } -#[derive(Debug, Snafu)] -#[snafu(display("failed to forward {scope:?} packet: {reason:?}"))] +#[add_meta] +#[derive(Error)] +#[display("failed to forward {scope:?} packet: {reason:?}")] pub(crate) struct ForwardPacketError { scope: PacketScope, reason: SendError, - backtrace: Option, -} - -impl ForwardPacketError { - pub(crate) fn new(scope: PacketScope, reason: SendError) -> Self { - Self { - scope, - reason, - backtrace: GenerateImplicitData::generate(), - } - } } /// Tracks how many unique endpoints have been seen during the last day. @@ -569,8 +529,8 @@ impl ClientCounter { #[cfg(test)] mod tests { use iroh_base::SecretKey; + use n0_error::{Result, StdResultExt}; use n0_future::Stream; - use n0_snafu::{Result, ResultExt}; use rand::SeedableRng; use tracing::info; use tracing_test::traced_test; @@ -579,7 +539,7 @@ mod tests { use crate::{client::conn::Conn, protos::common::FrameType}; async fn recv_frame< - E: snafu::Error + Sync + Send + 'static, + E: std::error::Error + Sync + Send + 'static, S: Stream> + Unpin, >( frame_type: FrameType, @@ -588,7 +548,7 @@ mod tests { match stream.next().await { Some(Ok(frame)) => { if frame_type != frame.typ() { - snafu::whatever!( + n0_error::whatever!( "Unexpected frame, got {:?}, but expected {:?}", frame.typ(), frame_type @@ -597,7 +557,7 @@ mod tests { Ok(frame) } Some(Err(err)) => Err(err).e(), - None => snafu::whatever!("Unexpected EOF, expected frame {frame_type:?}"), + None => n0_error::whatever!("Unexpected EOF, expected frame {frame_type:?}"), } } @@ -645,7 +605,7 @@ mod tests { src: endpoint_id, data: Datagrams::from(&data[..]), }; - send_queue_s.send(packet.clone()).await.context("send")?; + send_queue_s.send(packet.clone()).await.std_context("send")?; let frame = recv_frame(FrameType::RelayToClientDatagram, &mut io_rw) .await .e()?; @@ -662,7 +622,7 @@ mod tests { disco_send_queue_s .send(packet.clone()) .await - .context("send")?; + .std_context("send")?; let frame = recv_frame(FrameType::RelayToClientDatagram, &mut io_rw) .await .e()?; @@ -676,7 +636,7 @@ mod tests { // send peer_gone println!("send peer gone"); - peer_gone_s.send(endpoint_id).await.context("send")?; + peer_gone_s.send(endpoint_id).await.std_context("send")?; let frame = recv_frame(FrameType::EndpointGone, &mut io_rw).await.e()?; assert_eq!(frame, RelayToClientMsg::EndpointGone(endpoint_id)); @@ -703,7 +663,7 @@ mod tests { datagrams: Datagrams::from(data), }) .await - .context("send")?; + .std_context("send")?; // send disco packet println!(" send disco packet"); @@ -717,10 +677,10 @@ mod tests { datagrams: disco_data.clone().into(), }) .await - .context("send")?; + .std_context("send")?; done.cancel(); - handle.await.context("join")?; + handle.await.std_context("join")?; Ok(()) } diff --git a/iroh-relay/src/server/clients.rs b/iroh-relay/src/server/clients.rs index fe92439db1d..ffbc9651f11 100644 --- a/iroh-relay/src/server/clients.rs +++ b/iroh-relay/src/server/clients.rs @@ -194,8 +194,8 @@ mod tests { use std::time::Duration; use iroh_base::SecretKey; + use n0_error::{Result, StdResultExt}; use n0_future::{Stream, StreamExt}; - use n0_snafu::{Result, ResultExt}; use rand::SeedableRng; use super::*; @@ -206,7 +206,7 @@ mod tests { }; async fn recv_frame< - E: snafu::Error + Sync + Send + 'static, + E: std::error::Error + Sync + Send + 'static, S: Stream> + Unpin, >( frame_type: FrameType, @@ -215,7 +215,7 @@ mod tests { match stream.next().await { Some(Ok(frame)) => { if frame_type != frame.typ() { - snafu::whatever!( + n0_error::whatever!( "Unexpected frame, got {:?}, but expected {:?}", frame.typ(), frame_type @@ -224,7 +224,7 @@ mod tests { Ok(frame) } Some(Err(err)) => Err(err).e(), - None => snafu::whatever!("Unexpected EOF, expected frame {frame_type:?}"), + None => n0_error::whatever!("Unexpected EOF, expected frame {frame_type:?}"), } } @@ -293,7 +293,7 @@ mod tests { } }) .await - .context("timeout")?; + .std_context("timeout")?; clients.shutdown().await; Ok(()) diff --git a/iroh-relay/src/server/http_server.rs b/iroh-relay/src/server/http_server.rs index b5b315560fc..ebee670ded2 100644 --- a/iroh-relay/src/server/http_server.rs +++ b/iroh-relay/src/server/http_server.rs @@ -16,8 +16,8 @@ use hyper::{ upgrade::Upgraded, }; use n0_future::time::Elapsed; -use nested_enum_utils::common_fields; -use snafu::{Backtrace, OptionExt, ResultExt, Snafu}; +use n0_error::{add_meta, Error, e, Err, StdResultExt}; +use snafu::{OptionExt}; use tokio::net::{TcpListener, TcpStream}; use tokio_rustls_acme::AcmeAcceptor; use tokio_util::{sync::CancellationToken, task::AbortOnDropHandle}; @@ -77,7 +77,7 @@ fn body_full(content: impl Into) -> BytesBody { fn downcast_upgrade(upgraded: Upgraded) -> Result<(MaybeTlsStream, Bytes), ConnectionHandlerError> { match upgraded.downcast::>() { Ok(parts) => Ok((parts.io.into_inner(), parts.read_buf)), - Err(_) => Err(DowncastUpgradeSnafu.build()), + Err(_) => Err!(ConnectionHandlerError::DowncastUpgrade), } } @@ -151,92 +151,51 @@ pub(super) struct TlsConfig { } /// Errors when attempting to upgrade and -#[common_fields({ - backtrace: Option, -})] #[allow(missing_docs)] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] pub enum ServeConnectionError { - #[snafu(display("TLS[acme] handshake"))] - TlsHandshake { - source: std::io::Error, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(display("TLS[acme] serve connection"))] - ServeConnection { - source: hyper::Error, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(display("TLS[manual] timeout"))] - Timeout { - source: Elapsed, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(display("TLS[manual] accept"))] - ManualAccept { - source: std::io::Error, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(display("TLS[acme] accept"))] - LetsEncryptAccept { - source: std::io::Error, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(display("HTTPS connection"))] - Https { - source: hyper::Error, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(display("HTTP connection"))] - Http { - source: hyper::Error, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, + #[display("TLS[acme] handshake")] + TlsHandshake { #[error(std_err)] source: std::io::Error }, + #[display("TLS[acme] serve connection")] + ServeConnection { #[error(std_err)] source: hyper::Error }, + #[display("TLS[manual] timeout")] + Timeout { #[error(std_err)] source: Elapsed }, + #[display("TLS[manual] accept")] + ManualAccept { #[error(std_err)] source: std::io::Error }, + #[display("TLS[acme] accept")] + LetsEncryptAccept { #[error(std_err)] source: std::io::Error }, + #[display("HTTPS connection")] + Https { #[error(std_err)] source: hyper::Error }, + #[display("HTTP connection")] + Http { #[error(std_err)] source: hyper::Error }, } /// Server accept errors. -#[common_fields({ - backtrace: Option, -})] #[allow(missing_docs)] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] pub enum AcceptError { - #[snafu(transparent)] + #[error(transparent)] Handshake { source: handshake::Error }, - #[snafu(display("rate limiting misconfigured"))] + #[display("rate limiting misconfigured")] RateLimitingMisconfigured { source: InvalidBucketConfig }, } /// Server connection errors, includes errors that can happen on `accept`. -#[common_fields({ - backtrace: Option, -})] #[allow(missing_docs)] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] pub enum ConnectionHandlerError { - #[snafu(transparent)] + #[error(transparent)] Accept { source: AcceptError }, - #[snafu(display("Could not downcast the upgraded connection to MaybeTlsStream"))] - DowncastUpgrade { - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(display("Cannot deal with buffered data yet: {buf:?}"))] - BufferNotEmpty { - buf: Bytes, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, + #[display("Could not downcast the upgraded connection to MaybeTlsStream")] + DowncastUpgrade {}, + #[display("Cannot deal with buffered data yet: {buf:?}")] + BufferNotEmpty { buf: Bytes }, } /// Builder for the Relay HTTP Server. @@ -339,7 +298,6 @@ impl ServerBuilder { /// Builds and spawns an HTTP(S) Relay Server. pub(super) async fn spawn(self) -> Result { - use snafu::ResultExt; let cancel_token = CancellationToken::new(); @@ -361,7 +319,7 @@ impl ServerBuilder { .await .map_err(|_| BindTcpListenerSnafu { addr }.build())?; - let addr = listener.local_addr().context(NoLocalAddrSnafu)?; + let addr = listener.local_addr().std_context("no-local-addr")?; let http_str = tls_config.as_ref().map_or("HTTP/WS", |_| "HTTPS/WSS"); info!("[{http_str}] relay: serving on {addr}"); @@ -432,22 +390,23 @@ struct Inner { metrics: Arc, } -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error, Debug)] enum RelayUpgradeReqError { - #[snafu(display("missing header: {header}"))] + #[display("missing header: {header}")] MissingHeader { header: http::HeaderName }, - #[snafu(display("invalid header value for {header}: {details}"))] + #[display("invalid header value for {header}: {details}")] InvalidHeader { header: http::HeaderName, details: String, }, - #[snafu(display( + #[display( "invalid header value for {SEC_WEBSOCKET_VERSION}: unsupported websocket version, only supporting {SUPPORTED_WEBSOCKET_VERSION}" - ))] + )] UnsupportedWebsocketVersion, - #[snafu(display( + #[display( "invalid header value for {SEC_WEBSOCKET_PROTOCOL}: unsupported relay version: we support {we_support} but you only provide {you_support}" - ))] + )] UnsupportedRelayVersion { we_support: &'static str, you_support: String, @@ -474,42 +433,33 @@ impl RelayService { ) -> Result<&HeaderValue, RelayUpgradeReqError> { req.headers() .get(&header) - .context(MissingHeaderSnafu { header }) + .ok_or_else(|| e!(RelayUpgradeReqError::MissingHeader { header })) } let upgrade_header = expect_header(&req, UPGRADE)?; - snafu::ensure!( + n0_error::ensure!( upgrade_header == HeaderValue::from_static(WEBSOCKET_UPGRADE_PROTOCOL), - InvalidHeaderSnafu { - header: UPGRADE, - details: format!("value must be {WEBSOCKET_UPGRADE_PROTOCOL}"), - } + e!(RelayUpgradeReqError::InvalidHeader { header: UPGRADE, details: format!("value must be {WEBSOCKET_UPGRADE_PROTOCOL}") }) ); let key = expect_header(&req, SEC_WEBSOCKET_KEY)?.clone(); let version = expect_header(&req, SEC_WEBSOCKET_VERSION)?.clone(); - snafu::ensure!( + n0_error::ensure!( version.as_bytes() == SUPPORTED_WEBSOCKET_VERSION.as_bytes(), - UnsupportedWebsocketVersionSnafu + e!(RelayUpgradeReqError::UnsupportedWebsocketVersion) ); let subprotocols = expect_header(&req, SEC_WEBSOCKET_PROTOCOL)? .to_str() .ok() - .context(InvalidHeaderSnafu { - header: SEC_WEBSOCKET_PROTOCOL, - details: "header value is not ascii".to_string(), - })?; + .ok_or_else(|| e!(RelayUpgradeReqError::InvalidHeader { header: SEC_WEBSOCKET_PROTOCOL, details: "header value is not ascii".to_string() }))?; let supports_our_version = subprotocols .split_whitespace() .any(|p| p == RELAY_PROTOCOL_VERSION); - snafu::ensure!( + n0_error::ensure!( supports_our_version, - UnsupportedRelayVersionSnafu { - we_support: RELAY_PROTOCOL_VERSION, - you_support: subprotocols.to_string(), - } + e!(RelayUpgradeReqError::UnsupportedRelayVersion { we_support: RELAY_PROTOCOL_VERSION, you_support: subprotocols.to_string() }) ); let client_auth_header = req.headers().get(CLIENT_AUTH_HEADER).cloned(); @@ -638,7 +588,7 @@ impl Inner { debug!("relay_connection upgraded"); let (io, read_buf) = downcast_upgrade(upgraded)?; if !read_buf.is_empty() { - return Err(BufferNotEmptySnafu { buf: read_buf }.build()); + return Err!(ConnectionHandlerError::BufferNotEmpty { buf: read_buf }); } self.accept(io, client_auth_header).await?; @@ -663,7 +613,7 @@ impl Inner { trace!("accept: start"); let io = RateLimited::from_cfg(self.rate_limit, io, self.metrics.clone()) - .context(RateLimitingMisconfiguredSnafu)?; + .map_err(|err| e!(AcceptError::RateLimitingMisconfigured, err))?; // Create a server builder with default config let websocket = tokio_websockets::ServerBuilder::new() @@ -755,7 +705,7 @@ impl RelayService { debug!("HTTP: serve connection"); self.serve_connection(MaybeTlsStream::Plain(stream)) .await - .context(HttpSnafu) + .map_err(|err| e!(ServeConnectionError::Http, err)) } }; match res { @@ -791,7 +741,7 @@ impl RelayService { let TlsConfig { acceptor, config } = tls_config; match acceptor { TlsAcceptor::LetsEncrypt(a) => { - match a.accept(stream).await.context(LetsEncryptAcceptSnafu)? { + match a.accept(stream).await.map_err(|err| e!(ServeConnectionError::LetsEncryptAccept, err))? { None => { info!("TLS[acme]: received TLS-ALPN-01 validation request"); } @@ -800,10 +750,10 @@ impl RelayService { let tls_stream = start_handshake .into_stream(config) .await - .context(TlsHandshakeSnafu)?; + .map_err(|err| e!(ServeConnectionError::TlsHandshake, err))?; self.serve_connection(MaybeTlsStream::Tls(tls_stream)) .await - .context(HttpsSnafu)?; + .map_err(|err| e!(ServeConnectionError::Https, err))?; } } } @@ -811,12 +761,12 @@ impl RelayService { debug!("TLS[manual]: accept"); let tls_stream = tokio::time::timeout(Duration::from_secs(30), a.accept(stream)) .await - .context(TimeoutSnafu)? - .context(ManualAcceptSnafu)?; + .std_context("timeout")? + .map_err(|err| e!(ServeConnectionError::ManualAccept, err))?; self.serve_connection(MaybeTlsStream::Tls(tls_stream)) .await - .context(ServeConnectionSnafu)?; + .map_err(|err| e!(ServeConnectionError::ServeConnection, err))?; } } Ok(()) @@ -867,10 +817,9 @@ mod tests { use iroh_base::{PublicKey, SecretKey}; use n0_future::{SinkExt, StreamExt}; - use n0_snafu::{Result, ResultExt}; + use n0_error::{Result, StdResultExt, whatever}; use rand::SeedableRng; use reqwest::Url; - use snafu::whatever; use tracing::info; use tracing_test::traced_test; diff --git a/iroh-relay/src/server/streams.rs b/iroh-relay/src/server/streams.rs index 545e61bd494..463f70c9486 100644 --- a/iroh-relay/src/server/streams.rs +++ b/iroh-relay/src/server/streams.rs @@ -6,8 +6,8 @@ use std::{ task::{Context, Poll}, }; +use n0_error::{add_meta, Error, e}; use n0_future::{FutureExt, Sink, Stream, ready, time}; -use snafu::{Backtrace, Snafu}; use tokio::io::{AsyncRead, AsyncWrite}; use tracing::instrument; @@ -75,14 +75,15 @@ impl RelayedStream { } /// Relay send errors -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] pub enum SendError { - #[snafu(transparent)] - StreamError { source: StreamError }, - #[snafu(display("Packet exceeds max packet size"))] + #[error(transparent)] + StreamError { #[error(std_err)] source: StreamError }, + #[display("Packet exceeds max packet size")] ExceedsMaxPacketSize { size: usize }, - #[snafu(display("Attempted to send empty packet"))] + #[display("Attempted to send empty packet")] EmptyPacket {}, } @@ -95,9 +96,9 @@ impl Sink for RelayedStream { fn start_send(mut self: Pin<&mut Self>, item: RelayToClientMsg) -> Result<(), Self::Error> { let size = item.encoded_len(); - snafu::ensure!(size <= MAX_PACKET_SIZE, ExceedsMaxPacketSizeSnafu { size }); + n0_error::ensure!(size <= MAX_PACKET_SIZE, e!(SendError::ExceedsMaxPacketSize { size })); if let RelayToClientMsg::Datagrams { datagrams, .. } = &item { - snafu::ensure!(!datagrams.contents.is_empty(), EmptyPacketSnafu); + n0_error::ensure!(!datagrams.contents.is_empty(), e!(SendError::EmptyPacket)); } Pin::new(&mut self.inner) @@ -115,13 +116,14 @@ impl Sink for RelayedStream { } /// Relay receive errors -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] pub enum RecvError { - #[snafu(transparent)] + #[error(transparent)] Proto { source: ProtoError }, - #[snafu(transparent)] - StreamError { source: StreamError }, + #[error(transparent)] + StreamError { #[error(std_err)] source: StreamError }, } impl Stream for RelayedStream { @@ -278,11 +280,9 @@ struct Bucket { } #[allow(missing_docs)] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] pub struct InvalidBucketConfig { - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, max: i64, bytes_per_second: i64, refill_period: time::Duration, @@ -296,13 +296,9 @@ impl Bucket { ) -> Result { // milliseconds is the tokio timer resolution let refill = bytes_per_second.saturating_mul(refill_period.as_millis() as i64) / 1000; - snafu::ensure!( + n0_error::ensure!( max > 0 && bytes_per_second > 0 && refill_period.as_millis() as u32 > 0 && refill > 0, - InvalidBucketConfigSnafu { - max, - bytes_per_second, - refill_period, - }, + e!(InvalidBucketConfig { max, bytes_per_second, refill_period }), ); Ok(Self { fill: max, @@ -481,7 +477,7 @@ mod tests { use std::sync::Arc; use n0_future::time; - use n0_snafu::{Result, ResultExt}; + use n0_error::Result; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tracing_test::traced_test; diff --git a/iroh/Cargo.toml b/iroh/Cargo.toml index 2bea278f51c..9a1e7e5b84d 100644 --- a/iroh/Cargo.toml +++ b/iroh/Cargo.toml @@ -41,6 +41,7 @@ iroh-base = { version = "0.93.2", default-features = false, features = ["key", " iroh-relay = { version = "0.93", path = "../iroh-relay", default-features = false } n0-future = "0.3.0" n0-snafu = "0.2.2" +n0-error = { git = "https://github.com/n0-computer/n0-error" } n0-watcher = "0.3" nested_enum_utils = "0.2.1" netwatch = { version = "0.10" } From 0b4c0149a74c0240b5a249efae7aca0ba3642108 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 13:47:13 +0200 Subject: [PATCH 04/58] wip --- iroh-relay/src/endpoint_info.rs | 1 - iroh-relay/src/quic.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/iroh-relay/src/endpoint_info.rs b/iroh-relay/src/endpoint_info.rs index 7dd23e1b1ec..d4740121df9 100644 --- a/iroh-relay/src/endpoint_info.rs +++ b/iroh-relay/src/endpoint_info.rs @@ -42,7 +42,6 @@ use std::{ use iroh_base::{EndpointAddr, EndpointId, KeyParsingError, RelayUrl, SecretKey}; use n0_error::{add_meta, Error, e}; -use n0_error::StdResultExt; use url::Url; /// The DNS name for the iroh TXT record. diff --git a/iroh-relay/src/quic.rs b/iroh-relay/src/quic.rs index d6d17cc985f..ad5879bc72c 100644 --- a/iroh-relay/src/quic.rs +++ b/iroh-relay/src/quic.rs @@ -3,7 +3,7 @@ use std::{net::SocketAddr, sync::Arc}; use n0_future::time::Duration; -use n0_error::{add_meta, Error, e}; +use n0_error::{add_meta, Error}; use quinn::{VarInt, crypto::rustls::QuicClientConfig}; use tokio::sync::watch; From 96506325b76c5bbab4e4a91983f955033d10b07f Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 14:58:36 +0200 Subject: [PATCH 05/58] wip: converting iroh --- iroh/src/disco.rs | 50 +++++------ iroh/src/discovery.rs | 52 +++++------ iroh/src/endpoint.rs | 150 +++++++++++++------------------ iroh/src/key.rs | 27 +++--- iroh/src/net_report.rs | 55 +++++++++--- iroh/src/net_report/reportgen.rs | 146 +++++++++++++++--------------- iroh/src/protocol.rs | 42 ++++----- 7 files changed, 251 insertions(+), 271 deletions(-) diff --git a/iroh/src/disco.rs b/iroh/src/disco.rs index 75e10aa7664..ec41903bdfc 100644 --- a/iroh/src/disco.rs +++ b/iroh/src/disco.rs @@ -25,10 +25,10 @@ use std::{ use data_encoding::HEXLOWER; use iroh_base::{PublicKey, RelayUrl}; -use nested_enum_utils::common_fields; +use n0_error::{add_meta, Error, e, Err}; use rand::Rng; use serde::{Deserialize, Serialize}; -use snafu::{Snafu, ensure}; +// use n0_error ensure macro path-qualified use url::Url; use crate::magicsock::transports; @@ -217,11 +217,11 @@ pub struct CallMeMaybe { impl Ping { fn from_bytes(p: &[u8]) -> Result { // Deliberately lax on longer-than-expected messages, for future compatibility. - ensure!(p.len() >= PING_LEN, TooShortSnafu); + n0_error::ensure!(p.len() >= PING_LEN, e!(ParseError::TooShort)); let tx_id: [u8; TX_LEN] = p[..TX_LEN].try_into().expect("length checked"); let raw_key = &p[TX_LEN..TX_LEN + iroh_base::PublicKey::LENGTH]; let endpoint_key = - PublicKey::try_from(raw_key).map_err(|_| InvalidEncodingSnafu.build())?; + PublicKey::try_from(raw_key).map_err(|_| e!(ParseError::InvalidEncoding))?; let tx_id = TransactionId::from(tx_id); Ok(Ping { @@ -243,36 +243,32 @@ impl Ping { } #[allow(missing_docs)] -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] pub enum ParseError { - #[snafu(display("message is too short"))] - TooShort {}, - #[snafu(display("invalid encoding"))] - InvalidEncoding {}, - #[snafu(display("unknown format"))] - UnknownFormat {}, + #[display("message is too short")] + TooShort, + #[display("invalid encoding")] + InvalidEncoding, + #[display("unknown format")] + UnknownFormat, } fn send_addr_from_bytes(p: &[u8]) -> Result { - ensure!(p.len() > 2, TooShortSnafu); + n0_error::ensure!(p.len() > 2, e!(ParseError::TooShort)); match p[0] { 0u8 => { - let bytes: [u8; EP_LENGTH] = p[1..].try_into().map_err(|_| TooShortSnafu.build())?; + let bytes: [u8; EP_LENGTH] = p[1..].try_into().map_err(|_| e!(ParseError::TooShort))?; let addr = socket_addr_from_bytes(bytes); Ok(SendAddr::Udp(addr)) } 1u8 => { - let s = std::str::from_utf8(&p[1..]).map_err(|_| InvalidEncodingSnafu.build())?; - let u: Url = s.parse().map_err(|_| InvalidEncodingSnafu.build())?; + let s = std::str::from_utf8(&p[1..]).map_err(|_| e!(ParseError::InvalidEncoding))?; + let u: Url = s.parse().map_err(|_| e!(ParseError::InvalidEncoding))?; Ok(SendAddr::Relay(u.into())) } - _ => Err(UnknownFormatSnafu.build()), + _ => Err!(ParseError::UnknownFormat), } } @@ -318,7 +314,7 @@ fn socket_addr_as_bytes(addr: &SocketAddr) -> [u8; EP_LENGTH] { impl Pong { fn from_bytes(p: &[u8]) -> Result { - let tx_id: [u8; TX_LEN] = p[..TX_LEN].try_into().map_err(|_| TooShortSnafu.build())?; + let tx_id: [u8; TX_LEN] = p[..TX_LEN].try_into().map_err(|_| e!(ParseError::TooShort))?; let tx_id = TransactionId::from(tx_id); let src = send_addr_from_bytes(&p[TX_LEN..])?; @@ -342,7 +338,7 @@ impl Pong { impl CallMeMaybe { fn from_bytes(p: &[u8]) -> Result { - ensure!(p.len() % EP_LENGTH == 0, InvalidEncodingSnafu); + n0_error::ensure!(p.len() % EP_LENGTH == 0, e!(ParseError::InvalidEncoding)); let num_entries = p.len() / EP_LENGTH; let mut m = CallMeMaybe { @@ -351,7 +347,7 @@ impl CallMeMaybe { for chunk in p.chunks_exact(EP_LENGTH) { let bytes: [u8; EP_LENGTH] = - chunk.try_into().map_err(|_| InvalidEncodingSnafu.build())?; + chunk.try_into().map_err(|_| e!(ParseError::InvalidEncoding))?; let src = socket_addr_from_bytes(bytes); m.my_numbers.push(src); } @@ -380,11 +376,11 @@ impl CallMeMaybe { impl Message { /// Parses the encrypted part of the message from inside the nacl secretbox. pub fn from_bytes(p: &[u8]) -> Result { - ensure!(p.len() >= 2, TooShortSnafu); + n0_error::ensure!(p.len() >= 2, e!(ParseError::TooShort)); - let t = MessageType::try_from(p[0]).map_err(|_| UnknownFormatSnafu.build())?; + let t = MessageType::try_from(p[0]).map_err(|_| e!(ParseError::UnknownFormat))?; let version = p[1]; - ensure!(version == V0, UnknownFormatSnafu); + n0_error::ensure!(version == V0, e!(ParseError::UnknownFormat)); let p = &p[2..]; match t { diff --git a/iroh/src/discovery.rs b/iroh/src/discovery.rs index 1e31e3d1c53..3b820649c0d 100644 --- a/iroh/src/discovery.rs +++ b/iroh/src/discovery.rs @@ -119,8 +119,7 @@ use n0_future::{ task::{self, AbortOnDropHandle}, time::{self, Duration}, }; -use nested_enum_utils::common_fields; -use snafu::{IntoError, Snafu, ensure}; +use n0_error::{add_meta, Error, e, AnyError, Err}; use tokio::sync::oneshot; use tracing::{Instrument, debug, error_span, warn}; @@ -181,20 +180,15 @@ impl DynIntoDiscovery for T { } /// IntoDiscovery errors -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] #[allow(missing_docs)] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] -#[snafu(module)] pub enum IntoDiscoveryError { - #[snafu(display("Service '{provenance}' error"))] + #[display("Service '{provenance}' error")] User { provenance: &'static str, - source: Box, + source: AnyError, }, } @@ -204,7 +198,7 @@ impl IntoDiscoveryError { provenance: &'static str, source: T, ) -> Self { - into_discovery_error::UserSnafu { provenance }.into_error(Box::new(source)) + e!(IntoDiscoveryError::User { provenance, source: AnyError::from_std(source) }) } /// Creates a new user error from an arbitrary boxed error type. @@ -212,28 +206,24 @@ impl IntoDiscoveryError { provenance: &'static str, source: Box, ) -> Self { - into_discovery_error::UserSnafu { provenance }.into_error(source) + e!(IntoDiscoveryError::User { provenance, source: AnyError::from_std_box(source) }) } } /// Discovery errors -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] #[allow(missing_docs)] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] pub enum DiscoveryError { - #[snafu(display("No discovery service configured"))] - NoServiceConfigured {}, - #[snafu(display("Discovery produced no results for {}", endpoint_id.fmt_short()))] + #[display("No discovery service configured")] + NoServiceConfigured, + #[display("Discovery produced no results for {}", endpoint_id.fmt_short())] NoResults { endpoint_id: EndpointId }, - #[snafu(display("Service '{provenance}' error"))] + #[display("Service '{provenance}' error")] User { provenance: &'static str, - source: Box, + source: AnyError, }, } @@ -243,7 +233,7 @@ impl DiscoveryError { provenance: &'static str, source: T, ) -> Self { - UserSnafu { provenance }.into_error(Box::new(source)) + e!(DiscoveryError::User { provenance, source: AnyError::from_std(source) }) } /// Creates a new user error from an arbitrary boxed error type. @@ -251,7 +241,7 @@ impl DiscoveryError { provenance: &'static str, source: Box, ) -> Self { - UserSnafu { provenance }.into_error(source) + e!(DiscoveryError::User { provenance, source: AnyError::from_std_box(source) }) } } @@ -505,7 +495,7 @@ pub(super) struct DiscoveryTask { impl DiscoveryTask { /// Starts a discovery task. pub(super) fn start(ep: Endpoint, endpoint_id: EndpointId) -> Result { - ensure!(!ep.discovery().is_empty(), NoServiceConfiguredSnafu); + n0_error::ensure!(!ep.discovery().is_empty(), e!(DiscoveryError::NoServiceConfigured)); let (on_first_tx, on_first_rx) = oneshot::channel(); let me = ep.id(); let task = task::spawn( @@ -536,7 +526,7 @@ impl DiscoveryTask { if !ep.needs_discovery(endpoint_id, MAX_AGE) { return Ok(None); } - ensure!(!ep.discovery().is_empty(), NoServiceConfiguredSnafu); + n0_error::ensure!(!ep.discovery().is_empty(), e!(DiscoveryError::NoServiceConfigured)); let (on_first_tx, on_first_rx) = oneshot::channel(); let ep = ep.clone(); let me = ep.id(); @@ -574,11 +564,11 @@ impl DiscoveryTask { ep: &Endpoint, endpoint_id: EndpointId, ) -> Result>, DiscoveryError> { - ensure!(!ep.discovery().is_empty(), NoServiceConfiguredSnafu); + n0_error::ensure!(!ep.discovery().is_empty(), e!(DiscoveryError::NoServiceConfigured)); let stream = ep .discovery() .resolve(endpoint_id) - .ok_or(NoResultsSnafu { endpoint_id }.build())?; + .ok_or_else(|| e!(DiscoveryError::NoResults { endpoint_id }))?; Ok(stream) } @@ -623,7 +613,7 @@ impl DiscoveryTask { } } if let Some(tx) = on_first_tx.take() { - tx.send(Err(NoResultsSnafu { endpoint_id }.build())).ok(); + tx.send(Err!(DiscoveryError::NoResults { endpoint_id })).ok(); } } } diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 77cd506216c..ca0ed060f2d 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -25,9 +25,8 @@ use iroh_base::{EndpointAddr, EndpointId, RelayUrl, SecretKey}; use iroh_relay::{RelayConfig, RelayMap}; use n0_future::time::Duration; use n0_watcher::Watcher; -use nested_enum_utils::common_fields; use pin_project::pin_project; -use snafu::{ResultExt, Snafu, ensure}; +use n0_error::{add_meta, Error, e, Err}; use tracing::{debug, instrument, trace, warn}; use url::Url; @@ -483,80 +482,55 @@ pub struct Endpoint { } #[allow(missing_docs)] -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] pub enum ConnectWithOptsError { - #[snafu(transparent)] - AddEndpointAddr { source: AddEndpointAddrError }, - #[snafu(display("Connecting to ourself is not supported"))] - SelfConnect {}, - #[snafu(display("No addressing information available"))] + #[error(transparent)] + AddEndpointAddr { #[error(std_err)] source: AddEndpointAddrError }, + #[display("Connecting to ourself is not supported")] + SelfConnect, + #[display("No addressing information available")] NoAddress { source: GetMappingAddressError }, - #[snafu(display("Unable to connect to remote"))] - Quinn { source: quinn::ConnectError }, + #[display("Unable to connect to remote")] + Quinn { #[error(std_err)] source: quinn_proto::ConnectError }, } #[allow(missing_docs)] -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] +#[error(from_sources, std_sources)] #[non_exhaustive] pub enum ConnectError { - #[snafu(transparent)] - Connect { - #[snafu(source(from(ConnectWithOptsError, Box::new)))] - source: Box, - }, - #[snafu(transparent)] - Connection { - #[snafu(source(from(ConnectionError, Box::new)))] - source: Box, - }, + #[error(transparent)] + Connect { source: ConnectWithOptsError }, + #[error(transparent)] + Connection { #[error(std_err)] source: ConnectionError }, } #[allow(missing_docs)] -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] +#[error(from_sources, std_sources)] #[non_exhaustive] pub enum BindError { - #[snafu(transparent)] - MagicSpawn { - source: magicsock::CreateHandleError, - }, - #[snafu(transparent)] - Discovery { - source: crate::discovery::IntoDiscoveryError, - }, + #[error(transparent)] + MagicSpawn { source: magicsock::CreateHandleError }, + #[error(transparent)] + Discovery { source: crate::discovery::IntoDiscoveryError }, } #[allow(missing_docs)] -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] -#[derive(Debug, Snafu)] -#[snafu(module)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] pub enum GetMappingAddressError { - #[snafu(display("Discovery service required due to missing addressing information"))] + #[display("Discovery service required due to missing addressing information")] DiscoveryStart { source: DiscoveryError }, - #[snafu(display("Discovery service failed"))] + #[display("Discovery service failed")] Discover { source: DiscoveryError }, - #[snafu(display("No addressing information found"))] - NoAddress {}, + #[display("No addressing information found")] + NoAddress, } impl Endpoint { @@ -692,10 +666,12 @@ impl Endpoint { ); // Connecting to ourselves is not supported. - ensure!(endpoint_addr.endpoint_id != self.id(), SelfConnectSnafu); + n0_error::ensure!(endpoint_addr.endpoint_id != self.id(), e!(ConnectWithOptsError::SelfConnect)); if !endpoint_addr.is_empty() { - self.add_endpoint_addr(endpoint_addr.clone(), Source::App)?; + self + .add_endpoint_addr(endpoint_addr.clone(), Source::App) + .map_err(|err| e!(ConnectWithOptsError::AddEndpointAddr { source: err }))?; } let endpoint_id = endpoint_addr.endpoint_id; let direct_addresses = endpoint_addr.direct_addresses.clone(); @@ -708,7 +684,7 @@ impl Endpoint { let (mapped_addr, _discovery_drop_guard) = self .get_mapping_addr_and_maybe_start_discovery(endpoint_addr) .await - .context(NoAddressSnafu)?; + .map_err(|err| e!(ConnectWithOptsError::NoAddress { source: err }))?; let transport_config = options .transport_config @@ -744,7 +720,7 @@ impl Endpoint { mapped_addr.private_socket_addr(), server_name, ) - .context(QuinnSnafu)?; + .map_err(|err| e!(ConnectWithOptsError::Quinn { source: err }))?; Ok(Connecting { inner: connect, @@ -798,8 +774,9 @@ impl Endpoint { endpoint_addr: EndpointAddr, source: Source, ) -> Result<(), AddEndpointAddrError> { - // Connecting to ourselves is not supported. - snafu::ensure!(endpoint_addr.endpoint_id != self.id(), OwnAddressSnafu); + if endpoint_addr.endpoint_id == self.id() { + return Err(OwnAddressSnafu.build()); + } self.msock.add_endpoint_addr(endpoint_addr, source) } @@ -1294,15 +1271,16 @@ impl Endpoint { // only then continue, because otherwise we wouldn't have any // path to the remote endpoint. let res = DiscoveryTask::start(self.clone(), endpoint_id); - let mut discovery = res.context(get_mapping_address_error::DiscoveryStartSnafu)?; + let mut discovery = res + .map_err(|source| e!(GetMappingAddressError::DiscoveryStart { source }))?; discovery .first_arrived() .await - .context(get_mapping_address_error::DiscoverSnafu)?; + .map_err(|source| e!(GetMappingAddressError::Discover { source }))?; if let Some(addr) = self.msock.get_mapping_addr(endpoint_id) { Ok((addr, Some(discovery))) } else { - Err(get_mapping_address_error::NoAddressSnafu.build()) + Err!(GetMappingAddressError::NoAddress) } } } @@ -1530,20 +1508,17 @@ pub struct Connecting { } #[allow(missing_docs)] -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] +#[error(from_sources, std_sources)] #[non_exhaustive] pub enum AlpnError { - #[snafu(transparent)] - ConnectionError { source: ConnectionError }, - #[snafu(display("No ALPN available"))] - Unavailable {}, - #[snafu(display("Unknown handshake type"))] - UnknownHandshake {}, + #[error(transparent)] + ConnectionError { #[error(std_err)] source: ConnectionError }, + #[display("No ALPN available")] + Unavailable, + #[display("Unknown handshake type")] + UnknownHandshake, } impl Connecting { @@ -1630,9 +1605,9 @@ impl Connecting { match data.downcast::() { Ok(data) => match data.protocol { Some(protocol) => Ok(protocol), - None => Err(UnavailableSnafu.build()), + None => Err!(AlpnError::Unavailable), }, - Err(_) => Err(UnknownHandshakeSnafu.build()), + Err(_) => Err!(AlpnError::UnknownHandshake), } } } @@ -1698,11 +1673,10 @@ pub struct Connection { } #[allow(missing_docs)] -#[derive(Debug, Snafu)] -#[snafu(display("Protocol error: no remote id available"))] -pub struct RemoteEndpointIdError { - backtrace: Option, -} +#[add_meta] +#[derive(Error)] +#[display("Protocol error: no remote id available")] +pub struct RemoteEndpointIdError; impl Connection { /// Initiates a new outgoing unidirectional stream. @@ -1924,7 +1898,7 @@ impl Connection { match data { None => { warn!("no peer certificate found"); - Err(RemoteEndpointIdSnafu.build()) + Err!(RemoteEndpointIdError) } Some(data) => match data.downcast::>() { Ok(certs) => { @@ -1933,19 +1907,19 @@ impl Connection { "expected a single peer certificate, but {} found", certs.len() ); - return Err(RemoteEndpointIdSnafu.build()); + return Err!(RemoteEndpointIdError); } let peer_id = EndpointId::from_verifying_key( VerifyingKey::from_public_key_der(&certs[0]) - .map_err(|_| RemoteEndpointIdSnafu.build())?, + .map_err(|_| e!(RemoteEndpointIdError))?, ); Ok(peer_id) } Err(err) => { warn!("invalid peer certificate: {:?}", err); - Err(RemoteEndpointIdSnafu.build()) + Err!(RemoteEndpointIdError) } }, } diff --git a/iroh/src/key.rs b/iroh/src/key.rs index 64f8d8bb051..bc720db161b 100644 --- a/iroh/src/key.rs +++ b/iroh/src/key.rs @@ -4,8 +4,7 @@ use std::fmt::Debug; use aead::{AeadCore, AeadInOut, Buffer}; use iroh_base::{PublicKey, SecretKey}; -use nested_enum_utils::common_fields; -use snafu::{ResultExt, Snafu, ensure}; +use n0_error::{add_meta, Error, e}; pub(crate) const NONCE_LEN: usize = 24; @@ -25,20 +24,17 @@ pub(super) fn secret_ed_box(key: &SecretKey) -> crypto_box::SecretKey { pub struct SharedSecret(crypto_box::ChaChaBox); /// Errors that can occur during [`SharedSecret::open`]. -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] +#[error(from_sources, std_sources)] #[non_exhaustive] pub enum DecryptionError { /// The nonce had the wrong size. - #[snafu(display("Invalid nonce"))] - InvalidNonce {}, + #[display("Invalid nonce")] + InvalidNonce, /// AEAD decryption failed. - #[snafu(display("Aead error"))] - Aead { source: aead::Error }, + #[display("Aead error")] + Aead { #[error(std_err)] source: aead::Error }, } impl Debug for SharedSecret { @@ -66,17 +62,16 @@ impl SharedSecret { /// Opens the ciphertext, which must have been created using `Self::seal`, and places the clear text into the provided buffer. pub fn open(&self, buffer: &mut dyn Buffer) -> Result<(), DecryptionError> { - ensure!(buffer.len() >= NONCE_LEN, InvalidNonceSnafu); + n0_error::ensure!(buffer.len() >= NONCE_LEN, e!(DecryptionError::InvalidNonce)); let offset = buffer.len() - NONCE_LEN; let nonce: [u8; NONCE_LEN] = buffer.as_ref()[offset..] .try_into() - .map_err(|_| InvalidNonceSnafu.build())?; + .map_err(|_| e!(DecryptionError::InvalidNonce))?; buffer.truncate(offset); self.0 - .decrypt_in_place(&nonce.into(), AEAD_DATA, buffer) - .context(AeadSnafu)?; + .decrypt_in_place(&nonce.into(), AEAD_DATA, buffer)?; Ok(()) } diff --git a/iroh/src/net_report.rs b/iroh/src/net_report.rs index 8b640602461..3b6026ab74d 100644 --- a/iroh/src/net_report.rs +++ b/iroh/src/net_report.rs @@ -39,6 +39,7 @@ use n0_future::{ time::{self, Duration, Instant}, }; use n0_watcher::{Watchable, Watcher}; +use n0_error::e; use tokio::task::JoinSet; use tokio_util::sync::CancellationToken; use tracing::{debug, trace, warn}; @@ -78,6 +79,22 @@ pub(crate) mod portmapper { pub(crate) use ip_mapped_addrs::{IpMappedAddr, IpMappedAddresses}; pub(crate) use self::reportgen::IfStateDetails; +#[cfg(not(wasm_browser))] +#[allow(missing_docs)] +#[n0_error::add_meta] +#[derive(n0_error::Error)] +#[non_exhaustive] +enum QadProbeError { + #[display("Failed to resolve relay address")] + GetRelayAddr { source: self::reportgen::GetRelayAddrError }, + #[display("Missing host in relay URL")] + MissingHost, + #[display("QUIC connection failed")] + Quic { source: iroh_relay::quic::Error }, + #[display("Receiver dropped")] + ReceiverDropped, +} + #[cfg(not(wasm_browser))] use self::reportgen::SocketState; pub use self::{ @@ -759,23 +776,30 @@ async fn run_probe_v4( relay: Arc, quic_client: QuicClient, dns_resolver: DnsResolver, -) -> n0_snafu::Result<(QadProbeReport, QadConn)> { - use n0_snafu::ResultExt; + ) -> n0_error::Result<(QadProbeReport, QadConn), QadProbeError> { - let relay_addr_orig = reportgen::get_relay_addr_ipv4(&dns_resolver, &relay).await?; + let relay_addr_orig = reportgen::get_relay_addr_ipv4(&dns_resolver, &relay) + .await + .map_err(|source| e!(QadProbeError::GetRelayAddr { source }))?; let relay_addr = reportgen::maybe_to_mapped_addr(ip_mapped_addrs.as_ref(), relay_addr_orig.into()); debug!(?relay_addr_orig, ?relay_addr, "relay addr v4"); - let host = relay.url.host_str().context("missing host url")?; - let conn = quic_client.create_conn(relay_addr, host).await?; + let host = relay + .url + .host_str() + .ok_or_else(|| e!(QadProbeError::MissingHost))?; + let conn = quic_client + .create_conn(relay_addr, host) + .await + .map_err(|source| e!(QadProbeError::Quic { source }))?; let mut receiver = conn.observed_external_addr(); // wait for an addr let addr = receiver .wait_for(|addr| addr.is_some()) .await - .context("receiver dropped")? + .map_err(|_| e!(QadProbeError::ReceiverDropped))? .expect("known"); let report = QadProbeReport { relay: relay.url.clone(), @@ -827,22 +851,29 @@ async fn run_probe_v6( relay: Arc, quic_client: QuicClient, dns_resolver: DnsResolver, -) -> n0_snafu::Result<(QadProbeReport, QadConn)> { - use n0_snafu::ResultExt; - let relay_addr_orig = reportgen::get_relay_addr_ipv6(&dns_resolver, &relay).await?; +) -> n0_error::Result<(QadProbeReport, QadConn), QadProbeError> { + let relay_addr_orig = reportgen::get_relay_addr_ipv6(&dns_resolver, &relay) + .await + .map_err(|source| e!(QadProbeError::GetRelayAddr { source }))?; let relay_addr = reportgen::maybe_to_mapped_addr(ip_mapped_addrs.as_ref(), relay_addr_orig.into()); debug!(?relay_addr_orig, ?relay_addr, "relay addr v6"); - let host = relay.url.host_str().context("missing host url")?; - let conn = quic_client.create_conn(relay_addr, host).await?; + let host = relay + .url + .host_str() + .ok_or_else(|| e!(QadProbeError::MissingHost))?; + let conn = quic_client + .create_conn(relay_addr, host) + .await + .map_err(|source| e!(QadProbeError::Quic { source }))?; let mut receiver = conn.observed_external_addr(); // wait for an addr let addr = receiver .wait_for(|addr| addr.is_some()) .await - .context("receiver dropped")? + .map_err(|_| e!(QadProbeError::ReceiverDropped))? .expect("known"); let report = QadProbeReport { relay: relay.url.clone(), diff --git a/iroh/src/net_report/reportgen.rs b/iroh/src/net_report/reportgen.rs index 334e5371e67..963af987367 100644 --- a/iroh/src/net_report/reportgen.rs +++ b/iroh/src/net_report/reportgen.rs @@ -30,7 +30,7 @@ use iroh_relay::{ }; #[cfg(not(wasm_browser))] use iroh_relay::{ - dns::{DnsError, DnsResolver, StaggeredError}, + dns::{DnsError, DnsResolver, DnsStaggeredError as StaggeredError}, quic::QuicClient, }; #[cfg(wasm_browser)] @@ -40,8 +40,9 @@ use n0_future::{ task::{self, AbortOnDropHandle, JoinSet}, time::{self, Duration, Instant}, }; +use n0_error::Err; use rand::seq::IteratorRandom; -use snafu::{IntoError, OptionExt, ResultExt, Snafu}; +use n0_error::{add_meta, Error, e}; use tokio::sync::mpsc; use tokio_util::sync::CancellationToken; use tracing::{Instrument, debug, error, trace, warn, warn_span}; @@ -176,17 +177,17 @@ struct Actor { } #[allow(missing_docs)] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] -#[snafu(module)] pub(super) enum ProbesError { - #[snafu(display("Probe failed"))] + #[display("Probe failed")] ProbeFailure { source: ProbeError }, - #[snafu(display("All probes failed"))] + #[display("All probes failed")] AllProbesFailed, - #[snafu(display("Probe cancelled"))] + #[display("Probe cancelled")] Cancelled, - #[snafu(display("Probe timed out"))] + #[display("Probe timed out")] Timeout, } @@ -300,8 +301,8 @@ impl Actor { Some(Ok(Ok(found))) => Some(found), Some(Ok(Err(err))) => { match err { - CaptivePortalError::CreateReqwestClient { source } - | CaptivePortalError::HttpRequest { source } + CaptivePortalError::CreateReqwestClient { source, .. } + | CaptivePortalError::HttpRequest { source, .. } if source.is_connect() => { debug!("check_captive_portal failed: {source:#}"); @@ -385,12 +386,12 @@ impl Actor { Some(Ok(Ok(report))) => Ok(report), Some(Ok(Err(err))) => { warn!("probe failed: {:#}", err); - Err(probes_error::ProbeFailureSnafu {}.into_error(err)) + Err!(ProbesError::ProbeFailure { source: err }) } Some(Err(time::Elapsed { .. })) => { - Err(probes_error::TimeoutSnafu.build()) + Err!(ProbesError::Timeout) } - None => Err(probes_error::CancelledSnafu.build()), + None => Err!(ProbesError::Cancelled), }; ProbeFinished::Regular(res) } @@ -450,26 +451,26 @@ pub(super) struct HttpsProbeReport { } #[allow(missing_docs)] -#[derive(Debug, Snafu)] -#[snafu(module)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] pub(super) enum ProbeError { - #[snafu(display("Client is gone"))] + #[display("Client is gone")] ClientGone, - #[snafu(display("Probe is no longer useful"))] + #[display("Probe is no longer useful")] NotUseful, - #[snafu(display("Failed to run HTTPS probe"))] + #[display("Failed to run HTTPS probe")] Https { source: MeasureHttpsLatencyError }, } #[allow(missing_docs)] -#[derive(Debug, Snafu)] -#[snafu(module)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] pub(super) enum QuicError { - #[snafu(display("No relay available"))] + #[display("No relay available")] NoRelay, - #[snafu(display("URL must have 'host' to use QUIC address discovery probes"))] + #[display("URL must have 'host' to use QUIC address discovery probes")] InvalidUrl, } @@ -514,7 +515,7 @@ impl Probe { .await { Ok(report) => Ok(ProbeReport::Https(report)), - Err(err) => Err(probe_error::HttpsSnafu.into_error(err)), + Err(err) => Err!(ProbeError::Https { source: err }), } } #[cfg(not(wasm_browser))] @@ -535,16 +536,16 @@ pub(super) fn maybe_to_mapped_addr( } #[cfg(not(wasm_browser))] -#[derive(Debug, Snafu)] -#[snafu(module)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] enum CaptivePortalError { - #[snafu(transparent)] - DnsLookup { source: StaggeredError }, - #[snafu(display("Creating HTTP client failed"))] - CreateReqwestClient { source: reqwest::Error }, - #[snafu(display("HTTP request failed"))] - HttpRequest { source: reqwest::Error }, + #[error(transparent)] + DnsLookup { source: iroh_relay::dns::DnsStaggeredError }, + #[display("Creating HTTP client failed")] + CreateReqwestClient { #[error(std_err)] source: reqwest::Error }, + #[display("HTTP request failed")] + HttpRequest { #[error(std_err)] source: reqwest::Error }, } /// Reports whether or not we think the system is behind a @@ -590,14 +591,15 @@ async fn check_captive_portal( // them. But our resolver doesn't support that yet. let addrs: Vec<_> = dns_resolver .lookup_ipv4_ipv6_staggered(domain, DNS_TIMEOUT, DNS_STAGGERING_MS) - .await? + .await + .map_err(|source| e!(CaptivePortalError::DnsLookup { source }))? .map(|ipaddr| SocketAddr::new(ipaddr, 0)) .collect(); builder = builder.resolve_to_addrs(domain, &addrs); } let client = builder .build() - .context(captive_portal_error::CreateReqwestClientSnafu)?; + .map_err(|source| e!(CaptivePortalError::CreateReqwestClient { source }))?; // Note: the set of valid characters in a challenge and the total // length is limited; see is_challenge_char in bin/iroh-relay for more @@ -611,7 +613,7 @@ async fn check_captive_portal( .header("X-Iroh-Challenge", &challenge) .send() .await - .context(captive_portal_error::HttpRequestSnafu)?; + .map_err(|source| e!(CaptivePortalError::HttpRequest { source }))?; let expected_response = format!("response {challenge}"); let is_valid_response = res @@ -646,21 +648,21 @@ fn get_quic_port(relay: &RelayConfig) -> Option { } #[cfg(not(wasm_browser))] -#[derive(Debug, Snafu)] -#[snafu(module)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] pub enum GetRelayAddrError { - #[snafu(display("No valid hostname in the relay URL"))] + #[display("No valid hostname in the relay URL")] InvalidHostname, - #[snafu(display("No suitable relay address found"))] + #[display("No suitable relay address found")] NoAddrFound, - #[snafu(display("DNS lookup failed"))] - DnsLookup { source: StaggeredError }, - #[snafu(display("Relay is not suitable"))] + #[display("DNS lookup failed")] + DnsLookup { source: iroh_relay::dns::DnsStaggeredError }, + #[display("Relay is not suitable")] UnsupportedRelay, - #[snafu(display("HTTPS probes are not implemented"))] + #[display("HTTPS probes are not implemented")] UnsupportedHttps, - #[snafu(display("No port available for this protocol"))] + #[display("No port available for this protocol")] MissingPort, } @@ -670,7 +672,7 @@ pub(super) async fn get_relay_addr_ipv4( dns_resolver: &DnsResolver, relay: &RelayConfig, ) -> Result { - let port = get_quic_port(relay).context(get_relay_addr_error::MissingPortSnafu)?; + let port = get_quic_port(relay).ok_or_else(|| e!(GetRelayAddrError::MissingPort))?; relay_lookup_ipv4_staggered(dns_resolver, relay, port).await } @@ -679,7 +681,7 @@ pub(super) async fn get_relay_addr_ipv6( dns_resolver: &DnsResolver, relay: &RelayConfig, ) -> Result { - let port = get_quic_port(relay).context(get_relay_addr_error::MissingPortSnafu)?; + let port = get_quic_port(relay).ok_or_else(|| e!(GetRelayAddrError::MissingPort))?; relay_lookup_ipv6_staggered(dns_resolver, relay, port).await } @@ -706,13 +708,13 @@ async fn relay_lookup_ipv4_staggered( IpAddr::V4(ip) => SocketAddrV4::new(ip, port), IpAddr::V6(_) => unreachable!("bad DNS lookup: {:?}", addr), }) - .ok_or(get_relay_addr_error::NoAddrFoundSnafu.build()), - Err(err) => Err(get_relay_addr_error::DnsLookupSnafu.into_error(err)), + .ok_or_else(|| e!(GetRelayAddrError::NoAddrFound)), + Err(err) => Err!(GetRelayAddrError::DnsLookup { source: err }), } } Some(url::Host::Ipv4(addr)) => Ok(SocketAddrV4::new(addr, port)), - Some(url::Host::Ipv6(_addr)) => Err(get_relay_addr_error::NoAddrFoundSnafu.build()), - None => Err(get_relay_addr_error::InvalidHostnameSnafu.build()), + Some(url::Host::Ipv6(_addr)) => Err!(GetRelayAddrError::NoAddrFound), + None => Err!(GetRelayAddrError::InvalidHostname), } } @@ -738,30 +740,30 @@ async fn relay_lookup_ipv6_staggered( IpAddr::V4(_) => unreachable!("bad DNS lookup: {:?}", addr), IpAddr::V6(ip) => SocketAddrV6::new(ip, port, 0, 0), }) - .ok_or(get_relay_addr_error::NoAddrFoundSnafu.build()), - Err(err) => Err(get_relay_addr_error::DnsLookupSnafu.into_error(err)), + .ok_or_else(|| e!(GetRelayAddrError::NoAddrFound)), + Err(err) => Err!(GetRelayAddrError::DnsLookup { source: err }), } } - Some(url::Host::Ipv4(_addr)) => Err(get_relay_addr_error::NoAddrFoundSnafu.build()), + Some(url::Host::Ipv4(_addr)) => Err!(GetRelayAddrError::NoAddrFound), Some(url::Host::Ipv6(addr)) => Ok(SocketAddrV6::new(addr, port, 0, 0)), - None => Err(get_relay_addr_error::InvalidHostnameSnafu.build()), + None => Err!(GetRelayAddrError::InvalidHostname), } } -#[derive(Debug, Snafu)] -#[snafu(module)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] pub enum MeasureHttpsLatencyError { - #[snafu(transparent)] - InvalidUrl { source: url::ParseError }, + #[error(transparent)] + InvalidUrl { #[error(std_err)] source: url::ParseError }, #[cfg(not(wasm_browser))] - #[snafu(transparent)] - DnsLookup { source: StaggeredError }, - #[snafu(display("Creating HTTP client failed"))] - CreateReqwestClient { source: reqwest::Error }, - #[snafu(display("HTTP request failed"))] - HttpRequest { source: reqwest::Error }, - #[snafu(display("Error response from server {status}: {:?}", status.canonical_reason()))] + #[error(transparent)] + DnsLookup { source: iroh_relay::dns::DnsStaggeredError }, + #[display("Creating HTTP client failed")] + CreateReqwestClient { #[error(std_err)] source: reqwest::Error }, + #[display("HTTP request failed")] + HttpRequest { #[error(std_err)] source: reqwest::Error }, + #[display("Error response from server {status}: {:?}", status.canonical_reason())] InvalidResponse { status: StatusCode }, } @@ -776,7 +778,9 @@ async fn run_https_probe( #[cfg(any(test, feature = "test-utils"))] insecure_skip_relay_cert_verify: bool, ) -> Result { trace!("HTTPS probe start"); - let url = relay.join(RELAY_PROBE_PATH)?; + let url = relay + .join(RELAY_PROBE_PATH) + .map_err(|source| e!(MeasureHttpsLatencyError::InvalidUrl { source }))?; // This should also use same connection establishment as relay client itself, which // needs to be more configurable so users can do more crazy things: @@ -799,7 +803,8 @@ async fn run_https_probe( // IPv6 though. But our resolver does not have a function for that yet. let addrs: Vec<_> = dns_resolver .lookup_ipv4_ipv6_staggered(domain, DNS_TIMEOUT, DNS_STAGGERING_MS) - .await? + .await + .map_err(|source| e!(MeasureHttpsLatencyError::DnsLookup { source }))? .map(|ipaddr| SocketAddr::new(ipaddr, 0)) .collect(); trace!(?addrs, "resolved addrs"); @@ -811,14 +816,14 @@ async fn run_https_probe( let client = builder .build() - .context(measure_https_latency_error::CreateReqwestClientSnafu)?; + .map_err(|source| e!(MeasureHttpsLatencyError::CreateReqwestClient { source }))?; let start = Instant::now(); let response = client .request(reqwest::Method::GET, url) .send() .await - .context(measure_https_latency_error::HttpRequestSnafu)?; + .map_err(|source| e!(MeasureHttpsLatencyError::HttpRequest { source }))?; let latency = start.elapsed(); if response.status().is_success() { // Drain the response body to be nice to the server, up to a limit. @@ -835,10 +840,7 @@ async fn run_https_probe( Ok(HttpsProbeReport { relay, latency }) } else { - Err(measure_https_latency_error::InvalidResponseSnafu { - status: response.status(), - } - .build()) + Err!(MeasureHttpsLatencyError::InvalidResponse { status: response.status() }) } } diff --git a/iroh/src/protocol.rs b/iroh/src/protocol.rs index 1a1f782b66e..37397512ab5 100644 --- a/iroh/src/protocol.rs +++ b/iroh/src/protocol.rs @@ -47,7 +47,7 @@ use n0_future::{ join_all, task::{self, AbortOnDropHandle, JoinSet}, }; -use snafu::{Backtrace, Snafu}; +use n0_error::{add_meta, Error, e, AnyError, Err}; use tokio_util::sync::CancellationToken; use tracing::{Instrument, error, field::Empty, info_span, trace, warn}; @@ -70,10 +70,10 @@ use crate::{ /// /// ```no_run /// # use std::sync::Arc; -/// # use n0_snafu::ResultExt; +/// # use n0_error::StdResultExt; /// # use iroh::{endpoint::Connecting, protocol::{ProtocolHandler, Router}, Endpoint, EndpointAddr}; /// # -/// # async fn test_compile() -> n0_snafu::Result<()> { +/// # async fn test_compile() -> n0_error::Result<()> { /// let endpoint = Endpoint::bind().await?; /// /// let router = Router::builder(endpoint) @@ -81,8 +81,8 @@ use crate::{ /// .spawn(); /// /// // wait until the user wants to -/// tokio::signal::ctrl_c().await.context("ctrl+c")?; -/// router.shutdown().await.context("shutdown")?; +/// tokio::signal::ctrl_c().await.std_context("ctrl+c")?; +/// router.shutdown().await.std_context("shutdown")?; /// # Ok(()) /// # } /// ``` @@ -102,33 +102,25 @@ pub struct RouterBuilder { } #[allow(missing_docs)] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] +#[error(from_sources, std_sources)] #[non_exhaustive] pub enum AcceptError { - #[snafu(transparent)] - Connection { - source: crate::endpoint::ConnectionError, - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, - }, - #[snafu(transparent)] + #[error(transparent)] + Connection { source: crate::endpoint::ConnectionError }, + #[error(transparent)] MissingRemoteEndpointId { source: RemoteEndpointIdError }, - #[snafu(display("Not allowed."))] + #[display("Not allowed.")] NotAllowed {}, - - #[snafu(transparent)] - User { - source: Box, - }, + #[error(transparent)] + User { source: AnyError }, } impl AcceptError { /// Creates a new user error from an arbitrary error type. pub fn from_err(value: T) -> Self { - Self::User { - source: Box::new(value), - } + e!(AcceptError::User { source: AnyError::from_std(value) }) } } @@ -562,7 +554,7 @@ impl ProtocolHandler for AccessLimit

{ let is_allowed = (self.limiter)(remote); if !is_allowed { conn.close(0u32.into(), b"not allowed"); - return Err(NotAllowedSnafu.build()); + return Err!(AcceptError::NotAllowed); } self.proto.accept(conn).await?; Ok(()) @@ -577,7 +569,7 @@ impl ProtocolHandler for AccessLimit

{ mod tests { use std::{sync::Mutex, time::Duration}; - use n0_snafu::{Result, ResultExt}; + use n0_error::{Result, StdResultExt}; use quinn::ApplicationClose; use super::*; From 54fef340e6690cdeb99bb78c02e06bf99e8284dd Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 14:58:45 +0200 Subject: [PATCH 06/58] fmt --- iroh-relay/src/client.rs | 59 ++++++++++++++++++++----- iroh-relay/src/client/conn.rs | 12 +++-- iroh-relay/src/client/tls.rs | 39 ++++++++++++---- iroh-relay/src/dns.rs | 66 +++++++++++++++++++++------- iroh-relay/src/endpoint_info.rs | 42 +++++++++++++----- iroh-relay/src/main.rs | 10 +++-- iroh-relay/src/protos/common.rs | 16 ++++--- iroh-relay/src/protos/handshake.rs | 58 ++++++++++++++++++------ iroh-relay/src/protos/relay.rs | 12 +++-- iroh-relay/src/quic.rs | 37 +++++++++++----- iroh-relay/src/server.rs | 50 ++++++++++++++++----- iroh-relay/src/server/client.rs | 17 ++++--- iroh-relay/src/server/http_server.rs | 65 ++++++++++++++++++++------- iroh-relay/src/server/streams.rs | 25 ++++++++--- iroh/src/disco.rs | 11 +++-- iroh/src/discovery.rs | 40 +++++++++++++---- iroh/src/endpoint.rs | 42 +++++++++++++----- iroh/src/key.rs | 10 +++-- iroh/src/net_report.rs | 9 ++-- iroh/src/net_report/reportgen.rs | 44 ++++++++++++++----- iroh/src/protocol.rs | 10 +++-- 21 files changed, 505 insertions(+), 169 deletions(-) diff --git a/iroh-relay/src/client.rs b/iroh-relay/src/client.rs index 11d734f8a2f..781672b3faa 100644 --- a/iroh-relay/src/client.rs +++ b/iroh-relay/src/client.rs @@ -11,12 +11,12 @@ use std::{ use conn::Conn; use iroh_base::{RelayUrl, SecretKey}; +use n0_error::{Err, Error, add_meta, e}; use n0_future::{ Sink, Stream, split::{SplitSink, SplitStream, split}, time, }; -use n0_error::{add_meta, Error, e, Err}; #[cfg(any(test, feature = "test-utils"))] use tracing::warn; use tracing::{Level, debug, event, trace}; @@ -66,19 +66,28 @@ pub enum ConnectError { source: ws_stream_wasm::WsErr, }, #[error(transparent)] - Handshake { #[error(std_err)] source: handshake::Error }, + Handshake { + #[error(std_err)] + source: handshake::Error, + }, #[error(transparent)] Dial { source: DialError }, #[display("Unexpected status during upgrade: {code}")] UnexpectedUpgradeStatus { code: hyper::StatusCode }, #[display("Failed to upgrade response")] - Upgrade { #[error(std_err)] source: hyper::Error }, + Upgrade { + #[error(std_err)] + source: hyper::Error, + }, #[display("Invalid TLS servername")] InvalidTlsServername {}, #[display("No local address available")] NoLocalAddr {}, #[display("tls connection failed")] - Tls { #[error(std_err)] source: std::io::Error }, + Tls { + #[error(std_err)] + source: std::io::Error, + }, #[cfg(wasm_browser)] #[display("The relay protocol is not available in browsers")] RelayProtoNotAvailable {}, @@ -95,11 +104,20 @@ pub enum DialError { InvalidTargetPort {}, #[error(transparent)] #[cfg(not(wasm_browser))] - Dns { #[error(std_err)] source: DnsError }, + Dns { + #[error(std_err)] + source: DnsError, + }, #[error(transparent)] - Timeout { #[error(std_err)] source: time::Elapsed }, + Timeout { + #[error(std_err)] + source: time::Elapsed, + }, #[error(transparent)] - Io { #[error(std_err)] source: std::io::Error }, + Io { + #[error(std_err)] + source: std::io::Error, + }, #[display("Invalid URL: {url}")] InvalidUrl { url: Url }, #[display("Failed proxy connection: {status}")] @@ -107,7 +125,10 @@ pub enum DialError { #[display("Invalid Proxy URL {proxy_url}")] ProxyInvalidUrl { proxy_url: Url }, #[display("failed to establish proxy connection")] - ProxyConnect { #[error(std_err)] source: hyper::Error }, + ProxyConnect { + #[error(std_err)] + source: hyper::Error, + }, #[display("Invalid proxy TLS servername: {proxy_hostname}")] ProxyInvalidTlsServername { proxy_hostname: String }, #[display("Invalid proxy target port")] @@ -214,7 +235,11 @@ impl ClientBuilder { "ws" => "ws", _ => "wss", }) - .map_err(|_| e!(ConnectError::InvalidWebsocketUrl { url: dial_url.clone() }))?; + .map_err(|_| { + e!(ConnectError::InvalidWebsocketUrl { + url: dial_url.clone() + }) + })?; debug!(%dial_url, "Dialing relay by websocket"); @@ -235,7 +260,11 @@ impl ClientBuilder { .map_err(|_| e!(ConnectError::NoLocalAddr))?; let mut builder = tokio_websockets::ClientBuilder::new() .uri(dial_url.as_str()) - .map_err(|_| e!(ConnectError::InvalidRelayUrl { url: dial_url.clone() }))? + .map_err(|_| { + e!(ConnectError::InvalidRelayUrl { + url: dial_url.clone() + }) + })? .add_header( SEC_WEBSOCKET_PROTOCOL, http::HeaderValue::from_static(RELAY_PROTOCOL_VERSION), @@ -257,7 +286,9 @@ impl ClientBuilder { let (conn, response) = builder.connect_on(stream).await?; if response.status() != hyper::StatusCode::SWITCHING_PROTOCOLS { - return Err!(ConnectError::UnexpectedUpgradeStatus { code: response.status() }); + return Err!(ConnectError::UnexpectedUpgradeStatus { + code: response.status() + }); } let conn = Conn::new(conn, self.key_cache.clone(), &self.secret_key).await?; @@ -304,7 +335,11 @@ impl ClientBuilder { "ws" => "ws", _ => "wss", }) - .map_err(|_| e!(ConnectError::InvalidWebsocketUrl { url: dial_url.clone() }))?; + .map_err(|_| { + e!(ConnectError::InvalidWebsocketUrl { + url: dial_url.clone() + }) + })?; debug!(%dial_url, "Dialing relay by websocket"); diff --git a/iroh-relay/src/client/conn.rs b/iroh-relay/src/client/conn.rs index 6d5d76eb75a..75742f4f97d 100644 --- a/iroh-relay/src/client/conn.rs +++ b/iroh-relay/src/client/conn.rs @@ -8,8 +8,8 @@ use std::{ }; use iroh_base::SecretKey; +use n0_error::{Error, add_meta}; use n0_future::{Sink, Stream}; -use n0_error::{add_meta, Error}; use tracing::debug; use super::KeyCache; @@ -139,9 +139,15 @@ impl Sink for Conn { fn start_send(mut self: Pin<&mut Self>, frame: ClientToRelayMsg) -> Result<(), Self::Error> { let size = frame.encoded_len(); - n0_error::ensure!(size <= MAX_PACKET_SIZE, n0_error::e!(SendError::ExceedsMaxPacketSize { size })); + n0_error::ensure!( + size <= MAX_PACKET_SIZE, + n0_error::e!(SendError::ExceedsMaxPacketSize { size }) + ); if let ClientToRelayMsg::Datagrams { datagrams, .. } = &frame { - n0_error::ensure!(!datagrams.contents.is_empty(), n0_error::e!(SendError::EmptyPacket)); + n0_error::ensure!( + !datagrams.contents.is_empty(), + n0_error::e!(SendError::EmptyPacket) + ); } Pin::new(&mut self.conn) diff --git a/iroh-relay/src/client/tls.rs b/iroh-relay/src/client/tls.rs index 084718c4ce5..eb71831c5d9 100644 --- a/iroh-relay/src/client/tls.rs +++ b/iroh-relay/src/client/tls.rs @@ -10,9 +10,9 @@ use bytes::Bytes; use data_encoding::BASE64URL; use http_body_util::Empty; use hyper::{Request, upgrade::Parts}; +use n0_error::{Err, e}; use n0_future::{task, time}; use rustls::client::Resumption; -use n0_error::{e, Err}; use tracing::error; use super::{ @@ -151,7 +151,8 @@ impl MaybeTlsStreamBuilder { let tcp_stream = time::timeout(DIAL_ENDPOINT_TIMEOUT, async move { TcpStream::connect(addr).await }) - .await.map_err(|err| e!(DialError::Timeout, err))??; + .await + .map_err(|err| e!(DialError::Timeout, err))??; tcp_stream.set_nodelay(true)?; @@ -174,7 +175,8 @@ impl MaybeTlsStreamBuilder { .resolve_host(&proxy_url, self.prefer_ipv6, DNS_TIMEOUT) .await?; - let proxy_port = url_port(&proxy_url).ok_or_else(|| e!(DialError::ProxyInvalidTargetPort))?; + let proxy_port = + url_port(&proxy_url).ok_or_else(|| e!(DialError::ProxyInvalidTargetPort))?; let proxy_addr = SocketAddr::new(proxy_ip, proxy_port); debug!(%proxy_addr, "connecting to proxy"); @@ -190,15 +192,27 @@ impl MaybeTlsStreamBuilder { let io = if proxy_url.scheme() == "http" { MaybeTlsStream::Raw(tcp_stream) } else { - let hostname = proxy_url.host_str().ok_or_else(|| e!(DialError::ProxyInvalidUrl { proxy_url: proxy_url.clone() }))?; + let hostname = proxy_url.host_str().ok_or_else(|| { + e!(DialError::ProxyInvalidUrl { + proxy_url: proxy_url.clone() + }) + })?; let hostname = - rustls::pki_types::ServerName::try_from(hostname.to_string()).map_err(|_| e!(DialError::ProxyInvalidTlsServername { proxy_hostname: hostname.to_string() }))?; + rustls::pki_types::ServerName::try_from(hostname.to_string()).map_err(|_| { + e!(DialError::ProxyInvalidTlsServername { + proxy_hostname: hostname.to_string() + }) + })?; let tls_stream = tls_connector.connect(hostname, tcp_stream).await?; MaybeTlsStream::Tls(tls_stream) }; let io = TokioIo::new(io); - let target_host = self.url.host_str().ok_or_else(|| e!(DialError::InvalidUrl { url: self.url.clone() }))?; + let target_host = self.url.host_str().ok_or_else(|| { + e!(DialError::InvalidUrl { + url: self.url.clone() + }) + })?; let port = url_port(&self.url).ok_or_else(|| e!(DialError::InvalidTargetPort))?; @@ -238,12 +252,19 @@ impl MaybeTlsStreamBuilder { } }); - let res = sender.send_request(req).await.map_err(|err| e!(DialError::ProxyConnect, err))?; + let res = sender + .send_request(req) + .await + .map_err(|err| e!(DialError::ProxyConnect, err))?; if !res.status().is_success() { - return Err!(DialError::ProxyConnectInvalidStatus { status: res.status() }); + return Err!(DialError::ProxyConnectInvalidStatus { + status: res.status() + }); } - let upgraded = hyper::upgrade::on(res).await.map_err(|err| e!(DialError::ProxyConnect, err))?; + let upgraded = hyper::upgrade::on(res) + .await + .map_err(|err| e!(DialError::ProxyConnect, err))?; let Parts { io, read_buf, .. } = upgraded .downcast::>>() .expect("only this upgrade used"); diff --git a/iroh-relay/src/dns.rs b/iroh-relay/src/dns.rs index ece0c0f04e0..7d7d44a0517 100644 --- a/iroh-relay/src/dns.rs +++ b/iroh-relay/src/dns.rs @@ -13,12 +13,12 @@ use hickory_resolver::{ name_server::TokioConnectionProvider, }; use iroh_base::EndpointId; +use n0_error::{Error, add_meta, e}; use n0_future::{ StreamExt, boxed::BoxFuture, time::{self, Duration}, }; -use n0_error::{add_meta, Error, e}; use tokio::sync::RwLock; use tracing::debug; use url::Url; @@ -68,15 +68,24 @@ pub type BoxIter = Box + Send + 'static>; #[non_exhaustive] pub enum DnsError { #[error(transparent)] - Timeout { #[error(std_err)] source: tokio::time::error::Elapsed }, + Timeout { + #[error(std_err)] + source: tokio::time::error::Elapsed, + }, #[display("No response")] NoResponse {}, #[display("Resolve failed ipv4: {ipv4}, ipv6 {ipv6}")] - ResolveBoth { ipv4: Box, ipv6: Box }, + ResolveBoth { + ipv4: Box, + ipv6: Box, + }, #[display("missing host")] MissingHost {}, #[error(transparent)] - Resolve { #[error(std_err)] source: hickory_resolver::ResolveError }, + Resolve { + #[error(std_err)] + source: hickory_resolver::ResolveError, + }, #[display("invalid DNS response: not a query for _iroh.z32encodedpubkey")] InvalidResponse {}, } @@ -88,7 +97,10 @@ pub enum DnsError { #[non_exhaustive] pub enum LookupError { #[display("Malformed txt from lookup")] - ParseError { #[error(std_err)] source: Box }, + ParseError { + #[error(std_err)] + source: Box, + }, #[display("Failed to resolve TXT record")] LookupFailed { source: DnsError }, } @@ -294,7 +306,10 @@ impl DnsResolver { (Ok(ipv4), Ok(ipv6)) => Ok(LookupIter::Both(ipv4.chain(ipv6))), (Ok(ipv4), Err(_)) => Ok(LookupIter::Ipv4(ipv4)), (Err(_), Ok(ipv6)) => Ok(LookupIter::Ipv6(ipv6)), - (Err(ipv4_err), Err(ipv6_err)) => Err(e!(DnsError::ResolveBoth { ipv4: Box::new(ipv4_err), ipv6: Box::new(ipv6_err) })), + (Err(ipv4_err), Err(ipv6_err)) => Err(e!(DnsError::ResolveBoth { + ipv4: Box::new(ipv4_err), + ipv6: Box::new(ipv6_err) + })), } } @@ -315,7 +330,10 @@ impl DnsResolver { ); let (v4, v6) = match lookup { (Err(ipv4_err), Err(ipv6_err)) => { - return Err(e!(DnsError::ResolveBoth { ipv4: Box::new(ipv4_err), ipv6: Box::new(ipv6_err) })); + return Err(e!(DnsError::ResolveBoth { + ipv4: Box::new(ipv4_err), + ipv6: Box::new(ipv6_err) + })); } (Err(_), Ok(mut v6)) => (None, v6.next()), (Ok(mut v4), Err(_)) => (v4.next(), None), @@ -346,7 +364,9 @@ impl DnsResolver { ) -> Result, DnsStaggeredError> { let host = host.to_string(); let f = || self.lookup_ipv4(host.clone(), timeout); - stagger_call(f, delays_ms).await.map_err(|errors| e!(DnsStaggeredError { errors })) + stagger_call(f, delays_ms) + .await + .map_err(|errors| e!(DnsStaggeredError { errors })) } /// Performs an IPv6 lookup with a timeout in a staggered fashion. @@ -363,7 +383,9 @@ impl DnsResolver { ) -> Result, DnsStaggeredError> { let host = host.to_string(); let f = || self.lookup_ipv6(host.clone(), timeout); - stagger_call(f, delays_ms).await.map_err(|errors| e!(DnsStaggeredError { errors })) + stagger_call(f, delays_ms) + .await + .map_err(|errors| e!(DnsStaggeredError { errors })) } /// Races an IPv4 and IPv6 lookup with a timeout in a staggered fashion. @@ -381,7 +403,9 @@ impl DnsResolver { ) -> Result, DnsStaggeredError> { let host = host.to_string(); let f = || self.lookup_ipv4_ipv6(host.clone(), timeout); - stagger_call(f, delays_ms).await.map_err(|errors| e!(DnsStaggeredError { errors })) + stagger_call(f, delays_ms) + .await + .map_err(|errors| e!(DnsStaggeredError { errors })) } /// Looks up endpoint info by [`EndpointId`] and origin domain name. @@ -399,8 +423,11 @@ impl DnsResolver { .lookup_txt(name.clone(), DNS_TIMEOUT) .await .map_err(|err| e!(LookupError::LookupFailed { source: err }))?; - let info = EndpointInfo::from_txt_lookup(name, lookup) - .map_err(|err| e!(LookupError::ParseError { source: Box::new(err) }))?; + let info = EndpointInfo::from_txt_lookup(name, lookup).map_err(|err| { + e!(LookupError::ParseError { + source: Box::new(err) + }) + })?; Ok(info) } @@ -414,8 +441,11 @@ impl DnsResolver { .lookup_txt(name.clone(), DNS_TIMEOUT) .await .map_err(|err| e!(LookupError::LookupFailed { source: err }))?; - let info = EndpointInfo::from_txt_lookup(name, lookup) - .map_err(|err| e!(LookupError::ParseError { source: Box::new(err) }))?; + let info = EndpointInfo::from_txt_lookup(name, lookup).map_err(|err| { + e!(LookupError::ParseError { + source: Box::new(err) + }) + })?; Ok(info) } @@ -431,7 +461,9 @@ impl DnsResolver { delays_ms: &[u64], ) -> Result { let f = || self.lookup_endpoint_by_domain_name(name); - stagger_call(f, delays_ms).await.map_err(|errors| e!(LookupStaggeredError { errors })) + stagger_call(f, delays_ms) + .await + .map_err(|errors| e!(LookupStaggeredError { errors })) } /// Looks up endpoint info by [`EndpointId`] and origin domain name. @@ -447,7 +479,9 @@ impl DnsResolver { delays_ms: &[u64], ) -> Result { let f = || self.lookup_endpoint_by_id(endpoint_id, origin); - stagger_call(f, delays_ms).await.map_err(|errors| e!(LookupStaggeredError { errors })) + stagger_call(f, delays_ms) + .await + .map_err(|errors| e!(LookupStaggeredError { errors })) } } diff --git a/iroh-relay/src/endpoint_info.rs b/iroh-relay/src/endpoint_info.rs index d4740121df9..e77eecea2a1 100644 --- a/iroh-relay/src/endpoint_info.rs +++ b/iroh-relay/src/endpoint_info.rs @@ -41,7 +41,7 @@ use std::{ }; use iroh_base::{EndpointAddr, EndpointId, KeyParsingError, RelayUrl, SecretKey}; -use n0_error::{add_meta, Error, e}; +use n0_error::{Error, add_meta, e}; use url::Url; /// The DNS name for the iroh TXT record. @@ -53,9 +53,15 @@ pub const IROH_TXT_NAME: &str = "_iroh"; #[non_exhaustive] pub enum EncodingError { #[error(transparent)] - FailedBuildingPacket { #[error(std_err)] source: pkarr::errors::SignedPacketBuildError }, + FailedBuildingPacket { + #[error(std_err)] + source: pkarr::errors::SignedPacketBuildError, + }, #[display("invalid TXT entry")] - InvalidTxtEntry { #[error(std_err)] source: pkarr::dns::SimpleDnsError }, + InvalidTxtEntry { + #[error(std_err)] + source: pkarr::dns::SimpleDnsError, + }, } #[allow(missing_docs)] @@ -64,7 +70,10 @@ pub enum EncodingError { #[non_exhaustive] pub enum DecodingError { #[display("endpoint id was not encoded in valid z32")] - InvalidEncodingZ32 { #[error(std_err)] source: z32::Z32Error }, + InvalidEncodingZ32 { + #[error(std_err)] + source: z32::Z32Error, + }, #[display("length must be 32 bytes, but got {len} byte(s)")] InvalidLength { len: usize }, #[display("endpoint id is not a valid public key")] @@ -91,7 +100,8 @@ impl EndpointIdExt for EndpointId { } fn from_z32(s: &str) -> Result { - let bytes = z32::decode(s.as_bytes()).map_err(|err| e!(DecodingError::InvalidEncodingZ32, err))?; + let bytes = + z32::decode(s.as_bytes()).map_err(|err| e!(DecodingError::InvalidEncodingZ32, err))?; let bytes: &[u8; 32] = &bytes .try_into() .map_err(|_| e!(DecodingError::InvalidLength { len: s.len() }))?; @@ -409,7 +419,10 @@ pub enum ParseError { #[display("Expected 2 labels, received {num_labels}")] NumLabels { num_labels: usize }, #[display("Could not parse labels")] - Utf8 { #[error(std_err)] source: Utf8Error }, + Utf8 { + #[error(std_err)] + source: Utf8Error, + }, #[display("Record is not an `iroh` record, expected `_iroh`, got `{label}`")] NotAnIrohRecord { label: String }, #[error(transparent)] @@ -443,7 +456,9 @@ fn endpoint_id_from_txt_name(name: &str) -> Result { let mut labels = name.split("."); let label = labels.next().expect("checked above"); if label != IROH_TXT_NAME { - return Err(e!(ParseError::NotAnIrohRecord { label: label.to_string() })); + return Err(e!(ParseError::NotAnIrohRecord { + label: label.to_string() + })); } let label = labels.next().expect("checked above"); let endpoint_id = EndpointId::from_z32(label)?; @@ -517,7 +532,11 @@ impl TxtAttrs { let (Some(key), Some(value)) = (parts.next(), parts.next()) else { return Err(e!(ParseError::UnexpectedFormat { s })); }; - let attr = T::from_str(key).map_err(|_| e!(ParseError::AttrFromString { key: key.to_string() }))?; + let attr = T::from_str(key).map_err(|_| { + e!(ParseError::AttrFromString { + key: key.to_string() + }) + })?; attrs.entry(attr).or_default().push(value.to_string()); } Ok(Self { attrs, endpoint_id }) @@ -593,10 +612,13 @@ impl TxtAttrs { let mut builder = pkarr::SignedPacket::builder(); for s in self.to_txt_strings() { let mut txt = rdata::TXT::new(); - txt.add_string(&s).map_err(|err| e!(EncodingError::InvalidTxtEntry, err))?; + txt.add_string(&s) + .map_err(|err| e!(EncodingError::InvalidTxtEntry, err))?; builder = builder.txt(name.clone(), txt.into_owned(), ttl); } - let signed_packet = builder.build(&keypair).map_err(|err| e!(EncodingError::FailedBuildingPacket, err))?; + let signed_packet = builder + .build(&keypair) + .map_err(|err| e!(EncodingError::FailedBuildingPacket, err))?; Ok(signed_packet) } } diff --git a/iroh-relay/src/main.rs b/iroh-relay/src/main.rs index af917fa72a8..5c571786145 100644 --- a/iroh-relay/src/main.rs +++ b/iroh-relay/src/main.rs @@ -74,12 +74,16 @@ fn load_secret_key( filename: impl AsRef, ) -> Result> { let filename = filename.as_ref(); - let keyfile = std::fs::File::open(filename) - .std_context(format!("cannot open secret key file {}", filename.display()))?; + let keyfile = std::fs::File::open(filename).std_context(format!( + "cannot open secret key file {}", + filename.display() + ))?; let mut reader = std::io::BufReader::new(keyfile); loop { - match rustls_pemfile::read_one(&mut reader).std_context("cannot parse secret key .pem file")? { + match rustls_pemfile::read_one(&mut reader) + .std_context("cannot parse secret key .pem file")? + { Some(rustls_pemfile::Item::Pkcs1Key(key)) => { return Ok(rustls::pki_types::PrivateKeyDer::Pkcs1(key)); } diff --git a/iroh-relay/src/protos/common.rs b/iroh-relay/src/protos/common.rs index 64f2fed4d1b..09c7bead6e9 100644 --- a/iroh-relay/src/protos/common.rs +++ b/iroh-relay/src/protos/common.rs @@ -4,8 +4,11 @@ //! integers for different frames. use bytes::{Buf, BufMut}; -use quinn_proto::{VarInt, coding::{Codec, UnexpectedEnd}}; -use n0_error::{add_meta, Error, e}; +use n0_error::{Error, add_meta, e}; +use quinn_proto::{ + VarInt, + coding::{Codec, UnexpectedEnd}, +}; /// Possible frame types during handshaking #[repr(u32)] @@ -57,9 +60,12 @@ pub enum FrameType { #[allow(missing_docs)] #[non_exhaustive] pub enum FrameTypeError { - #[display("not enough bytes to parse frame type")] - UnexpectedEnd { #[error(std_err)] source: UnexpectedEnd }, - #[display("frame type unknown")] + #[display("not enough bytes to parse frame type")] + UnexpectedEnd { + #[error(std_err)] + source: UnexpectedEnd, + }, + #[display("frame type unknown")] UnknownFrameType { tag: VarInt }, } diff --git a/iroh-relay/src/protos/handshake.rs b/iroh-relay/src/protos/handshake.rs index 8266f188e9a..92368a74ff7 100644 --- a/iroh-relay/src/protos/handshake.rs +++ b/iroh-relay/src/protos/handshake.rs @@ -31,11 +31,10 @@ use http::HeaderValue; #[cfg(feature = "server")] use iroh_base::Signature; use iroh_base::{PublicKey, SecretKey}; +use n0_error::{Err, Error, add_meta, e}; use n0_future::{SinkExt, TryStreamExt}; -use n0_error::{add_meta, Error, e, Err}; #[cfg(feature = "server")] use rand::CryptoRng; - use tracing::trace; use super::{ @@ -231,7 +230,14 @@ impl ClientAuth { let message = challenge.message_to_sign(); self.public_key .verify(&message, &Signature::from_bytes(&self.signature)) - .map_err(|err| e!(VerificationError::SignatureInvalid { source: err, message: message.to_vec(), signature: self.signature, public_key: self.public_key })) + .map_err(|err| { + e!(VerificationError::SignatureInvalid { + source: err, + message: message.to_vec(), + signature: self.signature, + public_key: self.public_key + }) + }) .map_err(Box::new) } } @@ -297,14 +303,24 @@ impl KeyMaterialClientAuth { let suffix: [u8; 16] = suffix.try_into().expect("hardcoded length"); n0_error::ensure!( suffix == self.key_material_suffix, - e!(VerificationError::MismatchedSuffix { expected: self.key_material_suffix, actual: suffix }) + e!(VerificationError::MismatchedSuffix { + expected: self.key_material_suffix, + actual: suffix + }) ); // NOTE: We don't blake3-hash here as we do it in [`ServerChallenge::message_to_sign`], // because we already have a domain separation string and keyed hashing step in // the TLS export keying material above. self.public_key .verify(message, &Signature::from_bytes(&self.signature)) - .map_err(|err| e!(VerificationError::SignatureInvalid { source: err, message: message.to_vec(), public_key: self.public_key, signature: self.signature })) + .map_err(|err| { + e!(VerificationError::SignatureInvalid { + source: err, + message: message.to_vec(), + public_key: self.public_key, + signature: self.signature + }) + }) .map_err(Box::new) } } @@ -340,7 +356,9 @@ pub(crate) async fn clientside( } FrameType::ServerDeniesAuth => { let denial: ServerDeniesAuth = deserialize_frame(frame)?; - Err!(Error::ServerDeniedAuth { reason: denial.reason }) + Err!(Error::ServerDeniedAuth { + reason: denial.reason + }) } _ => unreachable!(), } @@ -428,7 +446,9 @@ pub(crate) async fn serverside( reason: "signature invalid".into(), }; write_frame(io, denial.clone()).await?; - Err!(Error::ServerDeniedAuth { reason: denial.reason }) + Err!(Error::ServerDeniedAuth { + reason: denial.reason + }) } else { trace!(?client_auth.public_key, "authentication succeeded via challenge"); Ok(SuccessfulAuthentication { @@ -455,7 +475,9 @@ impl SuccessfulAuthentication { reason: "not authorized".into(), }; write_frame(io, denial.clone()).await?; - Err!(Error::ServerDeniedAuth { reason: denial.reason }) + Err!(Error::ServerDeniedAuth { + reason: denial.reason + }) } } } @@ -471,7 +493,9 @@ async fn write_frame( .expect("serialization failed") // buffer can't become "full" without being a critical failure, datastructures shouldn't ever fail serialization .into_inner() .freeze(); - io.send(bytes).await.map_err(|err| e!(Error::Websocket, err))?; + io.send(bytes) + .await + .map_err(|err| e!(Error::Websocket, err))?; io.flush().await.map_err(|err| e!(Error::Websocket, err))?; Ok(()) } @@ -486,19 +510,27 @@ async fn read_frame( .map_err(|err| e!(Error::Websocket, err))? .ok_or_else(|| e!(Error::UnexpectedEnd))?; - let frame_type = FrameType::from_bytes(&mut payload) - .map_err(|err| e!(Error::FrameTypeError, err))?; + let frame_type = + FrameType::from_bytes(&mut payload).map_err(|err| e!(Error::FrameTypeError, err))?; trace!(?frame_type, "Reading frame"); n0_error::ensure!( expected_types.contains(&frame_type), - e!(Error::UnexpectedFrameType { frame_type, expected_types: expected_types.to_vec() }) + e!(Error::UnexpectedFrameType { + frame_type, + expected_types: expected_types.to_vec() + }) ); Ok((frame_type, payload)) } fn deserialize_frame(frame: Bytes) -> Result { - postcard::from_bytes(&frame).map_err(|err| e!(Error::DeserializationError { frame_type: F::TAG, source: err })) + postcard::from_bytes(&frame).map_err(|err| { + e!(Error::DeserializationError { + frame_type: F::TAG, + source: err + }) + }) } #[cfg(all(test, feature = "server"))] diff --git a/iroh-relay/src/protos/relay.rs b/iroh-relay/src/protos/relay.rs index 242b6ed8052..91885057dba 100644 --- a/iroh-relay/src/protos/relay.rs +++ b/iroh-relay/src/protos/relay.rs @@ -11,8 +11,8 @@ use std::num::NonZeroU16; use bytes::{Buf, BufMut, Bytes, BytesMut}; use iroh_base::{EndpointId, KeyParsingError}; +use n0_error::{Err, Error, add_meta, e}; use n0_future::time::Duration; -use n0_error::{add_meta, Error, e, Err}; use super::common::{FrameType, FrameTypeError}; use crate::KeyCache; @@ -51,7 +51,10 @@ pub enum Error { #[display("Frame is too large, has {frame_len} bytes")] FrameTooLarge { frame_len: usize }, #[error(transparent)] - SerDe { #[error(std_err)] source: postcard::Error }, + SerDe { + #[error(std_err)] + source: postcard::Error, + }, #[error(transparent)] FrameTypeError { source: FrameTypeError }, #[display("Invalid public key")] @@ -61,7 +64,10 @@ pub enum Error { #[display("Invalid frame type: {frame_type:?}")] InvalidFrameType { frame_type: FrameType }, #[display("Invalid protocol message encoding")] - InvalidProtocolMessageEncoding { #[error(std_err)] source: std::str::Utf8Error }, + InvalidProtocolMessageEncoding { + #[error(std_err)] + source: std::str::Utf8Error, + }, #[display("Too few bytes")] TooSmall {}, } diff --git a/iroh-relay/src/quic.rs b/iroh-relay/src/quic.rs index ad5879bc72c..0060ea871fe 100644 --- a/iroh-relay/src/quic.rs +++ b/iroh-relay/src/quic.rs @@ -2,10 +2,9 @@ //! for QUIC address discovery. use std::{net::SocketAddr, sync::Arc}; +use n0_error::{Error, add_meta}; use n0_future::time::Duration; -use n0_error::{add_meta, Error}; use quinn::{VarInt, crypto::rustls::QuicClientConfig}; - use tokio::sync::watch; /// ALPN for our quic addr discovery @@ -17,11 +16,11 @@ pub const QUIC_ADDR_DISC_CLOSE_REASON: &[u8] = b"finished"; #[cfg(feature = "server")] pub(crate) mod server { + use n0_error::StdResultExt; use quinn::{ ApplicationClose, ConnectionError, crypto::rustls::{NoInitialCipherSuite, QuicServerConfig}, }; - use n0_error::StdResultExt; use tokio::task::JoinSet; use tokio_util::{sync::CancellationToken, task::AbortOnDropHandle}; use tracing::{Instrument, debug, info, info_span}; @@ -42,11 +41,20 @@ pub(crate) mod server { #[non_exhaustive] pub enum QuicSpawnError { #[error(transparent)] - NoInitialCipherSuite { #[error(std_err)] source: NoInitialCipherSuite }, + NoInitialCipherSuite { + #[error(std_err)] + source: NoInitialCipherSuite, + }, #[display("Unable to spawn a QUIC endpoint server")] - EndpointServer { #[error(std_err)] source: std::io::Error }, + EndpointServer { + #[error(std_err)] + source: std::io::Error, + }, #[display("Unable to get the local address from the endpoint")] - LocalAddr { #[error(std_err)] source: std::io::Error }, + LocalAddr { + #[error(std_err)] + source: std::io::Error, + }, } impl QuicServer { @@ -221,11 +229,20 @@ pub(crate) mod server { #[non_exhaustive] pub enum Error { #[error(transparent)] - Connect { #[error(std_err)] source: quinn::ConnectError }, + Connect { + #[error(std_err)] + source: quinn::ConnectError, + }, #[error(transparent)] - Connection { #[error(std_err)] source: quinn::ConnectionError }, + Connection { + #[error(std_err)] + source: quinn::ConnectionError, + }, #[error(transparent)] - WatchRecv { #[error(std_err)] source: watch::error::RecvError }, + WatchRecv { + #[error(std_err)] + source: watch::error::RecvError, + }, } /// Handles the client side of QUIC address discovery. @@ -341,11 +358,11 @@ impl QuicClient { mod tests { use std::net::Ipv4Addr; + use n0_error::{Error, Result, StdResultExt}; use n0_future::{ task::AbortOnDropHandle, time::{self, Instant}, }; - use n0_error::{Error, Result, StdResultExt}; use quinn::crypto::rustls::QuicServerConfig; use tracing::{Instrument, debug, info, info_span}; use tracing_test::traced_test; diff --git a/iroh-relay/src/server.rs b/iroh-relay/src/server.rs index fab602bd971..b037aab0800 100644 --- a/iroh-relay/src/server.rs +++ b/iroh-relay/src/server.rs @@ -26,8 +26,8 @@ use hyper::body::Incoming; use iroh_base::EndpointId; #[cfg(feature = "test-utils")] use iroh_base::RelayUrl; +use n0_error::{Err, Error, StdResultExt, add_meta, e}; use n0_future::{StreamExt, future::Boxed}; -use n0_error::{add_meta, Error, e, Err, StdResultExt}; use tokio::{ net::TcpListener, task::{JoinError, JoinSet}, @@ -270,15 +270,30 @@ pub struct Server { #[non_exhaustive] pub enum SpawnError { #[display("Unable to get local address")] - LocalAddr { #[error(std_err)] source: std::io::Error }, + LocalAddr { + #[error(std_err)] + source: std::io::Error, + }, #[display("Failed to bind QAD listener")] - QuicSpawn { #[error(std_err)] source: QuicSpawnError }, + QuicSpawn { + #[error(std_err)] + source: QuicSpawnError, + }, #[display("Failed to parse TLS header")] - TlsHeaderParse { #[error(std_err)] source: InvalidHeaderValue }, + TlsHeaderParse { + #[error(std_err)] + source: InvalidHeaderValue, + }, #[display("Failed to bind TcpListener")] - BindTlsListener { #[error(std_err)] source: std::io::Error }, + BindTlsListener { + #[error(std_err)] + source: std::io::Error, + }, #[display("No local address")] - NoLocalAddr { #[error(std_err)] source: std::io::Error }, + NoLocalAddr { + #[error(std_err)] + source: std::io::Error, + }, #[display("Failed to bind server socket to {addr}")] BindTcpListener { addr: SocketAddr }, } @@ -290,11 +305,17 @@ pub enum SpawnError { #[non_exhaustive] pub enum SupervisorError { #[display("Error starting metrics server")] - Metrics { #[error(std_err)] source: std::io::Error }, + Metrics { + #[error(std_err)] + source: std::io::Error, + }, #[display("Acme event stream finished")] AcmeEventStreamFinished {}, #[error(transparent)] - JoinError { #[error(std_err)] source: JoinError }, + JoinError { + #[error(std_err)] + source: JoinError, + }, #[display("No relay services are enabled")] NoRelayServicesEnabled {}, #[display("Task cancelled")] @@ -351,7 +372,12 @@ impl Server { debug!("Starting Relay server"); let mut headers = HeaderMap::new(); for (name, value) in TLS_HEADERS.iter() { - headers.insert(*name, value.parse().map_err(|err| e!(SpawnError::TlsHeaderParse, err))?); + headers.insert( + *name, + value + .parse() + .map_err(|err| e!(SpawnError::TlsHeaderParse, err))?, + ); } let relay_bind_addr = match relay_config.tls { Some(ref tls) => tls.https_bind_addr, @@ -413,7 +439,9 @@ impl Server { let http_listener = TcpListener::bind(&relay_config.http_bind_addr) .await .map_err(|err| e!(SpawnError::BindTlsListener, err))?; - let http_addr = http_listener.local_addr().map_err(|err| e!(SpawnError::NoLocalAddr, err))?; + let http_addr = http_listener + .local_addr() + .map_err(|err| e!(SpawnError::NoLocalAddr, err))?; tasks.spawn( async move { run_captive_portal_service(http_listener).await; @@ -741,8 +769,8 @@ mod tests { use http::StatusCode; use iroh_base::{EndpointId, RelayUrl, SecretKey}; - use n0_future::{FutureExt, SinkExt, StreamExt}; use n0_error::Result; + use n0_future::{FutureExt, SinkExt, StreamExt}; use rand::SeedableRng; use tracing::{info, instrument}; use tracing_test::traced_test; diff --git a/iroh-relay/src/server/client.rs b/iroh-relay/src/server/client.rs index e028f5d278e..e0e1ee2a596 100644 --- a/iroh-relay/src/server/client.rs +++ b/iroh-relay/src/server/client.rs @@ -3,10 +3,9 @@ use std::{collections::HashSet, sync::Arc, time::Duration}; use iroh_base::EndpointId; +use n0_error::{Err, Error, add_meta, e}; use n0_future::{SinkExt, StreamExt}; -use n0_error::{add_meta, Error, e, Err}; use rand::Rng; - use time::{Date, OffsetDateTime}; use tokio::{ sync::mpsc::{self, error::TrySendError}, @@ -197,7 +196,10 @@ pub enum WriteFrameError { #[error(transparent)] Stream { source: RelaySendError }, #[error(transparent)] - Timeout { #[error(std_err)] source: tokio::time::error::Elapsed }, + Timeout { + #[error(std_err)] + source: tokio::time::error::Elapsed, + }, } /// Run error @@ -295,7 +297,6 @@ impl Actor { } async fn run_inner(&mut self, done: CancellationToken) -> Result<(), RunError> { - // Add some jitter to ping pong interactions, to avoid all pings being sent at the same time let next_interval = || { let random_secs = rand::rng().random_range(1..=5); @@ -368,7 +369,8 @@ impl Actor { /// /// Errors if the send does not happen within the `timeout` duration async fn write_frame(&mut self, frame: RelayToClientMsg) -> Result<(), WriteFrameError> { - tokio::time::timeout(self.timeout, self.stream.send(frame)).await? + tokio::time::timeout(self.timeout, self.stream.send(frame)) + .await? .map_err(|err| e!(WriteFrameError::Stream { source: err }))?; Ok(()) } @@ -605,7 +607,10 @@ mod tests { src: endpoint_id, data: Datagrams::from(&data[..]), }; - send_queue_s.send(packet.clone()).await.std_context("send")?; + send_queue_s + .send(packet.clone()) + .await + .std_context("send")?; let frame = recv_frame(FrameType::RelayToClientDatagram, &mut io_rw) .await .e()?; diff --git a/iroh-relay/src/server/http_server.rs b/iroh-relay/src/server/http_server.rs index ebee670ded2..a27966eed3e 100644 --- a/iroh-relay/src/server/http_server.rs +++ b/iroh-relay/src/server/http_server.rs @@ -15,9 +15,9 @@ use hyper::{ service::Service, upgrade::Upgraded, }; +use n0_error::{Err, Error, StdResultExt, add_meta, e}; use n0_future::time::Elapsed; -use n0_error::{add_meta, Error, e, Err, StdResultExt}; -use snafu::{OptionExt}; +use snafu::OptionExt; use tokio::net::{TcpListener, TcpStream}; use tokio_rustls_acme::AcmeAcceptor; use tokio_util::{sync::CancellationToken, task::AbortOnDropHandle}; @@ -157,19 +157,40 @@ pub(super) struct TlsConfig { #[non_exhaustive] pub enum ServeConnectionError { #[display("TLS[acme] handshake")] - TlsHandshake { #[error(std_err)] source: std::io::Error }, + TlsHandshake { + #[error(std_err)] + source: std::io::Error, + }, #[display("TLS[acme] serve connection")] - ServeConnection { #[error(std_err)] source: hyper::Error }, + ServeConnection { + #[error(std_err)] + source: hyper::Error, + }, #[display("TLS[manual] timeout")] - Timeout { #[error(std_err)] source: Elapsed }, + Timeout { + #[error(std_err)] + source: Elapsed, + }, #[display("TLS[manual] accept")] - ManualAccept { #[error(std_err)] source: std::io::Error }, + ManualAccept { + #[error(std_err)] + source: std::io::Error, + }, #[display("TLS[acme] accept")] - LetsEncryptAccept { #[error(std_err)] source: std::io::Error }, + LetsEncryptAccept { + #[error(std_err)] + source: std::io::Error, + }, #[display("HTTPS connection")] - Https { #[error(std_err)] source: hyper::Error }, + Https { + #[error(std_err)] + source: hyper::Error, + }, #[display("HTTP connection")] - Http { #[error(std_err)] source: hyper::Error }, + Http { + #[error(std_err)] + source: hyper::Error, + }, } /// Server accept errors. @@ -298,7 +319,6 @@ impl ServerBuilder { /// Builds and spawns an HTTP(S) Relay Server. pub(super) async fn spawn(self) -> Result { - let cancel_token = CancellationToken::new(); let service = RelayService::new( @@ -439,7 +459,10 @@ impl RelayService { let upgrade_header = expect_header(&req, UPGRADE)?; n0_error::ensure!( upgrade_header == HeaderValue::from_static(WEBSOCKET_UPGRADE_PROTOCOL), - e!(RelayUpgradeReqError::InvalidHeader { header: UPGRADE, details: format!("value must be {WEBSOCKET_UPGRADE_PROTOCOL}") }) + e!(RelayUpgradeReqError::InvalidHeader { + header: UPGRADE, + details: format!("value must be {WEBSOCKET_UPGRADE_PROTOCOL}") + }) ); let key = expect_header(&req, SEC_WEBSOCKET_KEY)?.clone(); @@ -453,13 +476,21 @@ impl RelayService { let subprotocols = expect_header(&req, SEC_WEBSOCKET_PROTOCOL)? .to_str() .ok() - .ok_or_else(|| e!(RelayUpgradeReqError::InvalidHeader { header: SEC_WEBSOCKET_PROTOCOL, details: "header value is not ascii".to_string() }))?; + .ok_or_else(|| { + e!(RelayUpgradeReqError::InvalidHeader { + header: SEC_WEBSOCKET_PROTOCOL, + details: "header value is not ascii".to_string() + }) + })?; let supports_our_version = subprotocols .split_whitespace() .any(|p| p == RELAY_PROTOCOL_VERSION); n0_error::ensure!( supports_our_version, - e!(RelayUpgradeReqError::UnsupportedRelayVersion { we_support: RELAY_PROTOCOL_VERSION, you_support: subprotocols.to_string() }) + e!(RelayUpgradeReqError::UnsupportedRelayVersion { + we_support: RELAY_PROTOCOL_VERSION, + you_support: subprotocols.to_string() + }) ); let client_auth_header = req.headers().get(CLIENT_AUTH_HEADER).cloned(); @@ -741,7 +772,11 @@ impl RelayService { let TlsConfig { acceptor, config } = tls_config; match acceptor { TlsAcceptor::LetsEncrypt(a) => { - match a.accept(stream).await.map_err(|err| e!(ServeConnectionError::LetsEncryptAccept, err))? { + match a + .accept(stream) + .await + .map_err(|err| e!(ServeConnectionError::LetsEncryptAccept, err))? + { None => { info!("TLS[acme]: received TLS-ALPN-01 validation request"); } @@ -816,8 +851,8 @@ mod tests { use std::sync::Arc; use iroh_base::{PublicKey, SecretKey}; - use n0_future::{SinkExt, StreamExt}; use n0_error::{Result, StdResultExt, whatever}; + use n0_future::{SinkExt, StreamExt}; use rand::SeedableRng; use reqwest::Url; use tracing::info; diff --git a/iroh-relay/src/server/streams.rs b/iroh-relay/src/server/streams.rs index 463f70c9486..309dfad6323 100644 --- a/iroh-relay/src/server/streams.rs +++ b/iroh-relay/src/server/streams.rs @@ -6,7 +6,7 @@ use std::{ task::{Context, Poll}, }; -use n0_error::{add_meta, Error, e}; +use n0_error::{Error, add_meta, e}; use n0_future::{FutureExt, Sink, Stream, ready, time}; use tokio::io::{AsyncRead, AsyncWrite}; use tracing::instrument; @@ -80,7 +80,10 @@ impl RelayedStream { #[non_exhaustive] pub enum SendError { #[error(transparent)] - StreamError { #[error(std_err)] source: StreamError }, + StreamError { + #[error(std_err)] + source: StreamError, + }, #[display("Packet exceeds max packet size")] ExceedsMaxPacketSize { size: usize }, #[display("Attempted to send empty packet")] @@ -96,7 +99,10 @@ impl Sink for RelayedStream { fn start_send(mut self: Pin<&mut Self>, item: RelayToClientMsg) -> Result<(), Self::Error> { let size = item.encoded_len(); - n0_error::ensure!(size <= MAX_PACKET_SIZE, e!(SendError::ExceedsMaxPacketSize { size })); + n0_error::ensure!( + size <= MAX_PACKET_SIZE, + e!(SendError::ExceedsMaxPacketSize { size }) + ); if let RelayToClientMsg::Datagrams { datagrams, .. } = &item { n0_error::ensure!(!datagrams.contents.is_empty(), e!(SendError::EmptyPacket)); } @@ -123,7 +129,10 @@ pub enum RecvError { #[error(transparent)] Proto { source: ProtoError }, #[error(transparent)] - StreamError { #[error(std_err)] source: StreamError }, + StreamError { + #[error(std_err)] + source: StreamError, + }, } impl Stream for RelayedStream { @@ -298,7 +307,11 @@ impl Bucket { let refill = bytes_per_second.saturating_mul(refill_period.as_millis() as i64) / 1000; n0_error::ensure!( max > 0 && bytes_per_second > 0 && refill_period.as_millis() as u32 > 0 && refill > 0, - e!(InvalidBucketConfig { max, bytes_per_second, refill_period }), + e!(InvalidBucketConfig { + max, + bytes_per_second, + refill_period + }), ); Ok(Self { fill: max, @@ -476,8 +489,8 @@ impl AsyncWrite for RateLimited { mod tests { use std::sync::Arc; - use n0_future::time; use n0_error::Result; + use n0_future::time; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tracing_test::traced_test; diff --git a/iroh/src/disco.rs b/iroh/src/disco.rs index ec41903bdfc..c99f45571a6 100644 --- a/iroh/src/disco.rs +++ b/iroh/src/disco.rs @@ -25,7 +25,7 @@ use std::{ use data_encoding::HEXLOWER; use iroh_base::{PublicKey, RelayUrl}; -use n0_error::{add_meta, Error, e, Err}; +use n0_error::{Err, Error, add_meta, e}; use rand::Rng; use serde::{Deserialize, Serialize}; // use n0_error ensure macro path-qualified @@ -314,7 +314,9 @@ fn socket_addr_as_bytes(addr: &SocketAddr) -> [u8; EP_LENGTH] { impl Pong { fn from_bytes(p: &[u8]) -> Result { - let tx_id: [u8; TX_LEN] = p[..TX_LEN].try_into().map_err(|_| e!(ParseError::TooShort))?; + let tx_id: [u8; TX_LEN] = p[..TX_LEN] + .try_into() + .map_err(|_| e!(ParseError::TooShort))?; let tx_id = TransactionId::from(tx_id); let src = send_addr_from_bytes(&p[TX_LEN..])?; @@ -346,8 +348,9 @@ impl CallMeMaybe { }; for chunk in p.chunks_exact(EP_LENGTH) { - let bytes: [u8; EP_LENGTH] = - chunk.try_into().map_err(|_| e!(ParseError::InvalidEncoding))?; + let bytes: [u8; EP_LENGTH] = chunk + .try_into() + .map_err(|_| e!(ParseError::InvalidEncoding))?; let src = socket_addr_from_bytes(bytes); m.my_numbers.push(src); } diff --git a/iroh/src/discovery.rs b/iroh/src/discovery.rs index 3b820649c0d..25045b4f865 100644 --- a/iroh/src/discovery.rs +++ b/iroh/src/discovery.rs @@ -113,13 +113,13 @@ use std::sync::{Arc, RwLock}; use iroh_base::{EndpointAddr, EndpointId}; +use n0_error::{AnyError, Err, Error, add_meta, e}; use n0_future::{ boxed::BoxStream, stream::StreamExt, task::{self, AbortOnDropHandle}, time::{self, Duration}, }; -use n0_error::{add_meta, Error, e, AnyError, Err}; use tokio::sync::oneshot; use tracing::{Instrument, debug, error_span, warn}; @@ -198,7 +198,10 @@ impl IntoDiscoveryError { provenance: &'static str, source: T, ) -> Self { - e!(IntoDiscoveryError::User { provenance, source: AnyError::from_std(source) }) + e!(IntoDiscoveryError::User { + provenance, + source: AnyError::from_std(source) + }) } /// Creates a new user error from an arbitrary boxed error type. @@ -206,7 +209,10 @@ impl IntoDiscoveryError { provenance: &'static str, source: Box, ) -> Self { - e!(IntoDiscoveryError::User { provenance, source: AnyError::from_std_box(source) }) + e!(IntoDiscoveryError::User { + provenance, + source: AnyError::from_std_box(source) + }) } } @@ -233,7 +239,10 @@ impl DiscoveryError { provenance: &'static str, source: T, ) -> Self { - e!(DiscoveryError::User { provenance, source: AnyError::from_std(source) }) + e!(DiscoveryError::User { + provenance, + source: AnyError::from_std(source) + }) } /// Creates a new user error from an arbitrary boxed error type. @@ -241,7 +250,10 @@ impl DiscoveryError { provenance: &'static str, source: Box, ) -> Self { - e!(DiscoveryError::User { provenance, source: AnyError::from_std_box(source) }) + e!(DiscoveryError::User { + provenance, + source: AnyError::from_std_box(source) + }) } } @@ -495,7 +507,10 @@ pub(super) struct DiscoveryTask { impl DiscoveryTask { /// Starts a discovery task. pub(super) fn start(ep: Endpoint, endpoint_id: EndpointId) -> Result { - n0_error::ensure!(!ep.discovery().is_empty(), e!(DiscoveryError::NoServiceConfigured)); + n0_error::ensure!( + !ep.discovery().is_empty(), + e!(DiscoveryError::NoServiceConfigured) + ); let (on_first_tx, on_first_rx) = oneshot::channel(); let me = ep.id(); let task = task::spawn( @@ -526,7 +541,10 @@ impl DiscoveryTask { if !ep.needs_discovery(endpoint_id, MAX_AGE) { return Ok(None); } - n0_error::ensure!(!ep.discovery().is_empty(), e!(DiscoveryError::NoServiceConfigured)); + n0_error::ensure!( + !ep.discovery().is_empty(), + e!(DiscoveryError::NoServiceConfigured) + ); let (on_first_tx, on_first_rx) = oneshot::channel(); let ep = ep.clone(); let me = ep.id(); @@ -564,7 +582,10 @@ impl DiscoveryTask { ep: &Endpoint, endpoint_id: EndpointId, ) -> Result>, DiscoveryError> { - n0_error::ensure!(!ep.discovery().is_empty(), e!(DiscoveryError::NoServiceConfigured)); + n0_error::ensure!( + !ep.discovery().is_empty(), + e!(DiscoveryError::NoServiceConfigured) + ); let stream = ep .discovery() .resolve(endpoint_id) @@ -613,7 +634,8 @@ impl DiscoveryTask { } } if let Some(tx) = on_first_tx.take() { - tx.send(Err!(DiscoveryError::NoResults { endpoint_id })).ok(); + tx.send(Err!(DiscoveryError::NoResults { endpoint_id })) + .ok(); } } } diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index ca0ed060f2d..fb8a5b8b816 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -23,10 +23,10 @@ use std::{ use ed25519_dalek::{VerifyingKey, pkcs8::DecodePublicKey}; use iroh_base::{EndpointAddr, EndpointId, RelayUrl, SecretKey}; use iroh_relay::{RelayConfig, RelayMap}; +use n0_error::{Err, Error, add_meta, e}; use n0_future::time::Duration; use n0_watcher::Watcher; use pin_project::pin_project; -use n0_error::{add_meta, Error, e, Err}; use tracing::{debug, instrument, trace, warn}; use url::Url; @@ -487,13 +487,19 @@ pub struct Endpoint { #[non_exhaustive] pub enum ConnectWithOptsError { #[error(transparent)] - AddEndpointAddr { #[error(std_err)] source: AddEndpointAddrError }, + AddEndpointAddr { + #[error(std_err)] + source: AddEndpointAddrError, + }, #[display("Connecting to ourself is not supported")] SelfConnect, #[display("No addressing information available")] NoAddress { source: GetMappingAddressError }, #[display("Unable to connect to remote")] - Quinn { #[error(std_err)] source: quinn_proto::ConnectError }, + Quinn { + #[error(std_err)] + source: quinn_proto::ConnectError, + }, } #[allow(missing_docs)] @@ -505,7 +511,10 @@ pub enum ConnectError { #[error(transparent)] Connect { source: ConnectWithOptsError }, #[error(transparent)] - Connection { #[error(std_err)] source: ConnectionError }, + Connection { + #[error(std_err)] + source: ConnectionError, + }, } #[allow(missing_docs)] @@ -515,9 +524,13 @@ pub enum ConnectError { #[non_exhaustive] pub enum BindError { #[error(transparent)] - MagicSpawn { source: magicsock::CreateHandleError }, + MagicSpawn { + source: magicsock::CreateHandleError, + }, #[error(transparent)] - Discovery { source: crate::discovery::IntoDiscoveryError }, + Discovery { + source: crate::discovery::IntoDiscoveryError, + }, } #[allow(missing_docs)] @@ -666,11 +679,13 @@ impl Endpoint { ); // Connecting to ourselves is not supported. - n0_error::ensure!(endpoint_addr.endpoint_id != self.id(), e!(ConnectWithOptsError::SelfConnect)); + n0_error::ensure!( + endpoint_addr.endpoint_id != self.id(), + e!(ConnectWithOptsError::SelfConnect) + ); if !endpoint_addr.is_empty() { - self - .add_endpoint_addr(endpoint_addr.clone(), Source::App) + self.add_endpoint_addr(endpoint_addr.clone(), Source::App) .map_err(|err| e!(ConnectWithOptsError::AddEndpointAddr { source: err }))?; } let endpoint_id = endpoint_addr.endpoint_id; @@ -1271,8 +1286,8 @@ impl Endpoint { // only then continue, because otherwise we wouldn't have any // path to the remote endpoint. let res = DiscoveryTask::start(self.clone(), endpoint_id); - let mut discovery = res - .map_err(|source| e!(GetMappingAddressError::DiscoveryStart { source }))?; + let mut discovery = + res.map_err(|source| e!(GetMappingAddressError::DiscoveryStart { source }))?; discovery .first_arrived() .await @@ -1514,7 +1529,10 @@ pub struct Connecting { #[non_exhaustive] pub enum AlpnError { #[error(transparent)] - ConnectionError { #[error(std_err)] source: ConnectionError }, + ConnectionError { + #[error(std_err)] + source: ConnectionError, + }, #[display("No ALPN available")] Unavailable, #[display("Unknown handshake type")] diff --git a/iroh/src/key.rs b/iroh/src/key.rs index bc720db161b..1a4be8026d3 100644 --- a/iroh/src/key.rs +++ b/iroh/src/key.rs @@ -4,7 +4,7 @@ use std::fmt::Debug; use aead::{AeadCore, AeadInOut, Buffer}; use iroh_base::{PublicKey, SecretKey}; -use n0_error::{add_meta, Error, e}; +use n0_error::{Error, add_meta, e}; pub(crate) const NONCE_LEN: usize = 24; @@ -34,7 +34,10 @@ pub enum DecryptionError { InvalidNonce, /// AEAD decryption failed. #[display("Aead error")] - Aead { #[error(std_err)] source: aead::Error }, + Aead { + #[error(std_err)] + source: aead::Error, + }, } impl Debug for SharedSecret { @@ -70,8 +73,7 @@ impl SharedSecret { .map_err(|_| e!(DecryptionError::InvalidNonce))?; buffer.truncate(offset); - self.0 - .decrypt_in_place(&nonce.into(), AEAD_DATA, buffer)?; + self.0.decrypt_in_place(&nonce.into(), AEAD_DATA, buffer)?; Ok(()) } diff --git a/iroh/src/net_report.rs b/iroh/src/net_report.rs index 3b6026ab74d..752a9d8309b 100644 --- a/iroh/src/net_report.rs +++ b/iroh/src/net_report.rs @@ -31,6 +31,7 @@ use iroh_relay::{ RelayMap, quic::{QUIC_ADDR_DISC_CLOSE_CODE, QUIC_ADDR_DISC_CLOSE_REASON}, }; +use n0_error::e; #[cfg(not(wasm_browser))] use n0_future::task; use n0_future::{ @@ -39,7 +40,6 @@ use n0_future::{ time::{self, Duration, Instant}, }; use n0_watcher::{Watchable, Watcher}; -use n0_error::e; use tokio::task::JoinSet; use tokio_util::sync::CancellationToken; use tracing::{debug, trace, warn}; @@ -86,7 +86,9 @@ pub(crate) use self::reportgen::IfStateDetails; #[non_exhaustive] enum QadProbeError { #[display("Failed to resolve relay address")] - GetRelayAddr { source: self::reportgen::GetRelayAddrError }, + GetRelayAddr { + source: self::reportgen::GetRelayAddrError, + }, #[display("Missing host in relay URL")] MissingHost, #[display("QUIC connection failed")] @@ -776,8 +778,7 @@ async fn run_probe_v4( relay: Arc, quic_client: QuicClient, dns_resolver: DnsResolver, - ) -> n0_error::Result<(QadProbeReport, QadConn), QadProbeError> { - +) -> n0_error::Result<(QadProbeReport, QadConn), QadProbeError> { let relay_addr_orig = reportgen::get_relay_addr_ipv4(&dns_resolver, &relay) .await .map_err(|source| e!(QadProbeError::GetRelayAddr { source }))?; diff --git a/iroh/src/net_report/reportgen.rs b/iroh/src/net_report/reportgen.rs index 963af987367..6bea64e22c5 100644 --- a/iroh/src/net_report/reportgen.rs +++ b/iroh/src/net_report/reportgen.rs @@ -33,6 +33,7 @@ use iroh_relay::{ dns::{DnsError, DnsResolver, DnsStaggeredError as StaggeredError}, quic::QuicClient, }; +use n0_error::{Err, Error, add_meta, e}; #[cfg(wasm_browser)] use n0_future::future::Pending; use n0_future::{ @@ -40,9 +41,7 @@ use n0_future::{ task::{self, AbortOnDropHandle, JoinSet}, time::{self, Duration, Instant}, }; -use n0_error::Err; use rand::seq::IteratorRandom; -use n0_error::{add_meta, Error, e}; use tokio::sync::mpsc; use tokio_util::sync::CancellationToken; use tracing::{Instrument, debug, error, trace, warn, warn_span}; @@ -541,11 +540,19 @@ pub(super) fn maybe_to_mapped_addr( #[non_exhaustive] enum CaptivePortalError { #[error(transparent)] - DnsLookup { source: iroh_relay::dns::DnsStaggeredError }, + DnsLookup { + source: iroh_relay::dns::DnsStaggeredError, + }, #[display("Creating HTTP client failed")] - CreateReqwestClient { #[error(std_err)] source: reqwest::Error }, + CreateReqwestClient { + #[error(std_err)] + source: reqwest::Error, + }, #[display("HTTP request failed")] - HttpRequest { #[error(std_err)] source: reqwest::Error }, + HttpRequest { + #[error(std_err)] + source: reqwest::Error, + }, } /// Reports whether or not we think the system is behind a @@ -657,7 +664,9 @@ pub enum GetRelayAddrError { #[display("No suitable relay address found")] NoAddrFound, #[display("DNS lookup failed")] - DnsLookup { source: iroh_relay::dns::DnsStaggeredError }, + DnsLookup { + source: iroh_relay::dns::DnsStaggeredError, + }, #[display("Relay is not suitable")] UnsupportedRelay, #[display("HTTPS probes are not implemented")] @@ -755,14 +764,25 @@ async fn relay_lookup_ipv6_staggered( #[non_exhaustive] pub enum MeasureHttpsLatencyError { #[error(transparent)] - InvalidUrl { #[error(std_err)] source: url::ParseError }, + InvalidUrl { + #[error(std_err)] + source: url::ParseError, + }, #[cfg(not(wasm_browser))] #[error(transparent)] - DnsLookup { source: iroh_relay::dns::DnsStaggeredError }, + DnsLookup { + source: iroh_relay::dns::DnsStaggeredError, + }, #[display("Creating HTTP client failed")] - CreateReqwestClient { #[error(std_err)] source: reqwest::Error }, + CreateReqwestClient { + #[error(std_err)] + source: reqwest::Error, + }, #[display("HTTP request failed")] - HttpRequest { #[error(std_err)] source: reqwest::Error }, + HttpRequest { + #[error(std_err)] + source: reqwest::Error, + }, #[display("Error response from server {status}: {:?}", status.canonical_reason())] InvalidResponse { status: StatusCode }, } @@ -840,7 +860,9 @@ async fn run_https_probe( Ok(HttpsProbeReport { relay, latency }) } else { - Err!(MeasureHttpsLatencyError::InvalidResponse { status: response.status() }) + Err!(MeasureHttpsLatencyError::InvalidResponse { + status: response.status() + }) } } diff --git a/iroh/src/protocol.rs b/iroh/src/protocol.rs index 37397512ab5..6e374ea3d96 100644 --- a/iroh/src/protocol.rs +++ b/iroh/src/protocol.rs @@ -43,11 +43,11 @@ use std::{ }; use iroh_base::EndpointId; +use n0_error::{AnyError, Err, Error, add_meta, e}; use n0_future::{ join_all, task::{self, AbortOnDropHandle, JoinSet}, }; -use n0_error::{add_meta, Error, e, AnyError, Err}; use tokio_util::sync::CancellationToken; use tracing::{Instrument, error, field::Empty, info_span, trace, warn}; @@ -108,7 +108,9 @@ pub struct RouterBuilder { #[non_exhaustive] pub enum AcceptError { #[error(transparent)] - Connection { source: crate::endpoint::ConnectionError }, + Connection { + source: crate::endpoint::ConnectionError, + }, #[error(transparent)] MissingRemoteEndpointId { source: RemoteEndpointIdError }, #[display("Not allowed.")] @@ -120,7 +122,9 @@ pub enum AcceptError { impl AcceptError { /// Creates a new user error from an arbitrary error type. pub fn from_err(value: T) -> Self { - e!(AcceptError::User { source: AnyError::from_std(value) }) + e!(AcceptError::User { + source: AnyError::from_std(value) + }) } } From 39a5935cd3358404154e8e907d92371438b09d05 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 14:59:54 +0200 Subject: [PATCH 07/58] fixup --- iroh/src/net_report/reportgen.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/iroh/src/net_report/reportgen.rs b/iroh/src/net_report/reportgen.rs index 6bea64e22c5..18883e9a169 100644 --- a/iroh/src/net_report/reportgen.rs +++ b/iroh/src/net_report/reportgen.rs @@ -30,7 +30,7 @@ use iroh_relay::{ }; #[cfg(not(wasm_browser))] use iroh_relay::{ - dns::{DnsError, DnsResolver, DnsStaggeredError as StaggeredError}, + dns::{DnsResolver, DnsStaggeredError as StaggeredError}, quic::QuicClient, }; use n0_error::{Err, Error, add_meta, e}; @@ -540,9 +540,7 @@ pub(super) fn maybe_to_mapped_addr( #[non_exhaustive] enum CaptivePortalError { #[error(transparent)] - DnsLookup { - source: iroh_relay::dns::DnsStaggeredError, - }, + DnsLookup { source: StaggeredError }, #[display("Creating HTTP client failed")] CreateReqwestClient { #[error(std_err)] @@ -664,9 +662,7 @@ pub enum GetRelayAddrError { #[display("No suitable relay address found")] NoAddrFound, #[display("DNS lookup failed")] - DnsLookup { - source: iroh_relay::dns::DnsStaggeredError, - }, + DnsLookup { source: StaggeredError }, #[display("Relay is not suitable")] UnsupportedRelay, #[display("HTTPS probes are not implemented")] @@ -770,9 +766,7 @@ pub enum MeasureHttpsLatencyError { }, #[cfg(not(wasm_browser))] #[error(transparent)] - DnsLookup { - source: iroh_relay::dns::DnsStaggeredError, - }, + DnsLookup { source: StaggeredError }, #[display("Creating HTTP client failed")] CreateReqwestClient { #[error(std_err)] From 3cd15f983f40cdda3150b7062594e743077bc74d Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 15:06:09 +0200 Subject: [PATCH 08/58] fixup --- Cargo.lock | 4 ++-- iroh-base/src/relay_url.rs | 8 +++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a1a4492bf81..de9f3d5fd58 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2828,7 +2828,7 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error#5e50fb8cbf50d98808ffc276850d2756a2c42f00" +source = "git+https://github.com/n0-computer/n0-error#ed20998c57f5daf45396ac3114dca6321f00d57d" dependencies = [ "anyhow", "derive_more 2.0.1", @@ -2839,7 +2839,7 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error#5e50fb8cbf50d98808ffc276850d2756a2c42f00" +source = "git+https://github.com/n0-computer/n0-error#ed20998c57f5daf45396ac3114dca6321f00d57d" dependencies = [ "darling", "heck", diff --git a/iroh-base/src/relay_url.rs b/iroh-base/src/relay_url.rs index f7139494c99..93d256a26da 100644 --- a/iroh-base/src/relay_url.rs +++ b/iroh-base/src/relay_url.rs @@ -41,12 +41,10 @@ impl From for RelayUrl { /// Can occur when parsing a string into a [`RelayUrl`]. #[add_meta] #[derive(Error)] -#[error(from_sources, std_sources)] #[allow(missing_docs)] -pub enum RelayUrlParseError { - /// Parsing the URL failed. - #[display("Failed to parse")] - Parse { source: url::ParseError }, +pub struct RelayUrlParseError { + #[error(from, std_err)] + source: url::ParseError, } /// Support for parsing strings directly. From f4ec7324fd66abdf9f68102c1ee38b879d7c288e Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 15:15:22 +0200 Subject: [PATCH 09/58] fixup --- iroh-base/src/relay_url.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/iroh-base/src/relay_url.rs b/iroh-base/src/relay_url.rs index 93d256a26da..afc8f6a0acc 100644 --- a/iroh-base/src/relay_url.rs +++ b/iroh-base/src/relay_url.rs @@ -41,7 +41,6 @@ impl From for RelayUrl { /// Can occur when parsing a string into a [`RelayUrl`]. #[add_meta] #[derive(Error)] -#[allow(missing_docs)] pub struct RelayUrlParseError { #[error(from, std_err)] source: url::ParseError, From 923694c440685f1ff6b8739e9256f703d1e587b8 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 16:47:39 +0200 Subject: [PATCH 10/58] codex is converting iroh --- Cargo.lock | 2 - iroh/Cargo.toml | 2 - iroh/src/discovery.rs | 4 +- iroh/src/discovery/mdns.rs | 4 +- iroh/src/discovery/pkarr.rs | 71 +++++-------- iroh/src/discovery/pkarr/dht.rs | 2 +- iroh/src/endpoint.rs | 29 +++-- iroh/src/magicsock.rs | 105 ++++++++---------- iroh/src/magicsock/transports/relay/actor.rs | 106 ++++++++----------- iroh/src/net_report.rs | 2 +- iroh/src/net_report/ip_mapped_addrs.rs | 9 +- iroh/src/net_report/probes.rs | 5 +- iroh/src/net_report/reportgen.rs | 2 +- iroh/src/test_utils.rs | 2 +- iroh/src/tls/resolver.rs | 14 +-- 15 files changed, 149 insertions(+), 210 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index de9f3d5fd58..cf05243999d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2283,7 +2283,6 @@ dependencies = [ "iroh-relay", "n0-error", "n0-future 0.3.0", - "n0-snafu", "n0-watcher", "nested_enum_utils", "netdev 0.38.2", @@ -2306,7 +2305,6 @@ dependencies = [ "serde", "serde_json", "smallvec", - "snafu", "strum", "surge-ping", "swarm-discovery", diff --git a/iroh/Cargo.toml b/iroh/Cargo.toml index 9a1e7e5b84d..2cea5b25a98 100644 --- a/iroh/Cargo.toml +++ b/iroh/Cargo.toml @@ -40,7 +40,6 @@ http = "1" iroh-base = { version = "0.93.2", default-features = false, features = ["key", "relay"], path = "../iroh-base" } iroh-relay = { version = "0.93", path = "../iroh-relay", default-features = false } n0-future = "0.3.0" -n0-snafu = "0.2.2" n0-error = { git = "https://github.com/n0-computer/n0-error" } n0-watcher = "0.3" nested_enum_utils = "0.2.1" @@ -59,7 +58,6 @@ ring = "0.17" rustls = { version = "0.23.33", default-features = false, features = ["ring"] } serde = { version = "1.0.219", features = ["derive", "rc"] } smallvec = "1.11.1" -snafu = { version = "0.8.5", features = ["rust_1_81"] } strum = { version = "0.27", features = ["derive"] } tokio = { version = "1.44.1", features = [ "io-util", diff --git a/iroh/src/discovery.rs b/iroh/src/discovery.rs index 25045b4f865..4a031618017 100644 --- a/iroh/src/discovery.rs +++ b/iroh/src/discovery.rs @@ -650,7 +650,7 @@ mod tests { }; use iroh_base::{EndpointAddr, SecretKey}; - use n0_snafu::{Error, Result, ResultExt}; + use n0_error::{Result, StackResultExt, StdResultExt, AnyError as Error}; use quinn::{IdleTimeout, TransportConfig}; use rand::{CryptoRng, Rng, SeedableRng}; use tokio_util::task::AbortOnDropHandle; @@ -970,7 +970,7 @@ mod test_dns_pkarr { use iroh_base::{EndpointAddr, SecretKey}; use iroh_relay::{RelayMap, endpoint_info::UserData}; use n0_future::time::Duration; - use n0_snafu::{Error, Result, ResultExt}; + use n0_error::{Result, StackResultExt, StdResultExt, AnyError as Error}; use rand::{CryptoRng, SeedableRng}; use tokio_util::task::AbortOnDropHandle; use tracing_test::traced_test; diff --git a/iroh/src/discovery/mdns.rs b/iroh/src/discovery/mdns.rs index f5a30fe0bbd..6169ae1332a 100644 --- a/iroh/src/discovery/mdns.rs +++ b/iroh/src/discovery/mdns.rs @@ -545,9 +545,9 @@ mod tests { mod run_in_isolation { use iroh_base::SecretKey; use n0_future::StreamExt; - use n0_snafu::{Error, Result, ResultExt}; + use n0_error::{Result, StackResultExt, StdResultExt, AnyError as Error}; use rand::{CryptoRng, SeedableRng}; - use snafu::whatever; + use n0_error::whatever; use tracing_test::traced_test; use super::super::*; diff --git a/iroh/src/discovery/pkarr.rs b/iroh/src/discovery/pkarr.rs index 1e1f0e54055..6f43ed81cd7 100644 --- a/iroh/src/discovery/pkarr.rs +++ b/iroh/src/discovery/pkarr.rs @@ -48,6 +48,7 @@ use std::sync::Arc; use iroh_base::{EndpointId, RelayUrl, SecretKey}; use iroh_relay::endpoint_info::{EncodingError, EndpointInfo}; +use n0_error::{add_meta, e, Error, Err}; use n0_future::{ boxed::BoxStream, task::{self, AbortOnDropHandle}, @@ -58,7 +59,6 @@ use pkarr::{ SignedPacket, errors::{PublicKeyError, SignedPacketVerifyError}, }; -use snafu::{ResultExt, Snafu}; use tracing::{Instrument, debug, error_span, warn}; use url::Url; @@ -76,22 +76,23 @@ use crate::{ pub mod dht; #[allow(missing_docs)] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] pub enum PkarrError { - #[snafu(display("Invalid public key"))] - PublicKey { source: PublicKeyError }, - #[snafu(display("Packet failed to verify"))] - Verify { source: SignedPacketVerifyError }, - #[snafu(display("Invalid relay URL"))] + #[display("Invalid public key")] + PublicKey { #[error(std_err)] source: PublicKeyError }, + #[display("Packet failed to verify")] + Verify { #[error(std_err)] source: SignedPacketVerifyError }, + #[display("Invalid relay URL")] InvalidRelayUrl { url: RelayUrl }, - #[snafu(display("Error sending http request"))] - HttpSend { source: reqwest::Error }, - #[snafu(display("Error resolving http request"))] + #[display("Error sending http request")] + HttpSend { #[error(std_err)] source: reqwest::Error }, + #[display("Error resolving http request")] HttpRequest { status: reqwest::StatusCode }, - #[snafu(display("Http payload error"))] - HttpPayload { source: reqwest::Error }, - #[snafu(display("EncodingError"))] + #[display("Http payload error")] + HttpPayload { #[error(std_err)] source: reqwest::Error }, + #[display("EncodingError")] Encoding { source: EncodingError }, } @@ -394,7 +395,7 @@ impl PublisherService { ); let signed_packet = info .to_pkarr_signed_packet(&self.secret_key, self.ttl) - .context(EncodingSnafu)?; + .map_err(|source| e!(PkarrError::Encoding { source }))?; self.pkarr_client.publish(&signed_packet).await?; Ok(()) } @@ -549,17 +550,12 @@ impl PkarrRelayClient { /// Resolves a [`SignedPacket`] for the given [`EndpointId`]. pub async fn resolve(&self, endpoint_id: EndpointId) -> Result { // We map the error to string, as in browsers the error is !Send - let public_key = - pkarr::PublicKey::try_from(endpoint_id.as_bytes()).context(PublicKeySnafu)?; + let public_key = pkarr::PublicKey::try_from(endpoint_id.as_bytes()) + .map_err(|source| e!(PkarrError::PublicKey { source }))?; let mut url = self.pkarr_relay_url.clone(); url.path_segments_mut() - .map_err(|_| { - InvalidRelayUrlSnafu { - url: self.pkarr_relay_url.clone(), - } - .build() - })? + .map_err(|_| e!(PkarrError::InvalidRelayUrl { url: self.pkarr_relay_url.clone().into() }))? .push(&public_key.to_z32()); let response = self @@ -567,20 +563,19 @@ impl PkarrRelayClient { .get(url) .send() .await - .context(HttpSendSnafu)?; + .map_err(|source| e!(PkarrError::HttpSend { source }))?; if !response.status().is_success() { - return Err(HttpRequestSnafu { - status: response.status(), - } - .build() - .into()); + return Err(e!(PkarrError::HttpRequest { status: response.status() }).into()); } - let payload = response.bytes().await.context(HttpPayloadSnafu)?; + let payload = response + .bytes() + .await + .map_err(|source| e!(PkarrError::HttpPayload { source }))?; // We map the error to string, as in browsers the error is !Send - let packet = - SignedPacket::from_relay_payload(&public_key, &payload).context(VerifySnafu)?; + let packet = SignedPacket::from_relay_payload(&public_key, &payload) + .map_err(|source| e!(PkarrError::Verify { source }))?; Ok(packet) } @@ -588,12 +583,7 @@ impl PkarrRelayClient { pub async fn publish(&self, signed_packet: &SignedPacket) -> Result<(), PkarrError> { let mut url = self.pkarr_relay_url.clone(); url.path_segments_mut() - .map_err(|_| { - InvalidRelayUrlSnafu { - url: self.pkarr_relay_url.clone(), - } - .build() - })? + .map_err(|_| e!(PkarrError::InvalidRelayUrl { url: self.pkarr_relay_url.clone().into() }))? .push(&signed_packet.public_key().to_z32()); let response = self @@ -602,13 +592,10 @@ impl PkarrRelayClient { .body(signed_packet.to_relay_payload()) .send() .await - .context(HttpSendSnafu)?; + .map_err(|source| e!(PkarrError::HttpSend { source }))?; if !response.status().is_success() { - return Err(HttpRequestSnafu { - status: response.status(), - } - .build()); + return Err!(PkarrError::HttpRequest { status: response.status() }); } Ok(()) diff --git a/iroh/src/discovery/pkarr/dht.rs b/iroh/src/discovery/pkarr/dht.rs index c00b1172422..7599416220c 100644 --- a/iroh/src/discovery/pkarr/dht.rs +++ b/iroh/src/discovery/pkarr/dht.rs @@ -333,7 +333,7 @@ mod tests { use std::collections::BTreeSet; use iroh_base::RelayUrl; - use n0_snafu::{Result, ResultExt}; + use n0_error::{Result, StackResultExt, StdResultExt}; use tracing_test::traced_test; use super::*; diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index fb8a5b8b816..6dd743cae26 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -40,7 +40,7 @@ use crate::{ UserData, }, endpoint::presets::Preset, - magicsock::{self, EndpointIdMappedAddr, Handle, OwnAddressSnafu}, + magicsock::{self, EndpointIdMappedAddr, Handle}, metrics::EndpointMetrics, net_report::Report, tls::{self, DEFAULT_MAX_TLS_TICKETS}, @@ -488,7 +488,6 @@ pub struct Endpoint { pub enum ConnectWithOptsError { #[error(transparent)] AddEndpointAddr { - #[error(std_err)] source: AddEndpointAddrError, }, #[display("Connecting to ourself is not supported")] @@ -505,22 +504,19 @@ pub enum ConnectWithOptsError { #[allow(missing_docs)] #[add_meta] #[derive(Error)] -#[error(from_sources, std_sources)] +#[error(from_sources)] #[non_exhaustive] pub enum ConnectError { #[error(transparent)] Connect { source: ConnectWithOptsError }, #[error(transparent)] - Connection { - #[error(std_err)] - source: ConnectionError, - }, + Connection { #[error(std_err)] source: ConnectionError }, } #[allow(missing_docs)] #[add_meta] #[derive(Error)] -#[error(from_sources, std_sources)] +#[error(from_sources)] #[non_exhaustive] pub enum BindError { #[error(transparent)] @@ -790,7 +786,7 @@ impl Endpoint { source: Source, ) -> Result<(), AddEndpointAddrError> { if endpoint_addr.endpoint_id == self.id() { - return Err(OwnAddressSnafu.build()); + return Err!(AddEndpointAddrError::OwnAddress); } self.msock.add_endpoint_addr(endpoint_addr, source) } @@ -2125,7 +2121,8 @@ mod tests { use iroh_base::{EndpointAddr, EndpointId, SecretKey}; use n0_future::{BufferedStreamExt, StreamExt, stream, task::AbortOnDropHandle}; - use n0_snafu::{Error, Result, ResultExt}; + use n0_error::{AnyError as Error, StackResultExt, StdResultExt}; + type Result = std::result::Result; use n0_watcher::Watcher; use quinn::ConnectionError; use rand::SeedableRng; @@ -2377,9 +2374,9 @@ mod tests { let task = tokio::spawn({ let server = server.clone(); async move { - let Some(conn) = server.accept().await else { - snafu::whatever!("Expected an incoming connection"); - }; + let Some(conn) = server.accept().await else { + n0_error::whatever!("Expected an incoming connection"); + }; let conn = conn.await.e()?; let (mut send, mut recv) = conn.accept_bi().await.e()?; let data = recv.read_to_end(1000).await.e()?; @@ -2429,7 +2426,7 @@ mod tests { for i in 0..2 { println!("accept: round {i}"); let Some(conn) = server.accept().await else { - snafu::whatever!("Expected an incoming connection"); + n0_error::whatever!("Expected an incoming connection"); }; let conn = conn.await.e()?; let (mut send, mut recv) = conn.accept_bi().await.e()?; @@ -2648,7 +2645,7 @@ mod tests { return Ok(()); } } - snafu::whatever!("conn_type stream ended before `ConnectionType::Direct`"); + n0_error::whatever!("conn_type stream ended before `ConnectionType::Direct`"); } async fn accept(ep: &Endpoint) -> Result { @@ -3047,7 +3044,7 @@ mod tests { let incoming = server.accept().await.e()?; let conn = incoming.await.e()?; conn.close(0u32.into(), b"bye!"); - Ok::<_, n0_snafu::Error>(conn.alpn()) + Ok::<_, n0_error::AnyError>(conn.alpn()) } }); diff --git a/iroh/src/magicsock.rs b/iroh/src/magicsock.rs index 07a8618478b..56fc6f7c5e8 100644 --- a/iroh/src/magicsock.rs +++ b/iroh/src/magicsock.rs @@ -37,14 +37,13 @@ use n0_future::{ time::{self, Duration, Instant}, }; use n0_watcher::{self, Watchable, Watcher}; -use nested_enum_utils::common_fields; use netwatch::netmon; #[cfg(not(wasm_browser))] use netwatch::{UdpSocket, ip::LocalAddresses}; use quinn::{AsyncUdpSocket, ServerConfig}; use rand::Rng; use smallvec::SmallVec; -use snafu::{ResultExt, Snafu}; +use n0_error::{add_meta, e, Error, Err}; use tokio::sync::{Mutex as AsyncMutex, mpsc}; use tokio_util::sync::CancellationToken; use tracing::{ @@ -214,21 +213,16 @@ pub(crate) struct MagicSock { } #[allow(missing_docs)] -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] -#[derive(Debug, Snafu)] -#[snafu(visibility(pub(crate)))] +#[add_meta] +#[derive(Error)] #[non_exhaustive] pub enum AddEndpointAddrError { - #[snafu(display("Empty addressing info"))] - Empty {}, - #[snafu(display("Empty addressing info, {pruned} direct address have been pruned"))] + #[display("Empty addressing info")] + Empty, + #[display("Empty addressing info, {pruned} direct address have been pruned")] EmptyPruned { pruned: usize }, - #[snafu(display("Adding our own address is not supported"))] - OwnAddress {}, + #[display("Adding our own address is not supported")] + OwnAddress, } impl MagicSock { @@ -421,9 +415,9 @@ impl MagicSock { .add_endpoint_addr(addr, source, have_ipv6, &self.metrics.magicsock); Ok(()) } else if pruned != 0 { - Err(EmptyPrunedSnafu { pruned }.build()) + Err!(AddEndpointAddrError::EmptyPruned { pruned }) } else { - Err(EmptySnafu.build()) + Err!(AddEndpointAddrError::Empty) } } @@ -1335,24 +1329,20 @@ impl DirectAddrUpdateState { } #[allow(missing_docs)] -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] pub enum CreateHandleError { - #[snafu(display("Failed to create bind sockets"))] - BindSockets { source: io::Error }, - #[snafu(display("Failed to create internal quinn endpoint"))] - CreateQuinnEndpoint { source: io::Error }, - #[snafu(display("Failed to create socket state"))] - CreateSocketState { source: io::Error }, - #[snafu(display("Failed to create netmon monitor"))] - CreateNetmonMonitor { source: netmon::Error }, - #[snafu(display("Failed to subscribe netmon monitor"))] - SubscribeNetmonMonitor { source: netmon::Error }, + #[display("Failed to create bind sockets")] + BindSockets { #[error(std_err)] source: io::Error }, + #[display("Failed to create internal quinn endpoint")] + CreateQuinnEndpoint { #[error(std_err)] source: io::Error }, + #[display("Failed to create socket state")] + CreateSocketState { #[error(std_err)] source: io::Error }, + #[display("Failed to create netmon monitor")] + CreateNetmonMonitor { #[error(std_err)] source: netmon::Error }, + #[display("Failed to subscribe netmon monitor")] + SubscribeNetmonMonitor { #[error(std_err)] source: netmon::Error }, } impl Handle { @@ -1380,8 +1370,8 @@ impl Handle { let addr_v4 = addr_v4.unwrap_or_else(|| SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0)); #[cfg(not(wasm_browser))] - let (ip_transports, port_mapper) = - bind_ip(addr_v4, addr_v6, &metrics).context(BindSocketsSnafu)?; + let (ip_transports, port_mapper) = bind_ip(addr_v4, addr_v6, &metrics) + .map_err(|source| e!(CreateHandleError::BindSockets { source }))?; let ip_mapped_addrs = IpMappedAddresses::default(); @@ -1471,11 +1461,11 @@ impl Handle { #[cfg(wasm_browser)] Arc::new(crate::web_runtime::WebRuntime), ) - .context(CreateQuinnEndpointSnafu)?; + .map_err(|source| e!(CreateHandleError::CreateQuinnEndpoint { source }))?; let network_monitor = netmon::Monitor::new() .await - .context(CreateNetmonMonitorSnafu)?; + .map_err(|source| e!(CreateHandleError::CreateNetmonMonitor { source }))?; let qad_endpoint = endpoint.clone(); @@ -1683,9 +1673,11 @@ impl DiscoState { sealed_box: &[u8], ) -> Result { let mut sealed_box = sealed_box.to_vec(); - self.get_secret(endpoint_id, |secret| secret.open(&mut sealed_box)) - .context(OpenSnafu)?; - disco::Message::from_bytes(&sealed_box).context(ParseSnafu) + self + .get_secret(endpoint_id, |secret| secret.open(&mut sealed_box)) + .map_err(|source| e!(DiscoBoxError::Open { source }))?; + disco::Message::from_bytes(&sealed_box) + .map_err(|source| e!(DiscoBoxError::Parse { source })) } fn get_secret(&self, endpoint_id: PublicKey, cb: F) -> T @@ -1702,24 +1694,14 @@ impl DiscoState { } #[allow(missing_docs)] -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] #[non_exhaustive] enum DiscoBoxError { - #[snafu(display("Failed to open crypto box"))] - Open { - #[snafu(source(from(DecryptionError, Box::new)))] - source: Box, - }, - #[snafu(display("Failed to parse disco message"))] - Parse { - #[snafu(source(from(disco::ParseError, Box::new)))] - source: Box, - }, + #[display("Failed to open crypto box")] + Open { source: DecryptionError }, + #[display("Failed to parse disco message")] + Parse { source: disco::ParseError }, } #[derive(Debug)] @@ -2400,8 +2382,9 @@ impl DiscoveredDirectAddrs { pub(crate) struct EndpointIdMappedAddr(Ipv6Addr); /// Can occur when converting a [`SocketAddr`] to an [`EndpointIdMappedAddr`] -#[derive(Debug, Snafu)] -#[snafu(display("Failed to convert"))] +#[add_meta] +#[derive(Error)] +#[display("Failed to convert")] pub struct EndpointIdMappedAddrError; /// Counter to always generate unique addresses for [`EndpointIdMappedAddr`]. @@ -2456,7 +2439,7 @@ impl TryFrom for EndpointIdMappedAddr { { return Ok(Self(value)); } - Err(EndpointIdMappedAddrError) + Err!(EndpointIdMappedAddrError) } } @@ -2540,8 +2523,8 @@ mod tests { use data_encoding::HEXLOWER; use iroh_base::{EndpointAddr, EndpointId, PublicKey}; + use n0_error::{Result, StackResultExt, StdResultExt, AnyError}; use n0_future::{StreamExt, time}; - use n0_snafu::{Result, ResultExt}; use n0_watcher::Watcher; use quinn::ServerConfig; use rand::{CryptoRng, Rng, RngCore, SeedableRng}; @@ -2896,7 +2879,7 @@ mod tests { #[tokio::test] #[traced_test] - async fn test_regression_network_change_rebind_wakes_connection_driver() -> n0_snafu::Result { + async fn test_regression_network_change_rebind_wakes_connection_driver() -> Result { let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(0u64); let m1 = MagicStack::new(&mut rng, RelayMode::Disabled).await; let m2 = MagicStack::new(&mut rng, RelayMode::Disabled).await; @@ -2916,7 +2899,7 @@ mod tests { conn.closed().await; } - Ok::<_, n0_snafu::Error>(()) + Ok::<_, n0_error::AnyError>(()) } })); diff --git a/iroh/src/magicsock/transports/relay/actor.rs b/iroh/src/magicsock/transports/relay/actor.rs index 8ad69779c9a..15bdc280691 100644 --- a/iroh/src/magicsock/transports/relay/actor.rs +++ b/iroh/src/magicsock/transports/relay/actor.rs @@ -50,9 +50,8 @@ use n0_future::{ time::{self, Duration, Instant, MissedTickBehavior}, }; use n0_watcher::Watchable; -use nested_enum_utils::common_fields; use netwatch::interfaces; -use snafu::{IntoError, ResultExt, Snafu}; +use n0_error::{add_meta, e, Error, Err}; use tokio::sync::{mpsc, oneshot}; use tokio_util::sync::CancellationToken; use tracing::{Instrument, Level, debug, error, event, info, info_span, instrument, trace, warn}; @@ -211,60 +210,45 @@ struct RelayConnectionOptions { /// Possible reasons for a failed relay connection. #[allow(missing_docs)] -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] enum RelayConnectionError { - #[snafu(display("Failed to connect to relay server"))] + #[display("Failed to connect to relay server")] Dial { source: DialError }, - #[snafu(display("Failed to handshake with relay server"))] + #[display("Failed to handshake with relay server")] Handshake { source: RunError }, - #[snafu(display("Lost connection to relay server"))] + #[display("Lost connection to relay server")] Established { source: RunError }, } #[allow(missing_docs)] -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] enum RunError { - #[snafu(display("Send timeout"))] - SendTimeout {}, - #[snafu(display("Ping timeout"))] - PingTimeout {}, - #[snafu(display("Local IP no longer valid"))] - LocalIpInvalid {}, - #[snafu(display("No local address"))] - LocalAddrMissing {}, - #[snafu(display("Stream closed by server."))] - StreamClosedServer {}, - #[snafu(display("Client stream read failed"))] - ClientStreamRead { source: RecvError }, - #[snafu(display("Client stream write failed"))] - ClientStreamWrite { source: SendError }, + #[display("Send timeout")] + SendTimeout, + #[display("Ping timeout")] + PingTimeout, + #[display("Local IP no longer valid")] + LocalIpInvalid, + #[display("No local address")] + LocalAddrMissing, + #[display("Stream closed by server.")] + StreamClosedServer, + #[display("Client stream read failed")] + ClientStreamRead { #[error(std_err)] source: RecvError }, + #[display("Client stream write failed")] + ClientStreamWrite { #[error(std_err)] source: SendError }, } #[allow(missing_docs)] -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] enum DialError { - #[snafu(display("timeout (>{timeout:?}) trying to establish a connection"))] + #[display("timeout (>{timeout:?}) trying to establish a connection")] Timeout { timeout: Duration }, - #[snafu(display("unable to connect"))] - Connect { - #[snafu(source(from(ConnectError, Box::new)))] - source: Box, - }, + #[display("unable to connect")] + Connect { source: ConnectError }, } impl ActiveRelayActor { @@ -375,7 +359,8 @@ impl ActiveRelayActor { /// be retried with a backoff. async fn run_once(&mut self) -> Result<(), RelayConnectionError> { let client = match self.run_dialing().instrument(info_span!("dialing")).await { - Some(client_res) => client_res.context(DialSnafu)?, + Some(client_res) => client_res + .map_err(|err| e!(RelayConnectionError::Dial { source: err }))?, None => return Ok(()), }; self.run_connected(client) @@ -497,11 +482,8 @@ impl ActiveRelayActor { async move { match time::timeout(CONNECT_TIMEOUT, client_builder.connect()).await { Ok(Ok(client)) => Ok(client), - Ok(Err(err)) => Err(ConnectSnafu.into_error(err)), - Err(_) => Err(TimeoutSnafu { - timeout: CONNECT_TIMEOUT, - } - .build()), + Ok(Err(err)) => Err!(DialError::Connect { source: err }), + Err(_) => Err!(DialError::Timeout { timeout: CONNECT_TIMEOUT }), } } } @@ -523,7 +505,7 @@ impl ActiveRelayActor { ); let (mut client_stream, client_sink) = client.split(); - let mut client_sink = client_sink.sink_map_err(|e| ClientStreamWriteSnafu.into_error(e)); + let mut client_sink = client_sink.sink_map_err(|e| e!(RunError::ClientStreamWrite { source: e })); let mut state = ConnectedRelayState { ping_tracker: PingTracker::default(), @@ -568,7 +550,7 @@ impl ActiveRelayActor { } } _ = state.ping_tracker.timeout() => { - break Err(PingTimeoutSnafu.build()); + break Err!(RunError::PingTimeout); } _ = ping_interval.tick() => { let data = state.ping_tracker.new_ping(); @@ -591,8 +573,8 @@ impl ActiveRelayActor { let fut = client_sink.send(ClientToRelayMsg::Ping(data)); self.run_sending(fut, &mut state, &mut client_stream).await?; } - Some(_) => break Err(LocalIpInvalidSnafu.build()), - None => break Err(LocalAddrMissingSnafu.build()), + Some(_) => break Err!(RunError::LocalIpInvalid), + None => break Err!(RunError::LocalAddrMissing), } } #[cfg(test)] @@ -633,7 +615,7 @@ impl ActiveRelayActor { } msg = client_stream.next() => { let Some(msg) = msg else { - break Err(StreamClosedServerSnafu.build()); + break Err!(RunError::StreamClosedServer); }; match msg { Ok(msg) => { @@ -641,7 +623,7 @@ impl ActiveRelayActor { // reset the ping timer, we have just received a message ping_interval.reset(); }, - Err(err) => break Err(ClientStreamReadSnafu.into_error(err)), + Err(err) => break Err!(RunError::ClientStreamRead { source: err }), } } _ = &mut self.inactive_timeout, if !self.is_home_relay => { @@ -743,7 +725,7 @@ impl ActiveRelayActor { break Ok(()); } _ = &mut timeout => { - break Err(SendTimeoutSnafu.build()); + break Err!(RunError::SendTimeout); } msg = self.prio_inbox.recv() => { let Some(msg) = msg else { @@ -764,16 +746,16 @@ impl ActiveRelayActor { } } _ = state.ping_tracker.timeout() => { - break Err(PingTimeoutSnafu.build()); + break Err!(RunError::PingTimeout); } // No need to read the inbox or datagrams to send. msg = client_stream.next() => { let Some(msg) = msg else { - break Err(StreamClosedServerSnafu.build()); + break Err!(RunError::StreamClosedServer); }; match msg { Ok(msg) => self.handle_relay_msg(msg, state), - Err(err) => break Err(ClientStreamReadSnafu.into_error(err)), + Err(err) => break Err!(RunError::ClientStreamRead { source: err }), } } _ = &mut self.inactive_timeout, if !self.is_home_relay => { @@ -814,9 +796,9 @@ struct ConnectedRelayState { impl ConnectedRelayState { fn map_err(&self, error: RunError) -> RelayConnectionError { if self.established { - EstablishedSnafu.into_error(error) + e!(RelayConnectionError::Established { source: error }) } else { - HandshakeSnafu.into_error(error) + e!(RelayConnectionError::Handshake { source: error }) } } } @@ -1238,7 +1220,7 @@ mod tests { use iroh_base::{EndpointId, RelayUrl, SecretKey}; use iroh_relay::{PingTracker, protos::relay::Datagrams}; - use n0_snafu::{Error, Result, ResultExt}; + use n0_error::{Result, StackResultExt, StdResultExt, AnyError as Error}; use tokio::sync::{mpsc, oneshot}; use tokio_util::{sync::CancellationToken, task::AbortOnDropHandle}; use tracing::{Instrument, info, info_span}; diff --git a/iroh/src/net_report.rs b/iroh/src/net_report.rs index 752a9d8309b..e39f6429e5c 100644 --- a/iroh/src/net_report.rs +++ b/iroh/src/net_report.rs @@ -963,7 +963,7 @@ mod tests { use iroh_base::RelayUrl; use iroh_relay::dns::DnsResolver; - use n0_snafu::{Result, ResultExt}; + use n0_error::{Result, StackResultExt, StdResultExt}; use tokio_util::sync::CancellationToken; use tracing_test::traced_test; diff --git a/iroh/src/net_report/ip_mapped_addrs.rs b/iroh/src/net_report/ip_mapped_addrs.rs index 2a8927edd92..f1fae4c45d5 100644 --- a/iroh/src/net_report/ip_mapped_addrs.rs +++ b/iroh/src/net_report/ip_mapped_addrs.rs @@ -7,11 +7,12 @@ use std::{ }, }; -use snafu::Snafu; +use n0_error::{add_meta, Error, Err, e}; /// Can occur when converting a [`SocketAddr`] to an [`IpMappedAddr`] -#[derive(Debug, Snafu)] -#[snafu(display("Failed to convert"))] +#[add_meta] +#[derive(Error)] +#[display("Failed to convert")] pub struct IpMappedAddrError; /// A map fake Ipv6 address with an actual IP address. @@ -73,7 +74,7 @@ impl TryFrom for IpMappedAddr { { return Ok(Self(value)); } - Err(IpMappedAddrError) + Err!(IpMappedAddrError) } } diff --git a/iroh/src/net_report/probes.rs b/iroh/src/net_report/probes.rs index c16ca4e0350..2001dd9f8c0 100644 --- a/iroh/src/net_report/probes.rs +++ b/iroh/src/net_report/probes.rs @@ -8,7 +8,6 @@ use std::{collections::BTreeSet, fmt, sync::Arc}; use iroh_relay::{RelayConfig, RelayMap}; use n0_future::time::Duration; -use snafu::Snafu; use crate::net_report::Report; @@ -52,9 +51,7 @@ pub(super) struct ProbeSet { probes: Vec<(Duration, Arc)>, } -#[derive(Debug, Snafu)] -#[snafu(display("Mismatching probe"))] -struct PushError; +// Removed legacy SNAFU error (unused) during error migration. impl ProbeSet { fn new(proto: Probe) -> Self { diff --git a/iroh/src/net_report/reportgen.rs b/iroh/src/net_report/reportgen.rs index 18883e9a169..ddb665654ae 100644 --- a/iroh/src/net_report/reportgen.rs +++ b/iroh/src/net_report/reportgen.rs @@ -865,7 +865,7 @@ mod tests { use std::net::Ipv4Addr; use iroh_relay::dns::DnsResolver; - use n0_snafu::{Result, ResultExt}; + use n0_error::{Result, StackResultExt, StdResultExt}; use tracing_test::traced_test; use super::{super::test_utils, *}; diff --git a/iroh/src/test_utils.rs b/iroh/src/test_utils.rs index 3900703d920..99289aea032 100644 --- a/iroh/src/test_utils.rs +++ b/iroh/src/test_utils.rs @@ -519,7 +519,7 @@ pub(crate) mod pkarr_dns_state { #[cfg(test)] mod tests { use iroh_base::EndpointId; - use n0_snafu::Result; + use n0_error::Result; #[test] fn test_endpoint_id_from_domain_name() -> Result { diff --git a/iroh/src/tls/resolver.rs b/iroh/src/tls/resolver.rs index 1acb5f98a42..034068003ab 100644 --- a/iroh/src/tls/resolver.rs +++ b/iroh/src/tls/resolver.rs @@ -2,8 +2,7 @@ use std::sync::Arc; use ed25519_dalek::pkcs8::{EncodePrivateKey, spki::der::pem::LineEnding}; use iroh_base::SecretKey; -use nested_enum_utils::common_fields; -use snafu::Snafu; +use n0_error::{add_meta, Error}; use webpki_types::{CertificateDer, PrivatePkcs8KeyDer, pem::PemObject}; #[derive(Debug)] @@ -12,16 +11,13 @@ pub(super) struct AlwaysResolvesCert { } /// Error for generating TLS configs. -#[common_fields({ - backtrace: Option, - #[snafu(implicit)] - span_trace: n0_snafu::SpanTrace, -})] -#[derive(Debug, Snafu)] +#[add_meta] +#[derive(Error)] +#[error(from_sources, std_sources)] #[non_exhaustive] pub(super) enum CreateConfigError { /// Rustls configuration error - #[snafu(display("rustls error"), context(false))] + #[display("rustls error")] Rustls { source: rustls::Error }, } From 9d39c78a2da8cd18f141752a0abbd450c2e25bb2 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 17:10:29 +0200 Subject: [PATCH 11/58] fixes --- Cargo.lock | 4 +- iroh-relay/src/protos/handshake.rs | 14 +++---- iroh-relay/src/quic.rs | 34 ++++++++------- iroh-relay/src/server.rs | 6 +-- iroh-relay/src/server/client.rs | 14 +++++-- iroh-relay/src/server/http_server.rs | 39 ++++++++++------- iroh-relay/src/server/streams.rs | 5 ++- iroh/src/discovery/static_provider.rs | 2 +- iroh/src/magicsock/transports/relay/actor.rs | 44 ++++++++++++-------- 9 files changed, 93 insertions(+), 69 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cf05243999d..d85df5e0038 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2826,7 +2826,7 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error#ed20998c57f5daf45396ac3114dca6321f00d57d" +source = "git+https://github.com/n0-computer/n0-error#a51431dba41021f1dd0bfbcb1115fc3c5ec75116" dependencies = [ "anyhow", "derive_more 2.0.1", @@ -2837,7 +2837,7 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error#ed20998c57f5daf45396ac3114dca6321f00d57d" +source = "git+https://github.com/n0-computer/n0-error#a51431dba41021f1dd0bfbcb1115fc3c5ec75116" dependencies = [ "darling", "heck", diff --git a/iroh-relay/src/protos/handshake.rs b/iroh-relay/src/protos/handshake.rs index 92368a74ff7..a08b0e56af7 100644 --- a/iroh-relay/src/protos/handshake.rs +++ b/iroh-relay/src/protos/handshake.rs @@ -409,18 +409,16 @@ pub(crate) async fn serverside( let client_auth_bytes = data_encoding::BASE64URL_NOPAD .decode(client_auth_header.as_ref()) .map_err(|_| { - ClientAuthHeaderInvalidSnafu { - value: client_auth_header.clone(), - } - .build() + e!(Error::ClientAuthHeaderInvalid { + value: client_auth_header.clone() + }) })?; let client_auth: KeyMaterialClientAuth = postcard::from_bytes(&client_auth_bytes).map_err(|_| { - ClientAuthHeaderInvalidSnafu { - value: client_auth_header.clone(), - } - .build() + e!(Error::ClientAuthHeaderInvalid { + value: client_auth_header.clone() + }) })?; if client_auth.verify(io).is_ok() { diff --git a/iroh-relay/src/quic.rs b/iroh-relay/src/quic.rs index 0060ea871fe..bde7c7925d6 100644 --- a/iroh-relay/src/quic.rs +++ b/iroh-relay/src/quic.rs @@ -16,7 +16,7 @@ pub const QUIC_ADDR_DISC_CLOSE_REASON: &[u8] = b"finished"; #[cfg(feature = "server")] pub(crate) mod server { - use n0_error::StdResultExt; + use n0_error::{StdResultExt, e}; use quinn::{ ApplicationClose, ConnectionError, crypto::rustls::{NoInitialCipherSuite, QuicServerConfig}, @@ -42,7 +42,7 @@ pub(crate) mod server { pub enum QuicSpawnError { #[error(transparent)] NoInitialCipherSuite { - #[error(std_err)] + #[error(std_err, from)] source: NoInitialCipherSuite, }, #[display("Unable to spawn a QUIC endpoint server")] @@ -108,8 +108,10 @@ pub(crate) mod server { .send_observed_address_reports(true); let endpoint = quinn::Endpoint::server(server_config, quic_config.bind_addr) - .std_context("endpoint server")?; - let bind_addr = endpoint.local_addr().std_context("local addr")?; + .map_err(|err| e!(QuicSpawnError::EndpointServer, err))?; + let bind_addr = endpoint + .local_addr() + .map_err(|err| e!(QuicSpawnError::LocalAddr, err))?; info!(?bind_addr, "QUIC server listening on"); @@ -420,7 +422,7 @@ mod tests { let server_socket = tokio::net::UdpSocket::bind(SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0)) .await - .context("bind")?; + .std_context("bind")?; let server_addr = server_socket.local_addr().std_context("local addr")?; // create the client configuration used for the client endpoint when they @@ -465,22 +467,22 @@ mod tests { // need to pop off messages before we attach it to the Quinn Endpoint. let socket = tokio::net::UdpSocket::bind(SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0)) .await - .context("bind")?; + .std_context("bind")?; let server_addr = socket.local_addr().std_context("local addr")?; info!(addr = ?server_addr, "server socket bound"); // Create a QAD server with a self-signed cert, all manually. - let cert = - rcgen::generate_simple_self_signed(vec!["localhost".into()]).context("self signed")?; + let cert = rcgen::generate_simple_self_signed(vec!["localhost".into()]) + .std_context("self signed")?; let key = PrivatePkcs8KeyDer::from(cert.signing_key.serialize_der()); let mut server_crypto = rustls::ServerConfig::builder() .with_no_client_auth() .with_single_cert(vec![cert.cert.into()], key.into()) - .context("tls")?; + .std_context("tls")?; server_crypto.key_log = Arc::new(rustls::KeyLogFile::new()); server_crypto.alpn_protocols = vec![ALPN_QUIC_ADDR_DISC.to_vec()]; let mut server_config = quinn::ServerConfig::with_crypto(Arc::new( - QuicServerConfig::try_from(server_crypto).context("config")?, + QuicServerConfig::try_from(server_crypto).std_context("config")?, )); let transport_config = Arc::get_mut(&mut server_config.transport).unwrap(); transport_config.send_observed_address_reports(true); @@ -505,14 +507,14 @@ mod tests { socket.into_std().unwrap(), Arc::new(quinn::TokioRuntime), ) - .context("endpoint new")?; + .std_context("endpoint new")?; info!("accepting conn"); let incoming = server.accept().await.expect("missing conn"); info!("incoming!"); - let conn = incoming.await.context("incoming")?; + let conn = incoming.await.std_context("incoming")?; conn.closed().await; server.wait_idle().await; - Ok::<_, Error>(()) + n0_error::Ok(()) } .instrument(info_span!("server")), ); @@ -535,15 +537,15 @@ mod tests { quic_client.get_addr_and_latency(server_addr, "localhost"), ) .await - .context("timeout")??; + .std_context("timeout")??; let duration = start.elapsed(); info!(?duration, ?addr, ?latency, "QAD succeeded"); assert!(duration >= Duration::from_secs(1)); time::timeout(Duration::from_secs(10), server_task) .await - .context("timeout")? - .context("server task")??; + .std_context("timeout")? + .std_context("server task")??; Ok(()) } diff --git a/iroh-relay/src/server.rs b/iroh-relay/src/server.rs index b037aab0800..3ac5c172a15 100644 --- a/iroh-relay/src/server.rs +++ b/iroh-relay/src/server.rs @@ -266,7 +266,7 @@ pub struct Server { /// Server spawn errors #[allow(missing_docs)] #[add_meta] -#[derive(Error, Debug)] +#[derive(Error)] #[non_exhaustive] pub enum SpawnError { #[display("Unable to get local address")] @@ -301,7 +301,7 @@ pub enum SpawnError { /// Server task errors #[allow(missing_docs)] #[add_meta] -#[derive(Error, Debug)] +#[derive(Error)] #[non_exhaustive] pub enum SupervisorError { #[display("Error starting metrics server")] @@ -313,7 +313,7 @@ pub enum SupervisorError { AcmeEventStreamFinished {}, #[error(transparent)] JoinError { - #[error(std_err)] + #[error(from, std_err)] source: JoinError, }, #[display("No relay services are enabled")] diff --git a/iroh-relay/src/server/client.rs b/iroh-relay/src/server/client.rs index e0e1ee2a596..76d346b5481 100644 --- a/iroh-relay/src/server/client.rs +++ b/iroh-relay/src/server/client.rs @@ -3,7 +3,7 @@ use std::{collections::HashSet, sync::Arc, time::Duration}; use iroh_base::EndpointId; -use n0_error::{Err, Error, add_meta, e}; +use n0_error::{Err, Error, StackResultExt, add_meta, e}; use n0_future::{SinkExt, StreamExt}; use rand::Rng; use time::{Date, OffsetDateTime}; @@ -209,11 +209,17 @@ pub enum WriteFrameError { #[non_exhaustive] pub enum RunError { #[error(transparent)] - ForwardPacket { source: ForwardPacketError }, + ForwardPacket { + #[error(from)] + source: ForwardPacketError, + }, #[display("Flush")] Flush {}, #[error(transparent)] - HandleFrame { source: HandleFrameError }, + HandleFrame { + #[error(from)] + source: HandleFrameError, + }, #[display("Server.disco_send_queue dropped")] DiscoSendQueuePacketDrop {}, #[display("Failed to send disco packet")] @@ -315,7 +321,7 @@ impl Actor { _ = done.cancelled() => { trace!("actor loop cancelled, exiting"); // final flush - self.stream.flush().await.map_err(|_| FlushSnafu.build())?; + self.stream.flush().await.map_err(|_| e!(RunError::Flush))?; break; } maybe_frame = self.stream.next() => { diff --git a/iroh-relay/src/server/http_server.rs b/iroh-relay/src/server/http_server.rs index a27966eed3e..45a24909ea7 100644 --- a/iroh-relay/src/server/http_server.rs +++ b/iroh-relay/src/server/http_server.rs @@ -15,9 +15,8 @@ use hyper::{ service::Service, upgrade::Upgraded, }; -use n0_error::{Err, Error, StdResultExt, add_meta, e}; +use n0_error::{Err, Error, StackResultExt, StdResultExt, add_meta, e}; use n0_future::time::Elapsed; -use snafu::OptionExt; use tokio::net::{TcpListener, TcpStream}; use tokio_rustls_acme::AcmeAcceptor; use tokio_util::{sync::CancellationToken, task::AbortOnDropHandle}; @@ -37,7 +36,7 @@ use crate::{ streams::WsBytesFramed, }, server::{ - BindTcpListenerSnafu, ClientRateLimit, NoLocalAddrSnafu, + ClientRateLimit, client::Config, metrics::Metrics, streams::{MaybeTlsStream, RateLimited, RelayedStream}, @@ -200,7 +199,10 @@ pub enum ServeConnectionError { #[non_exhaustive] pub enum AcceptError { #[error(transparent)] - Handshake { source: handshake::Error }, + Handshake { + #[error(from)] + source: handshake::Error, + }, #[display("rate limiting misconfigured")] RateLimitingMisconfigured { source: InvalidBucketConfig }, } @@ -212,7 +214,10 @@ pub enum AcceptError { #[non_exhaustive] pub enum ConnectionHandlerError { #[error(transparent)] - Accept { source: AcceptError }, + Accept { + #[error(from)] + source: AcceptError, + }, #[display("Could not downcast the upgraded connection to MaybeTlsStream")] DowncastUpgrade {}, #[display("Cannot deal with buffered data yet: {buf:?}")] @@ -337,9 +342,11 @@ impl ServerBuilder { let listener = TcpListener::bind(&addr) .await - .map_err(|_| BindTcpListenerSnafu { addr }.build())?; + .map_err(|_| e!(super::SpawnError::BindTcpListener { addr }))?; - let addr = listener.local_addr().std_context("no-local-addr")?; + let addr = listener + .local_addr() + .map_err(|source| e!(super::SpawnError::NoLocalAddr { source }))?; let http_str = tls_config.as_ref().map_or("HTTP/WS", |_| "HTTPS/WSS"); info!("[{http_str}] relay: serving on {addr}"); @@ -411,7 +418,7 @@ struct Inner { } #[add_meta] -#[derive(Error, Debug)] +#[derive(Error)] enum RelayUpgradeReqError { #[display("missing header: {header}")] MissingHeader { header: http::HeaderName }, @@ -557,7 +564,7 @@ impl Service> for RelayService { let res = match self.handle_relay_ws_upgrade(req) { Ok(response) => Ok(response), // It's convention to send back the version(s) we *do* support - Err(e @ RelayUpgradeReqError::UnsupportedWebsocketVersion) => self + Err(e @ RelayUpgradeReqError::UnsupportedWebsocketVersion { .. }) => self .build_response() .status(StatusCode::BAD_REQUEST) .header(SEC_WEBSOCKET_VERSION, SUPPORTED_WEBSOCKET_VERSION) @@ -796,7 +803,7 @@ impl RelayService { debug!("TLS[manual]: accept"); let tls_stream = tokio::time::timeout(Duration::from_secs(30), a.accept(stream)) .await - .std_context("timeout")? + .map_err(|err| e!(ServeConnectionError::Timeout, err))? .map_err(|err| e!(ServeConnectionError::ManualAccept, err))?; self.serve_connection(MaybeTlsStream::Tls(tls_stream)) @@ -1086,7 +1093,7 @@ mod tests { client_a.close().await?; client_b.close().await?; server.shutdown(); - server.task_handle().await.context("join")?; + server.task_handle().await.std_context("join")?; Ok(()) } @@ -1122,7 +1129,7 @@ mod tests { let handler_task = tokio::spawn(async move { s.0.accept(MaybeTlsStream::Test(rw_a), None).await }); let mut client_a = make_test_client(client_a, &key_a).await?; - handler_task.await.context("join")??; + handler_task.await.std_context("join")??; info!("Create client B and connect it to the server."); let key_b = SecretKey::generate(&mut rng); @@ -1132,7 +1139,7 @@ mod tests { let handler_task = tokio::spawn(async move { s.0.accept(MaybeTlsStream::Test(rw_b), None).await }); let mut client_b = make_test_client(client_b, &key_b).await?; - handler_task.await.context("join")??; + handler_task.await.std_context("join")??; info!("Send message from A to B."); let msg = Datagrams::from(b"hello client b!!"); @@ -1222,7 +1229,7 @@ mod tests { let handler_task = tokio::spawn(async move { s.0.accept(MaybeTlsStream::Test(rw_a), None).await }); let mut client_a = make_test_client(client_a, &key_a).await?; - handler_task.await.context("join")??; + handler_task.await.std_context("join")??; info!("Create client B and connect it to the server."); let key_b = SecretKey::generate(&mut rng); @@ -1232,7 +1239,7 @@ mod tests { let handler_task = tokio::spawn(async move { s.0.accept(MaybeTlsStream::Test(rw_b), None).await }); let mut client_b = make_test_client(client_b, &key_b).await?; - handler_task.await.context("join")??; + handler_task.await.std_context("join")??; info!("Send message from A to B."); let msg = Datagrams::from(b"hello client b!!"); @@ -1282,7 +1289,7 @@ mod tests { let handler_task = tokio::spawn(async move { s.0.accept(MaybeTlsStream::Test(new_rw_b), None).await }); let mut new_client_b = make_test_client(new_client_b, &key_b).await?; - handler_task.await.context("join")??; + handler_task.await.std_context("join")??; // assert!(client_b.recv().await.is_err()); diff --git a/iroh-relay/src/server/streams.rs b/iroh-relay/src/server/streams.rs index 309dfad6323..032c04f930b 100644 --- a/iroh-relay/src/server/streams.rs +++ b/iroh-relay/src/server/streams.rs @@ -81,7 +81,7 @@ impl RelayedStream { pub enum SendError { #[error(transparent)] StreamError { - #[error(std_err)] + #[error(from, std_err)] source: StreamError, }, #[display("Packet exceeds max packet size")] @@ -124,6 +124,7 @@ impl Sink for RelayedStream { /// Relay receive errors #[add_meta] #[derive(Error)] +#[error(from_sources)] #[non_exhaustive] pub enum RecvError { #[error(transparent)] @@ -489,7 +490,7 @@ impl AsyncWrite for RateLimited { mod tests { use std::sync::Arc; - use n0_error::Result; + use n0_error::{Result, StdResultExt}; use n0_future::time; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tracing_test::traced_test; diff --git a/iroh/src/discovery/static_provider.rs b/iroh/src/discovery/static_provider.rs index 4fee934b4a3..3ee8ec78a7f 100644 --- a/iroh/src/discovery/static_provider.rs +++ b/iroh/src/discovery/static_provider.rs @@ -235,7 +235,7 @@ impl Discovery for StaticProvider { #[cfg(test)] mod tests { use iroh_base::{EndpointAddr, SecretKey}; - use n0_snafu::{Result, ResultExt}; + use n0_error::{Result, StackResultExt}; use super::*; use crate::{Endpoint, RelayMode}; diff --git a/iroh/src/magicsock/transports/relay/actor.rs b/iroh/src/magicsock/transports/relay/actor.rs index 15bdc280691..56701b219a1 100644 --- a/iroh/src/magicsock/transports/relay/actor.rs +++ b/iroh/src/magicsock/transports/relay/actor.rs @@ -44,6 +44,7 @@ use iroh_relay::{ client::{Client, ConnectError, RecvError, SendError}, protos::relay::{ClientToRelayMsg, Datagrams, RelayToClientMsg}, }; +use n0_error::{Err, Error, add_meta, e}; use n0_future::{ FuturesUnorderedBounded, SinkExt, StreamExt, task::JoinSet, @@ -51,7 +52,6 @@ use n0_future::{ }; use n0_watcher::Watchable; use netwatch::interfaces; -use n0_error::{add_meta, e, Error, Err}; use tokio::sync::{mpsc, oneshot}; use tokio_util::sync::CancellationToken; use tracing::{Instrument, Level, debug, error, event, info, info_span, instrument, trace, warn}; @@ -236,9 +236,15 @@ enum RunError { #[display("Stream closed by server.")] StreamClosedServer, #[display("Client stream read failed")] - ClientStreamRead { #[error(std_err)] source: RecvError }, + ClientStreamRead { + #[error(std_err)] + source: RecvError, + }, #[display("Client stream write failed")] - ClientStreamWrite { #[error(std_err)] source: SendError }, + ClientStreamWrite { + #[error(std_err)] + source: SendError, + }, } #[allow(missing_docs)] @@ -359,8 +365,9 @@ impl ActiveRelayActor { /// be retried with a backoff. async fn run_once(&mut self) -> Result<(), RelayConnectionError> { let client = match self.run_dialing().instrument(info_span!("dialing")).await { - Some(client_res) => client_res - .map_err(|err| e!(RelayConnectionError::Dial { source: err }))?, + Some(client_res) => { + client_res.map_err(|err| e!(RelayConnectionError::Dial { source: err }))? + } None => return Ok(()), }; self.run_connected(client) @@ -483,7 +490,9 @@ impl ActiveRelayActor { match time::timeout(CONNECT_TIMEOUT, client_builder.connect()).await { Ok(Ok(client)) => Ok(client), Ok(Err(err)) => Err!(DialError::Connect { source: err }), - Err(_) => Err!(DialError::Timeout { timeout: CONNECT_TIMEOUT }), + Err(_) => Err!(DialError::Timeout { + timeout: CONNECT_TIMEOUT + }), } } } @@ -505,7 +514,8 @@ impl ActiveRelayActor { ); let (mut client_stream, client_sink) = client.split(); - let mut client_sink = client_sink.sink_map_err(|e| e!(RunError::ClientStreamWrite { source: e })); + let mut client_sink = + client_sink.sink_map_err(|e| e!(RunError::ClientStreamWrite { source: e })); let mut state = ConnectedRelayState { ping_tracker: PingTracker::default(), @@ -1220,7 +1230,7 @@ mod tests { use iroh_base::{EndpointId, RelayUrl, SecretKey}; use iroh_relay::{PingTracker, protos::relay::Datagrams}; - use n0_error::{Result, StackResultExt, StdResultExt, AnyError as Error}; + use n0_error::{AnyError as Error, Result, StackResultExt, StdResultExt}; use tokio::sync::{mpsc, oneshot}; use tokio_util::{sync::CancellationToken, task::AbortOnDropHandle}; use tracing::{Instrument, info, info_span}; @@ -1339,7 +1349,7 @@ mod tests { tokio::time::timeout(Duration::from_secs(10), async move { loop { let res = tokio::time::timeout(UNDELIVERABLE_DATAGRAM_TIMEOUT, async { - tx.send(item.clone()).await.context("send item")?; + tx.send(item.clone()).await.std_context("send item")?; let RelayRecvDatagram { url: _, src: _, @@ -1403,17 +1413,17 @@ mod tests { inbox_tx .send(ActiveRelayMessage::GetLocalAddr(tx)) .await - .context("send get local addr msg")?; + .std_context("send get local addr msg")?; let local_addr = rx .await - .context("wait for local addr msg")? + .std_context("wait for local addr msg")? .context("no local addr")?; info!(?local_addr, "check connection with addr"); inbox_tx .send(ActiveRelayMessage::CheckConnection(vec![local_addr.ip()])) .await - .context("send check connection message")?; + .std_context("send check connection message")?; // Sync the ActiveRelayActor. Ping blocks it and we want to be sure it has handled // another inbox message before continuing. @@ -1421,8 +1431,8 @@ mod tests { inbox_tx .send(ActiveRelayMessage::GetLocalAddr(tx)) .await - .context("send get local addr msg")?; - rx.await.context("recv send local addr msg")?; + .std_context("send get local addr msg")?; + rx.await.std_context("recv send local addr msg")?; // Echo should still work. info!("second echo"); @@ -1439,7 +1449,7 @@ mod tests { inbox_tx .send(ActiveRelayMessage::CheckConnection(Vec::new())) .await - .context("send check connection msg")?; + .std_context("send check connection msg")?; // Give some time to reconnect, mostly to sort logs rather than functional. tokio::time::sleep(Duration::from_millis(10)).await; @@ -1455,7 +1465,7 @@ mod tests { // Shut down the actor. cancel_token.cancel(); - task.await.context("wait for task to finish")?; + task.await.std_context("wait for task to finish")?; Ok(()) } @@ -1497,7 +1507,7 @@ mod tests { } }) .await - .context("timeout")?; + .std_context("timeout")?; // From now on, we pause time tokio::time::pause(); From 4e830d1b8def8ace1ad67b35a8bb4710d3d2b8fd Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 17:31:38 +0200 Subject: [PATCH 12/58] wip --- Cargo.lock | 3 ++- iroh-dns-server/Cargo.toml | 1 + iroh-dns-server/src/lib.rs | 18 ++++++++------ iroh-relay/src/server/client.rs | 5 +++- iroh/bench/Cargo.toml | 2 +- iroh/bench/src/bin/bulk.rs | 2 +- iroh/bench/src/iroh.rs | 18 +++++++------- iroh/bench/src/lib.rs | 2 +- iroh/bench/src/quinn.rs | 18 +++++++------- iroh/src/discovery.rs | 16 ++++++------ iroh/src/discovery/mdns.rs | 10 ++++---- iroh/src/endpoint.rs | 4 +-- iroh/src/magicsock.rs | 44 ++++++++++++++++----------------- iroh/tests/integration.rs | 4 +-- 14 files changed, 77 insertions(+), 70 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d85df5e0038..7ffe62f3c18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2355,8 +2355,8 @@ dependencies = [ "iroh", "iroh-metrics", "iroh-quinn", + "n0-error", "n0-future 0.3.0", - "n0-snafu", "rand 0.9.2", "rcgen 0.14.5", "rustls", @@ -2388,6 +2388,7 @@ dependencies = [ "iroh", "iroh-metrics", "lru 0.16.1", + "n0-error", "n0-future 0.3.0", "n0-snafu", "pkarr", diff --git a/iroh-dns-server/Cargo.toml b/iroh-dns-server/Cargo.toml index 2ed91c0aa93..ffd0d06dc23 100644 --- a/iroh-dns-server/Cargo.toml +++ b/iroh-dns-server/Cargo.toml @@ -64,6 +64,7 @@ criterion = "0.7.0" data-encoding = "2.3.3" hickory-resolver = "0.25.0" iroh = { path = "../iroh" } +n0-error = { git = "https://github.com/n0-computer/n0-error" } rand = "0.9.2" rand_chacha = "0.9" tracing-test = "0.2.5" diff --git a/iroh-dns-server/src/lib.rs b/iroh-dns-server/src/lib.rs index c381a1774f2..1a0e16e551a 100644 --- a/iroh-dns-server/src/lib.rs +++ b/iroh-dns-server/src/lib.rs @@ -43,7 +43,7 @@ mod tests { #[tokio::test] #[traced_test] async fn pkarr_publish_dns_resolve() -> Result { - let (server, nameserver, http_url) = Server::spawn_for_tests().await?; + let (server, nameserver, http_url) = Server::spawn_for_tests().await.e()?; let pkarr_relay_url = { let mut url = http_url.clone(); url.set_path("/pkarr"); @@ -117,7 +117,7 @@ mod tests { // resolve root record let name = Name::from_utf8(format!("{pubkey}.")).e()?; - let res = resolver.lookup_txt(name, DNS_TIMEOUT).await?; + let res = resolver.lookup_txt(name, DNS_TIMEOUT).await.e()?; let records = res.into_iter().map(|t| t.to_string()).collect::>(); assert_eq!(records, vec!["hi0".to_string()]); @@ -200,7 +200,7 @@ mod tests { max_batch_time: Duration::from_millis(100), ..Default::default() }; - let store = ZoneStore::in_memory(options, Default::default())?; + let store = ZoneStore::in_memory(options, Default::default()).e()?; // create a signed packet let signed_packet = random_signed_packet(&mut rng)?; @@ -208,11 +208,12 @@ mod tests { store .insert(signed_packet, PacketSource::PkarrPublish) - .await?; + .await + .e()?; tokio::time::sleep(Duration::from_secs(1)).await; for _ in 0..10 { - let entry = store.get_signed_packet(&key).await?; + let entry = store.get_signed_packet(&key).await.e()?; if entry.is_none() { return Ok(()); } @@ -233,7 +234,8 @@ mod tests { // spawn our server with mainline support let (server, nameserver, _http_url) = Server::spawn_for_tests_with_options(Some(BootstrapOption::Custom(bootstrap)), None) - .await?; + .await + .e()?; let origin = "irohdns.example."; @@ -254,12 +256,12 @@ mod tests { // resolve via DNS from our server, which will lookup from our DHT let resolver = test_resolver(nameserver); - let res = resolver.lookup_endpoint_by_id(&endpoint_id, origin).await?; + let res = resolver.lookup_endpoint_by_id(&endpoint_id, origin).await.e()?; assert_eq!(res.endpoint_id, endpoint_id); assert_eq!(res.relay_url(), Some(&relay_url)); - server.shutdown().await?; + server.shutdown().await.e()?; Ok(()) } diff --git a/iroh-relay/src/server/client.rs b/iroh-relay/src/server/client.rs index 76d346b5481..a7cb42b98f1 100644 --- a/iroh-relay/src/server/client.rs +++ b/iroh-relay/src/server/client.rs @@ -325,7 +325,10 @@ impl Actor { break; } maybe_frame = self.stream.next() => { - self.handle_frame(maybe_frame).await?; + self + .handle_frame(maybe_frame) + .await + .map_err(|source| e!(RunError::HandleFrame { source }))?; // reset the ping interval, we just received a message ping_interval.reset(); } diff --git a/iroh/bench/Cargo.toml b/iroh/bench/Cargo.toml index c5df9439638..34a7140e64f 100644 --- a/iroh/bench/Cargo.toml +++ b/iroh/bench/Cargo.toml @@ -11,7 +11,7 @@ hdrhistogram = { version = "7.2", default-features = false } iroh = { path = ".." } iroh-metrics = "0.36" n0-future = "0.3.0" -n0-snafu = "0.2.0" +n0-error = { git = "https://github.com/n0-computer/n0-error" } quinn = { package = "iroh-quinn", version = "0.14" } rand = "0.9.2" rcgen = "0.14" diff --git a/iroh/bench/src/bin/bulk.rs b/iroh/bench/src/bin/bulk.rs index b666a1a20fd..b38d87e02f3 100644 --- a/iroh/bench/src/bin/bulk.rs +++ b/iroh/bench/src/bin/bulk.rs @@ -5,7 +5,7 @@ use clap::Parser; use iroh_bench::quinn; use iroh_bench::{Commands, Opt, configure_tracing_subscriber, iroh, rt, s2n}; use iroh_metrics::{MetricValue, MetricsGroup}; -use n0_snafu::Result; +use n0_error::Result; fn main() { let cmd = Commands::parse(); diff --git a/iroh/bench/src/iroh.rs b/iroh/bench/src/iroh.rs index d43d5314c07..4720e845917 100644 --- a/iroh/bench/src/iroh.rs +++ b/iroh/bench/src/iroh.rs @@ -8,7 +8,7 @@ use iroh::{ Endpoint, EndpointAddr, RelayMode, RelayUrl, endpoint::{Connection, ConnectionError, RecvStream, SendStream, TransportConfig}, }; -use n0_snafu::{Result, ResultExt}; +use n0_error::{Result, StackResultExt, StdResultExt}; use tracing::{trace, warn}; use crate::{ @@ -120,7 +120,7 @@ pub async fn connect_client( let connection = endpoint .connect(server_addr, ALPN) .await - .context("unable to connect")?; + .std_context("unable to connect")?; trace!("connected"); Ok((endpoint, connection)) @@ -200,21 +200,21 @@ async fn send_data_on_stream(stream: &mut SendStream, stream_size: u64) -> Resul stream .write_chunk(bytes_data.clone()) .await - .context("failed sending data")?; + .std_context("failed sending data")?; } if remaining != 0 { stream .write_chunk(bytes_data.slice(0..remaining)) .await - .context("failed sending data")?; + .std_context("failed sending data")?; } - stream.finish().context("failed finishing stream")?; + stream.finish().std_context("failed finishing stream")?; stream .stopped() .await - .context("failed to wait for stream to be stopped")?; + .std_context("failed to wait for stream to be stopped")?; Ok(()) } @@ -229,7 +229,7 @@ pub async fn handle_client_stream( let (mut send_stream, mut recv_stream) = connection .open_bi() .await - .context("failed to open stream")?; + .std_context("failed to open stream")?; send_data_on_stream(&mut send_stream, upload_size).await?; @@ -258,7 +258,7 @@ pub async fn server(endpoint: Endpoint, opt: Opt) -> Result<()> { continue; } }; - let connection = connecting.await.context("handshake failed")?; + let connection = connecting.await.std_context("handshake failed")?; server_tasks.push(tokio::spawn(async move { loop { @@ -275,7 +275,7 @@ pub async fn server(endpoint: Endpoint, opt: Opt) -> Result<()> { tokio::spawn(async move { drain_stream(&mut recv_stream, opt.read_unordered).await?; send_data_on_stream(&mut send_stream, opt.download_size).await?; - Ok::<_, n0_snafu::Error>(()) + Ok::<_, n0_error::AnyError>(()) }); } diff --git a/iroh/bench/src/lib.rs b/iroh/bench/src/lib.rs index 4921793db69..0e6669b38a6 100644 --- a/iroh/bench/src/lib.rs +++ b/iroh/bench/src/lib.rs @@ -6,7 +6,7 @@ use std::{ }; use clap::Parser; -use n0_snafu::Result; +use n0_error::Result; use stats::Stats; use tokio::{ runtime::{Builder, Runtime}, diff --git a/iroh/bench/src/quinn.rs b/iroh/bench/src/quinn.rs index e9ca57c33ad..9021a32a5e2 100644 --- a/iroh/bench/src/quinn.rs +++ b/iroh/bench/src/quinn.rs @@ -5,7 +5,7 @@ use std::{ }; use bytes::Bytes; -use n0_snafu::{Result, ResultExt}; +use n0_error::{Result, StdResultExt}; use quinn::{ Connection, Endpoint, RecvStream, SendStream, TransportConfig, crypto::rustls::QuicClientConfig, }; @@ -91,7 +91,7 @@ pub async fn connect_client( .connect_with(client_config, server_addr, "localhost") .unwrap() .await - .context("unable to connect")?; + .std_context("unable to connect")?; trace!("connected"); Ok((endpoint, connection)) @@ -171,21 +171,21 @@ async fn send_data_on_stream(stream: &mut SendStream, stream_size: u64) -> Resul stream .write_chunk(bytes_data.clone()) .await - .context("failed sending data")?; + .std_context("failed sending data")?; } if remaining != 0 { stream .write_chunk(bytes_data.slice(0..remaining)) .await - .context("failed sending data")?; + .std_context("failed sending data")?; } - stream.finish().context("failed finishing stream")?; + stream.finish().std_context("failed finishing stream")?; stream .stopped() .await - .context("failed to wait for stream to be stopped")?; + .std_context("failed to wait for stream to be stopped")?; Ok(()) } @@ -200,7 +200,7 @@ pub async fn handle_client_stream( let (mut send_stream, mut recv_stream) = connection .open_bi() .await - .context("failed to open stream")?; + .std_context("failed to open stream")?; send_data_on_stream(&mut send_stream, upload_size).await?; @@ -229,7 +229,7 @@ pub async fn server(endpoint: Endpoint, opt: Opt) -> Result<()> { continue; } }; - let connection = connecting.await.context("handshake failed")?; + let connection = connecting.await.std_context("handshake failed")?; server_tasks.push(tokio::spawn(async move { loop { @@ -246,7 +246,7 @@ pub async fn server(endpoint: Endpoint, opt: Opt) -> Result<()> { tokio::spawn(async move { drain_stream(&mut recv_stream, opt.read_unordered).await?; send_data_on_stream(&mut send_stream, opt.download_size).await?; - Ok::<_, n0_snafu::Error>(()) + Ok::<_, n0_error::AnyError>(()) }); } diff --git a/iroh/src/discovery.rs b/iroh/src/discovery.rs index 4a031618017..b5f7b8677e8 100644 --- a/iroh/src/discovery.rs +++ b/iroh/src/discovery.rs @@ -942,7 +942,7 @@ mod tests { // we skip accept() errors, they can be caused by retransmits while let Some(connecting) = ep.accept().await.and_then(|inc| inc.accept().ok()) { // Just accept incoming connections, but don't do anything with them. - let conn = connecting.await.context("connecting")?; + let conn = connecting.await.std_context("connecting")?; connections.push(conn); } @@ -995,7 +995,7 @@ mod test_dns_pkarr { let state = State::new(origin.clone()); let (nameserver, _dns_drop_guard) = run_dns_server(state.clone()) .await - .context("Running DNS server")?; + .std_context("Running DNS server")?; let secret_key = SecretKey::generate(&mut rng); let endpoint_info = EndpointInfo::new(secret_key.public()) @@ -1003,7 +1003,7 @@ mod test_dns_pkarr { let signed_packet = endpoint_info.to_pkarr_signed_packet(&secret_key, 30)?; state .upsert(signed_packet) - .context("update and insert signed packet")?; + .std_context("update and insert signed packet")?; let resolver = DnsResolver::with_nameserver(nameserver); let resolved = resolver @@ -1023,7 +1023,7 @@ mod test_dns_pkarr { let dns_pkarr_server = DnsPkarrServer::run_with_origin(origin.clone()) .await - .context("DnsPkarrServer")?; + .std_context("DnsPkarrServer")?; let secret_key = SecretKey::generate(&mut rng); let endpoint_id = secret_key.public(); @@ -1042,7 +1042,7 @@ mod test_dns_pkarr { dns_pkarr_server .on_endpoint(&endpoint_id, PUBLISH_TIMEOUT) .await - .context("wait for on endpoint update")?; + .std_context("wait for on endpoint update")?; let resolved = resolver .lookup_endpoint_by_id(&endpoint_id, &origin) .await?; @@ -1066,7 +1066,7 @@ mod test_dns_pkarr { async fn pkarr_publish_dns_discover() -> Result<()> { let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(0u64); - let dns_pkarr_server = DnsPkarrServer::run().await.context("DnsPkarrServer run")?; + let dns_pkarr_server = DnsPkarrServer::run().await.std_context("DnsPkarrServer run")?; let (relay_map, _relay_url, _relay_guard) = run_relay_server().await?; let (ep1, _guard1) = ep_with_discovery(&mut rng, &relay_map, &dns_pkarr_server).await?; @@ -1076,7 +1076,7 @@ mod test_dns_pkarr { dns_pkarr_server .on_endpoint(&ep1.id(), PUBLISH_TIMEOUT) .await - .context("wait for on endpoint update")?; + .std_context("wait for on endpoint update")?; // we connect only by endpoint id! let _conn = ep2.connect(ep1.id(), TEST_ALPN).await?; @@ -1103,7 +1103,7 @@ mod test_dns_pkarr { async move { // we skip accept() errors, they can be caused by retransmits while let Some(connecting) = ep.accept().await.and_then(|inc| inc.accept().ok()) { - let _conn = connecting.await.context("connecting")?; + let _conn = connecting.await.std_context("connecting")?; // Just accept incoming connections, but don't do anything with them. } diff --git a/iroh/src/discovery/mdns.rs b/iroh/src/discovery/mdns.rs index 6169ae1332a..a7515b1808c 100644 --- a/iroh/src/discovery/mdns.rs +++ b/iroh/src/discovery/mdns.rs @@ -591,7 +591,7 @@ mod tests { .. } = tokio::time::timeout(Duration::from_secs(5), s1.next()) .await - .context("timeout")? + .std_context("timeout")? .unwrap() else { panic!("Received unexpected discovery event"); @@ -601,7 +601,7 @@ mod tests { .. } = tokio::time::timeout(Duration::from_secs(5), s2.next()) .await - .context("timeout")? + .std_context("timeout")? .unwrap() else { panic!("Received unexpected discovery event"); @@ -632,7 +632,7 @@ mod tests { loop { let event = tokio::time::timeout(Duration::from_secs(5), s1.next()) .await - .context("timeout")? + .std_context("timeout")? .expect("Stream should not be closed"); match event { @@ -653,7 +653,7 @@ mod tests { loop { let event = tokio::time::timeout(Duration::from_secs(10), s1.next()) .await - .context("timeout waiting for expiration event")? + .std_context("timeout waiting for expiration event")? .expect("Stream should not be closed"); match event { @@ -717,7 +717,7 @@ mod tests { }; tokio::time::timeout(Duration::from_secs(5), test) .await - .context("timeout")? + .std_context("timeout")? } #[tokio::test] diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 6dd743cae26..56da2dd34e6 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -3019,7 +3019,7 @@ mod tests { let mut registry = Registry::default(); register_endpoint(&mut registry, &client); register_endpoint(&mut registry, &server); - let s = registry.encode_openmetrics_to_string()?; + let s = registry.encode_openmetrics_to_string().e()?; assert!(s.contains(r#"magicsock_endpoints_contacted_directly_total{id="3b6a27bcce"} 1"#)); assert!(s.contains(r#"magicsock_endpoints_contacted_directly_total{id="8a88e3dd74"} 1"#)); Ok(()) @@ -3125,7 +3125,7 @@ mod tests { let endpoint = Endpoint::empty_builder(RelayMode::Staging).bind().await?; // can get a first report - endpoint.net_report().updated().await?; + endpoint.net_report().updated().await.e()?; Ok(()) } diff --git a/iroh/src/magicsock.rs b/iroh/src/magicsock.rs index 56fc6f7c5e8..8c8fcfcd827 100644 --- a/iroh/src/magicsock.rs +++ b/iroh/src/magicsock.rs @@ -2697,7 +2697,7 @@ mod tests { } }) .await - .context("timeout")?; + .std_context("timeout")?; info!("all endpoints meshed"); Ok(tasks) } @@ -2708,24 +2708,24 @@ mod tests { let conn = ep.endpoint.accept().await.expect("no conn"); info!("connecting"); - let conn = conn.await.context("connecting")?; + let conn = conn.await.std_context("connecting")?; info!("accepting bi"); - let (mut send_bi, mut recv_bi) = conn.accept_bi().await.context("accept bi")?; + let (mut send_bi, mut recv_bi) = conn.accept_bi().await.std_context("accept bi")?; info!("reading"); let val = recv_bi .read_to_end(usize::MAX) .await - .context("read to end")?; + .std_context("read to end")?; info!("replying"); for chunk in val.chunks(12) { - send_bi.write_all(chunk).await.context("write all")?; + send_bi.write_all(chunk).await.std_context("write all")?; } info!("finishing"); - send_bi.finish().context("finish")?; - send_bi.stopped().await.context("stopped")?; + send_bi.finish().std_context("finish")?; + send_bi.stopped().await.std_context("stopped")?; let stats = conn.stats(); info!("stats: {:#?}", stats); @@ -2757,20 +2757,20 @@ mod tests { let conn = ep.endpoint.connect(dest, ALPN).await?; info!("opening bi"); - let (mut send_bi, mut recv_bi) = conn.open_bi().await.context("open bi")?; + let (mut send_bi, mut recv_bi) = conn.open_bi().await.std_context("open bi")?; info!("writing message"); - send_bi.write_all(msg).await.context("write all")?; + send_bi.write_all(msg).await.std_context("write all")?; info!("finishing"); - send_bi.finish().context("finish")?; - send_bi.stopped().await.context("stopped")?; + send_bi.finish().std_context("finish")?; + send_bi.stopped().await.std_context("stopped")?; info!("reading_to_end"); let val = recv_bi .read_to_end(usize::MAX) .await - .context("read to end")?; + .std_context("read to end")?; assert_eq!( val, msg, @@ -2921,7 +2921,7 @@ mod tests { test_two_devices_roundtrip_network_change_impl(), ) .await - .context("timeout")? + .std_context("timeout")? } /// Same structure as `test_two_devices_roundtrip_quinn_magic`, but interrupts regularly @@ -3147,7 +3147,7 @@ mod tests { mapped_addr.private_socket_addr(), &tls::name::encode(endpoint_id), ) - .context("connect")?; + .std_context("connect")?; let connection = connect.await.e()?; Ok(connection) } @@ -3191,12 +3191,12 @@ mod tests { // This needs an accept task let accept_task = tokio::spawn({ async fn accept(ep: quinn::Endpoint) -> Result<()> { - let incoming = ep.accept().await.context("no incoming")?; + let incoming = ep.accept().await.std_context("no incoming")?; let _conn = incoming .accept() - .context("accept")? + .std_context("accept")? .await - .context("connecting")?; + .std_context("connecting")?; // Keep this connection alive for a while tokio::time::sleep(Duration::from_secs(10)).await; @@ -3268,14 +3268,14 @@ mod tests { // We need a task to accept the connection. let accept_task = tokio::spawn({ async fn accept(ep: quinn::Endpoint) -> Result<()> { - let incoming = ep.accept().await.context("no incoming")?; + let incoming = ep.accept().await.std_context("no incoming")?; let conn = incoming .accept() - .context("accept")? + .std_context("accept")? .await - .context("connecting")?; - let mut stream = conn.accept_uni().await.context("accept uni")?; - stream.read_to_end(1 << 16).await.context("read to end")?; + .std_context("connecting")?; + let mut stream = conn.accept_uni().await.std_context("accept uni")?; + stream.read_to_end(1 << 16).await.std_context("read to end")?; info!("accept finished"); Ok(()) } diff --git a/iroh/tests/integration.rs b/iroh/tests/integration.rs index 99121088ebb..6a470f578d9 100644 --- a/iroh/tests/integration.rs +++ b/iroh/tests/integration.rs @@ -17,7 +17,7 @@ use n0_future::{ StreamExt, task, time::{self, Duration}, }; -use n0_snafu::{Result, ResultExt}; +use n0_error::{Result, StackResultExt, StdResultExt}; #[cfg(not(wasm_browser))] use tokio::test; use tracing::{Instrument, info_span}; @@ -78,7 +78,7 @@ async fn simple_endpoint_id_based_connection_transfer() -> Result { tracing::info!("Closed with code: {code:?}"); } - Ok::<_, n0_snafu::Error>(()) + Ok::<_, n0_error::AnyError>(()) } .instrument(info_span!("server")) }); From 894ff10b088f669e0db0935e2064199fdb4a174a Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 23:14:53 +0200 Subject: [PATCH 13/58] codex did it --- Cargo.lock | 55 --------------------- iroh-dns-server/Cargo.toml | 4 +- iroh-dns-server/benches/write.rs | 2 +- iroh-dns-server/examples/convert.rs | 4 +- iroh-dns-server/examples/publish.rs | 4 +- iroh-dns-server/examples/resolve.rs | 4 +- iroh-dns-server/src/config.rs | 12 +++-- iroh-dns-server/src/dns.rs | 2 +- iroh-dns-server/src/dns/node_authority.rs | 7 ++- iroh-dns-server/src/http.rs | 13 +++-- iroh-dns-server/src/http/doh.rs | 2 +- iroh-dns-server/src/http/doh/response.rs | 24 ++++----- iroh-dns-server/src/http/error.rs | 4 +- iroh-dns-server/src/http/tls.rs | 13 +++-- iroh-dns-server/src/lib.rs | 11 +++-- iroh-dns-server/src/main.rs | 2 +- iroh-dns-server/src/server.rs | 2 +- iroh-dns-server/src/store.rs | 2 +- iroh-dns-server/src/store/signed_packets.rs | 33 +++++++------ iroh-dns-server/src/util.rs | 8 +-- iroh/examples/0rtt.rs | 18 +++---- iroh/examples/connect-unreliable.rs | 4 +- iroh/examples/connect.rs | 2 +- iroh/examples/dht_discovery.rs | 10 ++-- iroh/examples/echo-no-router.rs | 2 +- iroh/examples/echo.rs | 2 +- iroh/examples/listen-unreliable.rs | 2 +- iroh/examples/listen.rs | 6 +-- iroh/examples/locally-discovered-nodes.rs | 4 +- iroh/examples/screening-connection.rs | 2 +- iroh/examples/search.rs | 2 +- iroh/examples/transfer.rs | 10 ++-- iroh/src/discovery.rs | 4 +- iroh/src/discovery/static_provider.rs | 6 +-- iroh/src/endpoint.rs | 12 ++--- iroh/src/endpoint/presets.rs | 2 +- iroh/src/lib.rs | 12 ++--- 37 files changed, 126 insertions(+), 182 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7ffe62f3c18..a85f45e577c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,9 +140,6 @@ name = "anyhow" version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" -dependencies = [ - "backtrace", -] [[package]] name = "anymap2" @@ -473,12 +470,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "btparse" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387e80962b798815a2b5c4bcfdb6bf626fa922ffe9f74e373103b858738e9f31" - [[package]] name = "bumpalo" version = "3.19.0" @@ -643,17 +634,6 @@ dependencies = [ "thiserror 2.0.17", ] -[[package]] -name = "color-backtrace" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e49b1973af2a47b5b44f7dd0a344598da95c872e1556b045607888784e973b91" -dependencies = [ - "backtrace", - "btparse", - "termcolor", -] - [[package]] name = "colorchoice" version = "1.0.4" @@ -2390,7 +2370,6 @@ dependencies = [ "lru 0.16.1", "n0-error", "n0-future 0.3.0", - "n0-snafu", "pkarr", "rand 0.9.2", "rand_chacha 0.9.0", @@ -2400,7 +2379,6 @@ dependencies = [ "rustls", "rustls-pemfile", "serde", - "snafu", "struct_iterable", "strum", "tokio", @@ -2910,19 +2888,6 @@ dependencies = [ "web-time", ] -[[package]] -name = "n0-snafu" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1815107e577a95bfccedb4cfabc73d709c0db6d12de3f14e0f284a8c5036dc4f" -dependencies = [ - "anyhow", - "btparse", - "color-backtrace", - "snafu", - "tracing-error", -] - [[package]] name = "n0-watcher" version = "0.3.0" @@ -4541,7 +4506,6 @@ version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e84b3f4eacbf3a1ce05eac6763b4d629d60cbc94d632e4092c54ade71f1e1a2" dependencies = [ - "backtrace", "snafu-derive", ] @@ -4803,15 +4767,6 @@ dependencies = [ "windows-sys 0.61.1", ] -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - [[package]] name = "thiserror" version = "1.0.69" @@ -5228,16 +5183,6 @@ dependencies = [ "valuable", ] -[[package]] -name = "tracing-error" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" -dependencies = [ - "tracing", - "tracing-subscriber", -] - [[package]] name = "tracing-log" version = "0.2.0" diff --git a/iroh-dns-server/Cargo.toml b/iroh-dns-server/Cargo.toml index ffd0d06dc23..5eee90e8a01 100644 --- a/iroh-dns-server/Cargo.toml +++ b/iroh-dns-server/Cargo.toml @@ -31,7 +31,6 @@ humantime-serde = "1.1.1" iroh-metrics = { version = "0.36", features = ["service"] } lru = "0.16" n0-future = "0.3.0" -n0-snafu = "0.2.2" pkarr = { version = "5", features = ["relays", "dht"], default-features = false } rcgen = "0.14" redb = "2.6.3" @@ -40,7 +39,7 @@ rustls = { version = "0.23.33", default-features = false, features = ["ring"] } rustls-pemfile = { version = "2.1" } serde = { version = "1", features = ["derive"] } struct_iterable = "0.1.1" -snafu = { version = "0.8.5", features = ["rust_1_81"] } +n0-error = { git = "https://github.com/n0-computer/n0-error" } strum = { version = "0.27", features = ["derive"] } tokio = { version = "1", features = ["full"] } tokio-rustls = { version = "0.26", default-features = false, features = [ @@ -64,7 +63,6 @@ criterion = "0.7.0" data-encoding = "2.3.3" hickory-resolver = "0.25.0" iroh = { path = "../iroh" } -n0-error = { git = "https://github.com/n0-computer/n0-error" } rand = "0.9.2" rand_chacha = "0.9" tracing-test = "0.2.5" diff --git a/iroh-dns-server/benches/write.rs b/iroh-dns-server/benches/write.rs index 2e66db59578..9373c1bfb95 100644 --- a/iroh-dns-server/benches/write.rs +++ b/iroh-dns-server/benches/write.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main}; use iroh::{SecretKey, discovery::pkarr::PkarrRelayClient, endpoint_info::EndpointInfo}; use iroh_dns_server::{ZoneStore, config::Config, metrics::Metrics, server::Server}; -use n0_snafu::Result; +use n0_error::Result; use rand_chacha::rand_core::SeedableRng; use tokio::runtime::Runtime; diff --git a/iroh-dns-server/examples/convert.rs b/iroh-dns-server/examples/convert.rs index 765c809f16f..ca5a9cb1cd7 100644 --- a/iroh-dns-server/examples/convert.rs +++ b/iroh-dns-server/examples/convert.rs @@ -2,7 +2,7 @@ use std::str::FromStr; use clap::Parser; use iroh::EndpointId; -use n0_snafu::{Result, ResultExt}; +use n0_error::{Result, StdResultExt}; #[derive(Debug, Parser)] struct Cli { @@ -26,7 +26,7 @@ fn main() -> Result<()> { } Command::PkarrToEndpoint { z32_pubkey } => { let public_key = pkarr::PublicKey::try_from(z32_pubkey.as_str()).e()?; - let endpoint_id = EndpointId::from_bytes(public_key.as_bytes()).e()?; + let endpoint_id = EndpointId::from_bytes(public_key.as_bytes())?; println!("{endpoint_id}") } } diff --git a/iroh-dns-server/examples/publish.rs b/iroh-dns-server/examples/publish.rs index a5dc9e4ee6e..99846964753 100644 --- a/iroh-dns-server/examples/publish.rs +++ b/iroh-dns-server/examples/publish.rs @@ -10,7 +10,7 @@ use iroh::{ }, endpoint_info::{EndpointIdExt, EndpointInfo, IROH_TXT_NAME}, }; -use n0_snafu::{Result, ResultExt}; +use n0_error::{Result, StdResultExt}; use url::Url; const DEV_PKARR_RELAY_URL: &str = "http://localhost:8080/pkarr"; @@ -61,7 +61,7 @@ async fn main() -> Result<()> { let secret_key = match std::env::var("IROH_SECRET") { Ok(s) => SecretKey::from_str(&s) - .context("failed to parse IROH_SECRET environment variable as iroh secret key")?, + .std_context("failed to parse IROH_SECRET environment variable as iroh secret key")?, Err(_) => { let s = SecretKey::generate(&mut rand::rng()); println!("Generated a new endpoint secret. To reuse, set"); diff --git a/iroh-dns-server/examples/resolve.rs b/iroh-dns-server/examples/resolve.rs index 4155256a51b..579f0a49a35 100644 --- a/iroh-dns-server/examples/resolve.rs +++ b/iroh-dns-server/examples/resolve.rs @@ -4,7 +4,7 @@ use iroh::{ discovery::dns::{N0_DNS_ENDPOINT_ORIGIN_PROD, N0_DNS_ENDPOINT_ORIGIN_STAGING}, dns::DnsResolver, }; -use n0_snafu::{Result, ResultExt}; +use n0_error::{Result, StdResultExt, format_err}; const DEV_DNS_SERVER: &str = "127.0.0.1:5300"; const DEV_DNS_ORIGIN_DOMAIN: &str = "irohdns.example"; @@ -51,7 +51,7 @@ async fn main() -> Result<()> { .await .e()? .next() - .context("failed to resolve DNS server address")?; + .ok_or_else(|| format_err!("failed to resolve DNS server address"))?; DnsResolver::with_nameserver(addr) } else { match args.env { diff --git a/iroh-dns-server/src/config.rs b/iroh-dns-server/src/config.rs index 867d89e07d5..d554ffec90b 100644 --- a/iroh-dns-server/src/config.rs +++ b/iroh-dns-server/src/config.rs @@ -7,7 +7,7 @@ use std::{ time::Duration, }; -use n0_snafu::{Result, ResultExt}; +use n0_error::{Result, StackResultExt, StdResultExt}; use serde::{Deserialize, Serialize}; use tracing::info; @@ -162,7 +162,10 @@ impl Config { ); let s = tokio::fs::read_to_string(path.as_ref()) .await - .with_context(|| format!("failed to read {}", path.as_ref().to_string_lossy()))?; + .std_context(format!( + "failed to read {}", + path.as_ref().to_string_lossy() + ))?; let config: Config = toml::from_str(&s).e()?; Ok(config) } @@ -172,8 +175,9 @@ impl Config { let dir = if let Some(val) = env::var_os("IROH_DNS_DATA_DIR") { PathBuf::from(val) } else { - let path = dirs_next::data_dir() - .context("operating environment provides no directory for application data")?; + let path = dirs_next::data_dir().std_context( + "operating environment provides no directory for application data", + )?; path.join("iroh-dns") }; diff --git a/iroh-dns-server/src/dns.rs b/iroh-dns-server/src/dns.rs index 38b4ad552e1..03a5dd7d365 100644 --- a/iroh-dns-server/src/dns.rs +++ b/iroh-dns-server/src/dns.rs @@ -25,7 +25,7 @@ use hickory_server::{ server::{Request, RequestHandler, ResponseHandler, ResponseInfo}, store::in_memory::InMemoryAuthority, }; -use n0_snafu::{Result, ResultExt, format_err}; +use n0_error::{Result, StdResultExt, format_err}; use serde::{Deserialize, Serialize}; use tokio::{ net::{TcpListener, UdpSocket}, diff --git a/iroh-dns-server/src/dns/node_authority.rs b/iroh-dns-server/src/dns/node_authority.rs index caba6747191..f5942c92472 100644 --- a/iroh-dns-server/src/dns/node_authority.rs +++ b/iroh-dns-server/src/dns/node_authority.rs @@ -13,8 +13,7 @@ use hickory_server::{ server::RequestInfo, store::in_memory::InMemoryAuthority, }; -use n0_snafu::{Result, ResultExt}; -use snafu::whatever; +use n0_error::{Result, StackResultExt, StdResultExt, whatever}; use tracing::{debug, trace}; use crate::{ @@ -191,8 +190,8 @@ fn parse_name_as_pkarr_with_origin( let mut labels_without_origin = labels.skip(origin.num_labels() as usize); let pkey_label = labels_without_origin.next().expect("length checked above"); let pkey_str = std::str::from_utf8(pkey_label).e()?; - let pkey = - PublicKeyBytes::from_z32(pkey_str).context("not a valid pkarr name: invalid pubkey")?; + let pkey = PublicKeyBytes::from_z32(pkey_str) + .std_context("not a valid pkarr name: invalid pubkey")?; let remaining_name = Name::from_labels(labels_without_origin.rev()).e()?; return Ok((remaining_name, pkey, origin.clone())); } diff --git a/iroh-dns-server/src/http.rs b/iroh-dns-server/src/http.rs index a3bdaed3696..cbd630a80b2 100644 --- a/iroh-dns-server/src/http.rs +++ b/iroh-dns-server/src/http.rs @@ -14,9 +14,8 @@ use axum::{ response::IntoResponse, routing::get, }; -use n0_snafu::{Result, ResultExt}; +use n0_error::{Result, StackResultExt, StdResultExt, whatever}; use serde::{Deserialize, Serialize}; -use snafu::whatever; use tokio::{net::TcpListener, task::JoinSet}; use tower_http::{ cors::{self, CorsLayer}, @@ -112,9 +111,9 @@ impl HttpServer { .join(config.cert_mode.to_string()); tokio::fs::create_dir_all(&cache_path) .await - .with_context(|| { - format!("failed to create cert cache dir at {cache_path:?}") - })?; + .std_context(format!( + "failed to create cert cache dir at {cache_path:?}" + ))?; config .cert_mode .build( @@ -173,11 +172,11 @@ impl HttpServer { Err(err) if err.is_cancelled() => {} Ok(Err(err)) => { warn!(?err, "task failed"); - final_res = Err(err).context("task"); + final_res = Err(err).std_context("task"); } Err(err) => { warn!(?err, "task panicked"); - final_res = Err(err).context("join"); + final_res = Err(err).std_context("join"); } } } diff --git a/iroh-dns-server/src/http/doh.rs b/iroh-dns-server/src/http/doh.rs index 570338843c3..30e013648bf 100644 --- a/iroh-dns-server/src/http/doh.rs +++ b/iroh-dns-server/src/http/doh.rs @@ -16,7 +16,7 @@ use http::{ HeaderValue, StatusCode, header::{CACHE_CONTROL, CONTENT_TYPE}, }; -use n0_snafu::ResultExt; +use n0_error::StdResultExt; use super::error::AppResult; use crate::state::AppState; diff --git a/iroh-dns-server/src/http/doh/response.rs b/iroh-dns-server/src/http/doh/response.rs index 2f706646418..ccd4624a729 100644 --- a/iroh-dns-server/src/http/doh/response.rs +++ b/iroh-dns-server/src/http/doh/response.rs @@ -4,9 +4,8 @@ // https://github.com/fission-codes/fission-server/blob/394de877fad021260c69fdb1edd7bb4b2f98108c/fission-core/src/dns.rs use hickory_server::proto; -use n0_snafu::Result; +use n0_error::{Result, whatever}; use serde::{Deserialize, Serialize}; -use snafu::ensure_whatever; #[derive(Debug, Serialize, Deserialize)] /// JSON representation of a DNS response @@ -48,20 +47,17 @@ pub struct DnsResponse { impl DnsResponse { /// Create a new JSON response from a DNS message pub fn from_message(message: proto::op::Message) -> Result { - ensure_whatever!( - message.message_type() == proto::op::MessageType::Response, - "Expected message type to be response" - ); + if message.message_type() != proto::op::MessageType::Response { + whatever!("Expected message type to be response"); + } - ensure_whatever!( - message.query_count() == message.queries().len() as u16, - "Query count mismatch" - ); + if message.query_count() != message.queries().len() as u16 { + whatever!("Query count mismatch"); + } - ensure_whatever!( - message.answer_count() == message.answers().len() as u16, - "Answer count mismatch" - ); + if message.answer_count() != message.answers().len() as u16 { + whatever!("Answer count mismatch"); + } let status: u32 = >::from(message.response_code()) as u32; diff --git a/iroh-dns-server/src/http/error.rs b/iroh-dns-server/src/http/error.rs index b3516e5043e..f964234c0c3 100644 --- a/iroh-dns-server/src/http/error.rs +++ b/iroh-dns-server/src/http/error.rs @@ -49,8 +49,8 @@ impl IntoResponse for AppError { } } -impl From for AppError { - fn from(value: n0_snafu::Error) -> Self { +impl From for AppError { + fn from(value: n0_error::AnyError) -> Self { Self { status: StatusCode::INTERNAL_SERVER_ERROR, detail: Some(value.to_string()), diff --git a/iroh-dns-server/src/http/tls.rs b/iroh-dns-server/src/http/tls.rs index fa43515d1dd..403da142ea2 100644 --- a/iroh-dns-server/src/http/tls.rs +++ b/iroh-dns-server/src/http/tls.rs @@ -10,9 +10,8 @@ use axum_server::{ tls_rustls::{RustlsAcceptor, RustlsConfig}, }; use n0_future::{FutureExt, future::Boxed as BoxFuture}; -use n0_snafu::{Result, ResultExt}; +use n0_error::{Result, StdResultExt, whatever}; use serde::{Deserialize, Serialize}; -use snafu::whatever; use tokio::io::{AsyncRead, AsyncWrite}; use tokio_rustls_acme::{AcmeConfig, axum::AxumAcceptor, caches::DirCache}; use tokio_stream::StreamExt; @@ -43,8 +42,8 @@ impl CertMode { CertMode::Manual => TlsAcceptor::manual(domains, cert_cache).await?, CertMode::SelfSigned => TlsAcceptor::self_signed(domains).await?, CertMode::LetsEncrypt => { - let contact = - letsencrypt_contact.context("contact is required for letsencrypt cert mode")?; + let contact = letsencrypt_contact + .std_context("contact is required for letsencrypt cert mode")?; TlsAcceptor::letsencrypt(domains, &contact, letsencrypt_prod, cert_cache)? } }) @@ -141,7 +140,7 @@ async fn load_certs( ) -> Result>> { let certfile = tokio::fs::read(filename) .await - .context("cannot open certificate file")?; + .std_context("cannot open certificate file")?; let mut reader = std::io::Cursor::new(certfile); let certs: Result, std::io::Error> = rustls_pemfile::certs(&mut reader).collect(); let certs = certs.e()?; @@ -154,11 +153,11 @@ async fn load_secret_key( ) -> Result> { let keyfile = tokio::fs::read(filename.as_ref()) .await - .context("cannot open secret key file")?; + .std_context("cannot open secret key file")?; let mut reader = std::io::Cursor::new(keyfile); loop { - match rustls_pemfile::read_one(&mut reader).context("cannot parse secret key .pem file")? { + match rustls_pemfile::read_one(&mut reader).std_context("cannot parse secret key .pem file")? { Some(rustls_pemfile::Item::Pkcs1Key(key)) => { return Ok(rustls::pki_types::PrivateKeyDer::Pkcs1(key)); } diff --git a/iroh-dns-server/src/lib.rs b/iroh-dns-server/src/lib.rs index 1a0e16e551a..f17050d7cfc 100644 --- a/iroh-dns-server/src/lib.rs +++ b/iroh-dns-server/src/lib.rs @@ -25,7 +25,7 @@ mod tests { RelayUrl, SecretKey, discovery::pkarr::PkarrRelayClient, dns::DnsResolver, endpoint_info::EndpointInfo, }; - use n0_snafu::{Result, ResultExt}; + use n0_error::{Result, StdResultExt}; use pkarr::{SignedPacket, Timestamp}; use rand::{CryptoRng, SeedableRng}; use tracing_test::traced_test; @@ -117,7 +117,7 @@ mod tests { // resolve root record let name = Name::from_utf8(format!("{pubkey}.")).e()?; - let res = resolver.lookup_txt(name, DNS_TIMEOUT).await.e()?; + let res = resolver.lookup_txt(name, DNS_TIMEOUT).await?; let records = res.into_iter().map(|t| t.to_string()).collect::>(); assert_eq!(records, vec!["hi0".to_string()]); @@ -158,7 +158,7 @@ mod tests { #[tokio::test] #[traced_test] async fn integration_smoke() -> Result { - let (server, nameserver, http_url) = Server::spawn_for_tests().await?; + let (server, nameserver, http_url) = Server::spawn_for_tests().await.e()?; let pkarr_relay = { let mut url = http_url.clone(); @@ -256,7 +256,10 @@ mod tests { // resolve via DNS from our server, which will lookup from our DHT let resolver = test_resolver(nameserver); - let res = resolver.lookup_endpoint_by_id(&endpoint_id, origin).await.e()?; + let res = resolver + .lookup_endpoint_by_id(&endpoint_id, origin) + .await + .e()?; assert_eq!(res.endpoint_id, endpoint_id); assert_eq!(res.relay_url(), Some(&relay_url)); diff --git a/iroh-dns-server/src/main.rs b/iroh-dns-server/src/main.rs index 83dfc514eec..7a7276ec202 100644 --- a/iroh-dns-server/src/main.rs +++ b/iroh-dns-server/src/main.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; use clap::Parser; use iroh_dns_server::{config::Config, server::run_with_config_until_ctrl_c}; -use n0_snafu::Result; +use n0_error::Result; use tracing::debug; #[derive(Parser, Debug)] diff --git a/iroh-dns-server/src/server.rs b/iroh-dns-server/src/server.rs index dcd7918a95f..d8ab32822ec 100644 --- a/iroh-dns-server/src/server.rs +++ b/iroh-dns-server/src/server.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use iroh_metrics::service::start_metrics_server; -use n0_snafu::{Result, ResultExt}; +use n0_error::{Result, StdResultExt, StackResultExt}; use tracing::info; use crate::{ diff --git a/iroh-dns-server/src/store.rs b/iroh-dns-server/src/store.rs index 0456183043b..08d492fdef4 100644 --- a/iroh-dns-server/src/store.rs +++ b/iroh-dns-server/src/store.rs @@ -4,7 +4,7 @@ use std::{collections::BTreeMap, num::NonZeroUsize, path::Path, sync::Arc, time: use hickory_server::proto::rr::{Name, RecordSet, RecordType, RrKey}; use lru::LruCache; -use n0_snafu::Result; +use n0_error::Result; use pkarr::{Client as PkarrClient, SignedPacket}; use tokio::sync::Mutex; use tracing::{debug, trace, warn}; diff --git a/iroh-dns-server/src/store/signed_packets.rs b/iroh-dns-server/src/store/signed_packets.rs index b686f91a2cc..9e7c1880814 100644 --- a/iroh-dns-server/src/store/signed_packets.rs +++ b/iroh-dns-server/src/store/signed_packets.rs @@ -6,7 +6,7 @@ use std::{ time::{Duration, SystemTime}, }; -use n0_snafu::{Result, ResultExt, format_err}; +use n0_error::{Result, StdResultExt, StackResultExt, format_err}; use pkarr::{SignedPacket, Timestamp}; use redb::{ Database, MultimapTableDefinition, ReadableTable, TableDefinition, backends::InMemoryBackend, @@ -144,10 +144,10 @@ impl Actor { }, Err(err) => { warn!("get {key} failed: {err:#}"); - return Err(err).with_context(|| format!("get packet for {key} failed")) - } - } - } + return Err(err).std_context(format!("get packet for {key} failed")) + } + } + } Message::Upsert { packet, res } => { let key = PublicKeyBytes::from_signed_packet(&packet); trace!("upsert {}", key); @@ -265,16 +265,14 @@ impl SignedPacketStore { let path = path.as_ref(); info!("loading packet database from {}", path.to_string_lossy()); if let Some(parent) = path.parent() { - std::fs::create_dir_all(parent).with_context(|| { - format!( - "failed to create database directory at {}", - path.to_string_lossy() - ) - })?; + std::fs::create_dir_all(parent).std_context(format!( + "failed to create database directory at {}", + path.to_string_lossy() + ))?; } let mut db = Database::builder() .create(path) - .context("failed to open packet database")?; + .std_context("failed to open packet database")?; match db.upgrade() { Ok(true) => info!("Database was upgraded to redb v3 compatible format"), Ok(false) => {} @@ -354,7 +352,10 @@ fn get_packet( table: &impl ReadableTable<&'static SignedPacketsKey, &'static [u8]>, key: &PublicKeyBytes, ) -> Result> { - let Some(row) = table.get(key.as_ref()).context("database fetch failed")? else { + let Some(row) = table + .get(key.as_ref()) + .std_context("database fetch failed")? + else { return Ok(None); }; match SignedPacket::deserialize(row.value()) { @@ -399,7 +400,7 @@ async fn evict_task_inner(send: mpsc::Sender, options: Options) -> Resu let (tx, rx) = oneshot::channel(); let _ = send.send(Message::Snapshot { res: tx }).await.ok(); // if we can't get the snapshot we exit the loop, main actor dead - let snapshot = rx.await.context("failed to get snapshot")?; + let snapshot = rx.await.std_context("failed to get snapshot")?; let expired = Timestamp::now() - expiry_us; trace!("evicting packets older than {}", fmt_time(expired)); @@ -458,11 +459,11 @@ impl IoThread { F: FnOnce() -> Fut + Send + 'static, Fut: Future, { - let rt = tokio::runtime::Handle::try_current().context("get tokio handle")?; + let rt = tokio::runtime::Handle::try_current().std_context("get tokio handle")?; let handle = std::thread::Builder::new() .name(name.into()) .spawn(move || rt.block_on(f())) - .context("failed to spawn thread")?; + .std_context("failed to spawn thread")?; Ok(Self { handle: Some(handle), }) diff --git a/iroh-dns-server/src/util.rs b/iroh-dns-server/src/util.rs index 046f8434582..119171bea2b 100644 --- a/iroh-dns-server/src/util.rs +++ b/iroh-dns-server/src/util.rs @@ -13,7 +13,7 @@ use hickory_server::proto::{ }, serialize::binary::BinDecodable, }; -use n0_snafu::{Error, Result, ResultExt}; +use n0_error::{AnyError, Result, StdResultExt}; use pkarr::SignedPacket; #[derive( @@ -28,7 +28,7 @@ impl PublicKeyBytes { pub fn from_z32(s: &str) -> Result { let bytes = z32::decode(s.as_bytes()).e()?; - let bytes = TryInto::<[u8; 32]>::try_into(&bytes[..]).context("invalid length")?; + let bytes = TryInto::<[u8; 32]>::try_into(&bytes[..]).std_context("invalid length")?; Ok(Self(bytes)) } @@ -68,14 +68,14 @@ impl From for PublicKeyBytes { } impl TryFrom for pkarr::PublicKey { - type Error = Error; + type Error = AnyError; fn try_from(value: PublicKeyBytes) -> Result { pkarr::PublicKey::try_from(&value.0).e() } } impl FromStr for PublicKeyBytes { - type Err = Error; + type Err = AnyError; fn from_str(s: &str) -> Result { Self::from_z32(s) } diff --git a/iroh/examples/0rtt.rs b/iroh/examples/0rtt.rs index 56b71d2af23..77f5cc14ff0 100644 --- a/iroh/examples/0rtt.rs +++ b/iroh/examples/0rtt.rs @@ -7,8 +7,8 @@ use iroh::{ endpoint::{Connecting, Connection}, }; use iroh_base::ticket::EndpointTicket; +use n0_error::{Result, StdResultExt, StackResultExt, whatever}; use n0_future::{StreamExt, future}; -use n0_snafu::ResultExt; use n0_watcher::Watcher; use tracing::{info, trace}; @@ -28,7 +28,7 @@ struct Args { /// Gets a secret key from the IROH_SECRET environment variable or generates a new random one. /// If the environment variable is set, it must be a valid string representation of a secret key. -pub fn get_or_generate_secret_key() -> n0_snafu::Result { +pub fn get_or_generate_secret_key() -> Result { if let Ok(secret) = env::var("IROH_SECRET") { // Parse the secret key from string SecretKey::from_str(&secret).context("Invalid secret key format") @@ -53,7 +53,7 @@ async fn pingpong( connection: &Connection, proceed: impl Future, x: u64, -) -> n0_snafu::Result<()> { +) -> Result<()> { let (mut send, recv) = connection.open_bi().await.e()?; let data = x.to_be_bytes(); send.write_all(&data).await.e()?; @@ -74,7 +74,7 @@ async fn pingpong( Ok(()) } -async fn pingpong_0rtt(connecting: Connecting, i: u64) -> n0_snafu::Result { +async fn pingpong_0rtt(connecting: Connecting, i: u64) -> Result { let connection = match connecting.into_0rtt() { Ok((connection, accepted)) => { trace!("0-RTT possible from our side"); @@ -91,7 +91,7 @@ async fn pingpong_0rtt(connecting: Connecting, i: u64) -> n0_snafu::Result n0_snafu::Result<()> { +async fn connect(args: Args) -> Result<()> { let endpoint_addr = args.endpoint.unwrap().endpoint_addr().clone(); let endpoint = iroh::Endpoint::builder() .relay_mode(iroh::RelayMode::Disabled) @@ -131,7 +131,7 @@ async fn connect(args: Args) -> n0_snafu::Result<()> { Ok(()) } -async fn accept(_args: Args) -> n0_snafu::Result<()> { +async fn accept(_args: Args) -> Result<()> { let secret_key = get_or_generate_secret_key()?; let endpoint = iroh::Endpoint::builder() .alpns(vec![PINGPONG_ALPN.to_vec()]) @@ -142,7 +142,7 @@ async fn accept(_args: Args) -> n0_snafu::Result<()> { let mut addrs = endpoint.watch_addr().stream(); let addr = loop { let Some(addr) = addrs.next().await else { - snafu::whatever!("Address stream closed"); + whatever!("Address stream closed"); }; if !addr.direct_addresses.is_empty() { break addr; @@ -166,7 +166,7 @@ async fn accept(_args: Args) -> n0_snafu::Result<()> { send.write_all(&data).await.e()?; send.finish().e()?; connection.closed().await; - Ok::<_, n0_snafu::Error>(()) + Ok::<_, n0_error::Error>(()) }); } }; @@ -182,7 +182,7 @@ async fn accept(_args: Args) -> n0_snafu::Result<()> { } #[tokio::main] -async fn main() -> n0_snafu::Result<()> { +async fn main() -> Result<()> { tracing_subscriber::fmt::init(); let args = Args::parse(); if args.endpoint.is_some() { diff --git a/iroh/examples/connect-unreliable.rs b/iroh/examples/connect-unreliable.rs index e4b30accf21..4ea30b2de66 100644 --- a/iroh/examples/connect-unreliable.rs +++ b/iroh/examples/connect-unreliable.rs @@ -9,7 +9,7 @@ use std::net::SocketAddr; use clap::Parser; use iroh::{Endpoint, EndpointAddr, RelayMode, RelayUrl, SecretKey}; -use n0_snafu::ResultExt; +use n0_error::{Result, StdResultExt}; use tracing::info; // An example ALPN that we are using to communicate over the `Endpoint` @@ -29,7 +29,7 @@ struct Cli { } #[tokio::main] -async fn main() -> n0_snafu::Result<()> { +async fn main() -> Result<()> { tracing_subscriber::fmt::init(); println!("\nconnect (unreliable) example!\n"); let args = Cli::parse(); diff --git a/iroh/examples/connect.rs b/iroh/examples/connect.rs index 960d9edd923..d68b432cc28 100644 --- a/iroh/examples/connect.rs +++ b/iroh/examples/connect.rs @@ -9,7 +9,7 @@ use std::net::SocketAddr; use clap::Parser; use iroh::{Endpoint, EndpointAddr, RelayMode, RelayUrl, SecretKey}; -use n0_snafu::{Result, ResultExt}; +use n0_error::{Result, StdResultExt}; use tracing::info; // An example ALPN that we are using to communicate over the `Endpoint` diff --git a/iroh/examples/dht_discovery.rs b/iroh/examples/dht_discovery.rs index 8dfc1969b20..33ca5a7302a 100644 --- a/iroh/examples/dht_discovery.rs +++ b/iroh/examples/dht_discovery.rs @@ -12,7 +12,7 @@ use std::str::FromStr; use clap::Parser; use iroh::{Endpoint, EndpointId}; -use n0_snafu::ResultExt; +use n0_error::{Result, StdResultExt}; use tracing::warn; use url::Url; @@ -61,7 +61,7 @@ fn build_discovery(args: Args) -> iroh::discovery::pkarr::dht::Builder { } } -async fn chat_server(args: Args) -> n0_snafu::Result<()> { +async fn chat_server(args: Args) -> Result<()> { let secret_key = iroh::SecretKey::generate(&mut rand::rng()); let endpoint_id = secret_key.public(); let discovery = build_discovery(args); @@ -100,13 +100,13 @@ async fn chat_server(args: Args) -> n0_snafu::Result<()> { tokio::spawn( async move { tokio::io::copy(&mut tokio::io::stdin(), &mut writer).await }, ); - Ok::<_, n0_snafu::Error>(()) + Ok::<_, n0_error::Error>(()) }); } Ok(()) } -async fn chat_client(args: Args) -> n0_snafu::Result<()> { +async fn chat_client(args: Args) -> Result<()> { let remote_endpoint_id = args.endpoint_id.unwrap(); let secret_key = iroh::SecretKey::generate(&mut rand::rng()); let endpoint_id = secret_key.public(); @@ -132,7 +132,7 @@ async fn chat_client(args: Args) -> n0_snafu::Result<()> { } #[tokio::main] -async fn main() -> n0_snafu::Result<()> { +async fn main() -> Result<()> { tracing_subscriber::fmt::init(); let args = Args::parse(); if args.endpoint_id.is_some() { diff --git a/iroh/examples/echo-no-router.rs b/iroh/examples/echo-no-router.rs index 770ddce3f32..6784383e2bb 100644 --- a/iroh/examples/echo-no-router.rs +++ b/iroh/examples/echo-no-router.rs @@ -8,7 +8,7 @@ //! cargo run --example echo-no-router --features=examples use iroh::{Endpoint, EndpointAddr}; -use n0_snafu::{Error, Result, ResultExt}; +use n0_error::{AnyError as Error, Result, StdResultExt}; /// Each protocol is identified by its ALPN string. /// diff --git a/iroh/examples/echo.rs b/iroh/examples/echo.rs index a378b6469a9..d8914ee15c4 100644 --- a/iroh/examples/echo.rs +++ b/iroh/examples/echo.rs @@ -11,7 +11,7 @@ use iroh::{ endpoint::Connection, protocol::{AcceptError, ProtocolHandler, Router}, }; -use n0_snafu::{Result, ResultExt}; +use n0_error::{Result, StdResultExt}; /// Each protocol is identified by its ALPN string. /// diff --git a/iroh/examples/listen-unreliable.rs b/iroh/examples/listen-unreliable.rs index 60274480dc3..14ff000ace2 100644 --- a/iroh/examples/listen-unreliable.rs +++ b/iroh/examples/listen-unreliable.rs @@ -4,7 +4,7 @@ //! run this example from the project root: //! $ cargo run --example listen-unreliable use iroh::{Endpoint, RelayMode, SecretKey}; -use n0_snafu::{Error, Result, ResultExt}; +use n0_error::{AnyError as Error, Result, StdResultExt}; use tracing::{info, warn}; // An example ALPN that we are using to communicate over the `Endpoint` diff --git a/iroh/examples/listen.rs b/iroh/examples/listen.rs index af9ed0e75e4..eac4e0b95c6 100644 --- a/iroh/examples/listen.rs +++ b/iroh/examples/listen.rs @@ -6,14 +6,14 @@ use std::time::Duration; use iroh::{Endpoint, RelayMode, SecretKey, endpoint::ConnectionError}; -use n0_snafu::ResultExt; +use n0_error::{Result, StdResultExt}; use tracing::{debug, info, warn}; // An example ALPN that we are using to communicate over the `Endpoint` const EXAMPLE_ALPN: &[u8] = b"n0/iroh/examples/magic/0"; #[tokio::main] -async fn main() -> n0_snafu::Result<()> { +async fn main() -> Result<()> { tracing_subscriber::fmt::init(); println!("\nlisten example!\n"); let secret_key = SecretKey::generate(&mut rand::rng()); @@ -105,7 +105,7 @@ async fn main() -> n0_snafu::Result<()> { if res.is_err() { println!("endpoint {endpoint_id} did not disconnect within 3 seconds"); } - Ok::<_, n0_snafu::Error>(()) + Ok::<_, n0_error::Error>(()) }); } // stop with SIGINT (ctrl-c) diff --git a/iroh/examples/locally-discovered-nodes.rs b/iroh/examples/locally-discovered-nodes.rs index 08e6226d94b..0a972d228c1 100644 --- a/iroh/examples/locally-discovered-nodes.rs +++ b/iroh/examples/locally-discovered-nodes.rs @@ -11,7 +11,7 @@ use iroh::{ endpoint_info::UserData, }; use n0_future::StreamExt; -use n0_snafu::Result; +use n0_error::Result; use tokio::task::JoinSet; #[tokio::main] @@ -73,7 +73,7 @@ async fn main() -> Result<()> { ep.set_user_data_for_discovery(Some(ud)); tokio::time::sleep(Duration::from_secs(3)).await; ep.close().await; - Ok::<_, n0_snafu::Error>(()) + Ok::<_, n0_error::Error>(()) }); } diff --git a/iroh/examples/screening-connection.rs b/iroh/examples/screening-connection.rs index d556649b16c..632dab56347 100644 --- a/iroh/examples/screening-connection.rs +++ b/iroh/examples/screening-connection.rs @@ -17,7 +17,7 @@ use iroh::{ endpoint::{Connecting, Connection}, protocol::{AcceptError, ProtocolHandler, Router}, }; -use n0_snafu::{Result, ResultExt}; +use n0_error::{Result, StdResultExt}; /// Each protocol is identified by its ALPN string. /// diff --git a/iroh/examples/search.rs b/iroh/examples/search.rs index e7c2df5aa2a..7e3edc75514 100644 --- a/iroh/examples/search.rs +++ b/iroh/examples/search.rs @@ -37,7 +37,7 @@ use iroh::{ endpoint::Connection, protocol::{AcceptError, ProtocolHandler, Router}, }; -use n0_snafu::{Result, ResultExt}; +use n0_error::{Result, StdResultExt}; use tokio::sync::Mutex; use tracing_subscriber::{EnvFilter, prelude::*}; diff --git a/iroh/examples/transfer.rs b/iroh/examples/transfer.rs index c26d4c0d7fe..8b3e4489500 100644 --- a/iroh/examples/transfer.rs +++ b/iroh/examples/transfer.rs @@ -18,7 +18,7 @@ use iroh::{ }; use iroh_base::ticket::EndpointTicket; use n0_future::task::AbortOnDropHandle; -use n0_snafu::{Result, ResultExt}; +use n0_error::{Result, StdResultExt, StackResultExt, whatever}; use n0_watcher::Watcher as _; use tokio_stream::StreamExt; use tracing::{info, warn}; @@ -201,7 +201,7 @@ impl EndpointArgs { } #[cfg(not(feature = "test-utils"))] { - snafu::whatever!( + whatever!( "Must have the `test-utils` feature enabled when using the `--env=dev` flag" ) } @@ -237,7 +237,7 @@ impl EndpointArgs { } #[cfg(not(feature = "test-utils"))] { - snafu::whatever!( + whatever!( "Must have the `discovery-local-network` enabled when using the `--mdns` flag" ); } @@ -268,7 +268,7 @@ impl EndpointArgs { } #[cfg(not(feature = "discovery-local-network"))] { - snafu::whatever!( + whatever!( "Must have the `test-utils` feature enabled when using the `--relay-only` flag" ); } @@ -379,7 +379,7 @@ async fn provide(endpoint: Endpoint, size: u64) -> Result<()> { } else { println!("[{remote}] Disconnected"); } - Ok::<_, n0_snafu::Error>(()) + Ok::<_, n0_error::Error>(()) }); } diff --git a/iroh/src/discovery.rs b/iroh/src/discovery.rs index b5f7b8677e8..f0c5b07a852 100644 --- a/iroh/src/discovery.rs +++ b/iroh/src/discovery.rs @@ -65,7 +65,7 @@ //! endpoint::RelayMode, //! }; //! -//! # async fn wrapper() -> n0_snafu::Result<()> { +//! # async fn wrapper() -> n0_error::Result<()> { //! let ep = Endpoint::empty_builder(RelayMode::Default) //! .discovery(PkarrPublisher::n0_dns()) //! .discovery(DnsDiscovery::n0_dns()) @@ -86,7 +86,7 @@ //! # Endpoint, SecretKey, //! # }; //! # -//! # async fn wrapper() -> n0_snafu::Result<()> { +//! # async fn wrapper() -> n0_error::Result<()> { //! let ep = Endpoint::empty_builder(RelayMode::Default) //! .discovery(PkarrPublisher::n0_dns()) //! .discovery(DnsDiscovery::n0_dns()) diff --git a/iroh/src/discovery/static_provider.rs b/iroh/src/discovery/static_provider.rs index 3ee8ec78a7f..0a09a460eeb 100644 --- a/iroh/src/discovery/static_provider.rs +++ b/iroh/src/discovery/static_provider.rs @@ -41,7 +41,7 @@ use super::{Discovery, DiscoveryError, DiscoveryItem, EndpointData, EndpointInfo /// use iroh_base::SecretKey; /// /// # #[tokio::main] -/// # async fn main() -> n0_snafu::Result<()> { +/// # async fn main() -> n0_error::Result<()> { /// // Create the discovery service and endpoint. /// let discovery = StaticProvider::new(); /// @@ -125,8 +125,8 @@ impl StaticProvider { /// # fn get_addrs() -> Vec { /// # Vec::new() /// # } - /// # #[tokio::main] - /// # async fn main() -> n0_snafu::Result<()> { +/// # #[tokio::main] +/// # async fn main() -> n0_error::Result<()> { /// // get addrs from somewhere /// let addrs = get_addrs(); /// diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 56da2dd34e6..5455180a5b4 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -827,7 +827,7 @@ impl Endpoint { /// The observed [`EndpointAddr`] will have the current [`RelayUrl`] and direct addresses. /// /// ```no_run - /// # async fn wrapper() -> n0_snafu::Result { + /// # async fn wrapper() -> n0_error::Result<()> { /// use iroh::{Endpoint, Watcher}; /// /// let endpoint = Endpoint::builder() @@ -1022,7 +1022,7 @@ impl Endpoint { /// ```rust /// # use std::collections::BTreeMap; /// # use iroh::endpoint::Endpoint; - /// # async fn wrapper() -> n0_snafu::Result { + /// # async fn wrapper() -> n0_error::Result<()> { /// let endpoint = Endpoint::bind().await?; /// assert_eq!(endpoint.metrics().magicsock.recv_datagrams.get(), 0); /// # Ok(()) @@ -1040,7 +1040,7 @@ impl Endpoint { /// # use std::collections::BTreeMap; /// # use iroh_metrics::{Metric, MetricsGroup, MetricValue, MetricsGroupSet}; /// # use iroh::endpoint::Endpoint; - /// # async fn wrapper() -> n0_snafu::Result { + /// # async fn wrapper() -> n0_error::Result<()> { /// let endpoint = Endpoint::bind().await?; /// let metrics: BTreeMap = endpoint /// .metrics() @@ -1063,7 +1063,7 @@ impl Endpoint { /// ```rust /// # use iroh_metrics::{Registry, MetricsSource}; /// # use iroh::endpoint::Endpoint; - /// # async fn wrapper() -> n0_snafu::Result { + /// # async fn wrapper() -> n0_error::Result<()> { /// let endpoint = Endpoint::bind().await?; /// let mut registry = Registry::default(); /// registry.register_all(endpoint.metrics()); @@ -1086,8 +1086,8 @@ impl Endpoint { /// # use std::{sync::{Arc, RwLock}, time::Duration}; /// # use iroh_metrics::{Registry, MetricsSource}; /// # use iroh::endpoint::Endpoint; - /// # use n0_snafu::ResultExt; - /// # async fn wrapper() -> n0_snafu::Result { + /// # use n0_error::StackResultExt; + /// # async fn wrapper() -> n0_error::Result<()> { /// // Create a registry, wrapped in a read-write lock so that we can register and serve /// // the metrics independently. /// let registry = Arc::new(RwLock::new(Registry::default())); diff --git a/iroh/src/endpoint/presets.rs b/iroh/src/endpoint/presets.rs index 412af114947..6952eb4b0f8 100644 --- a/iroh/src/endpoint/presets.rs +++ b/iroh/src/endpoint/presets.rs @@ -3,7 +3,7 @@ //! # Example //! //! ```no_run -//! # async fn wrapper() -> n0_snafu::Result { +//! # async fn wrapper() -> n0_error::Result<()> { //! use iroh::{Endpoint, RelayMode, Watcher, endpoint::presets}; //! //! let endpoint = Endpoint::empty_builder(RelayMode::Disabled) diff --git a/iroh/src/lib.rs b/iroh/src/lib.rs index e171e695bd9..cb44baed13d 100644 --- a/iroh/src/lib.rs +++ b/iroh/src/lib.rs @@ -9,8 +9,8 @@ //! //! ```no_run //! # use iroh::{Endpoint, EndpointAddr}; -//! # use n0_snafu::ResultExt; -//! # async fn wrapper() -> n0_snafu::Result { +//! # use n0_error::StackResultExt; +//! # async fn wrapper() -> n0_error::Result<()> { //! let addr: EndpointAddr = todo!(); //! let ep = Endpoint::bind().await?; //! let conn = ep.connect(addr, b"my-alpn").await?; @@ -27,8 +27,8 @@ //! //! ```no_run //! # use iroh::{Endpoint, EndpointAddr}; -//! # use n0_snafu::ResultExt; -//! # async fn wrapper() -> n0_snafu::Result { +//! # use n0_error::StackResultExt; +//! # async fn wrapper() -> n0_error::Result<()> { //! let ep = Endpoint::builder() //! .alpns(vec![b"my-alpn".to_vec()]) //! .bind() @@ -171,7 +171,7 @@ //! //! ```no_run //! use iroh::{Endpoint, EndpointAddr}; -//! use n0_snafu::{Result, ResultExt}; +//! use n0_error::{Result, StackResultExt}; //! //! async fn connect(addr: EndpointAddr) -> Result<()> { //! // The Endpoint is the central object that manages an iroh node. @@ -197,7 +197,7 @@ //! ```no_run //! use iroh::{Endpoint, EndpointAddr}; //! use n0_future::StreamExt; -//! use n0_snafu::{Result, ResultExt}; +//! use n0_error::{Result, StackResultExt}; //! //! async fn accept() -> Result<()> { //! // To accept connections at least one ALPN must be configured. From 47064a3154e2dc66121315d39ba881d60839e6ff Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 23:16:31 +0200 Subject: [PATCH 14/58] fix & fmt --- iroh-dns-server/src/config.rs | 5 +- iroh-dns-server/src/dns/node_authority.rs | 2 +- iroh-dns-server/src/http.rs | 4 +- iroh-dns-server/src/http/tls.rs | 6 +- iroh-dns-server/src/server.rs | 2 +- iroh-dns-server/src/store/signed_packets.rs | 152 ++++++++++---------- iroh/bench/src/iroh.rs | 2 +- iroh/examples/0rtt.rs | 2 +- iroh/examples/locally-discovered-nodes.rs | 2 +- iroh/examples/transfer.rs | 2 +- iroh/src/discovery.rs | 8 +- iroh/src/discovery/mdns.rs | 3 +- iroh/src/discovery/pkarr.rs | 43 ++++-- iroh/src/discovery/static_provider.rs | 4 +- iroh/src/endpoint.rs | 17 +-- iroh/src/lib.rs | 2 +- iroh/src/magicsock.rs | 37 +++-- iroh/src/net_report/ip_mapped_addrs.rs | 2 +- iroh/src/tls/resolver.rs | 2 +- iroh/tests/integration.rs | 2 +- 20 files changed, 171 insertions(+), 128 deletions(-) diff --git a/iroh-dns-server/src/config.rs b/iroh-dns-server/src/config.rs index d554ffec90b..bf15f9a693e 100644 --- a/iroh-dns-server/src/config.rs +++ b/iroh-dns-server/src/config.rs @@ -175,9 +175,8 @@ impl Config { let dir = if let Some(val) = env::var_os("IROH_DNS_DATA_DIR") { PathBuf::from(val) } else { - let path = dirs_next::data_dir().std_context( - "operating environment provides no directory for application data", - )?; + let path = dirs_next::data_dir() + .std_context("operating environment provides no directory for application data")?; path.join("iroh-dns") }; diff --git a/iroh-dns-server/src/dns/node_authority.rs b/iroh-dns-server/src/dns/node_authority.rs index f5942c92472..9f948a09e62 100644 --- a/iroh-dns-server/src/dns/node_authority.rs +++ b/iroh-dns-server/src/dns/node_authority.rs @@ -13,7 +13,7 @@ use hickory_server::{ server::RequestInfo, store::in_memory::InMemoryAuthority, }; -use n0_error::{Result, StackResultExt, StdResultExt, whatever}; +use n0_error::{Result, StdResultExt, whatever}; use tracing::{debug, trace}; use crate::{ diff --git a/iroh-dns-server/src/http.rs b/iroh-dns-server/src/http.rs index cbd630a80b2..c415355ca18 100644 --- a/iroh-dns-server/src/http.rs +++ b/iroh-dns-server/src/http.rs @@ -111,9 +111,7 @@ impl HttpServer { .join(config.cert_mode.to_string()); tokio::fs::create_dir_all(&cache_path) .await - .std_context(format!( - "failed to create cert cache dir at {cache_path:?}" - ))?; + .std_context(format!("failed to create cert cache dir at {cache_path:?}"))?; config .cert_mode .build( diff --git a/iroh-dns-server/src/http/tls.rs b/iroh-dns-server/src/http/tls.rs index 403da142ea2..655b3f0675b 100644 --- a/iroh-dns-server/src/http/tls.rs +++ b/iroh-dns-server/src/http/tls.rs @@ -9,8 +9,8 @@ use axum_server::{ accept::Accept, tls_rustls::{RustlsAcceptor, RustlsConfig}, }; -use n0_future::{FutureExt, future::Boxed as BoxFuture}; use n0_error::{Result, StdResultExt, whatever}; +use n0_future::{FutureExt, future::Boxed as BoxFuture}; use serde::{Deserialize, Serialize}; use tokio::io::{AsyncRead, AsyncWrite}; use tokio_rustls_acme::{AcmeConfig, axum::AxumAcceptor, caches::DirCache}; @@ -157,7 +157,9 @@ async fn load_secret_key( let mut reader = std::io::Cursor::new(keyfile); loop { - match rustls_pemfile::read_one(&mut reader).std_context("cannot parse secret key .pem file")? { + match rustls_pemfile::read_one(&mut reader) + .std_context("cannot parse secret key .pem file")? + { Some(rustls_pemfile::Item::Pkcs1Key(key)) => { return Ok(rustls::pki_types::PrivateKeyDer::Pkcs1(key)); } diff --git a/iroh-dns-server/src/server.rs b/iroh-dns-server/src/server.rs index d8ab32822ec..8eb0b515782 100644 --- a/iroh-dns-server/src/server.rs +++ b/iroh-dns-server/src/server.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use iroh_metrics::service::start_metrics_server; -use n0_error::{Result, StdResultExt, StackResultExt}; +use n0_error::{Result, StdResultExt}; use tracing::info; use crate::{ diff --git a/iroh-dns-server/src/store/signed_packets.rs b/iroh-dns-server/src/store/signed_packets.rs index 9e7c1880814..13d702f7979 100644 --- a/iroh-dns-server/src/store/signed_packets.rs +++ b/iroh-dns-server/src/store/signed_packets.rs @@ -6,7 +6,7 @@ use std::{ time::{Duration, SystemTime}, }; -use n0_error::{Result, StdResultExt, StackResultExt, format_err}; +use n0_error::{Result, StdResultExt, format_err}; use pkarr::{SignedPacket, Timestamp}; use redb::{ Database, MultimapTableDefinition, ReadableTable, TableDefinition, backends::InMemoryBackend, @@ -128,90 +128,90 @@ impl Actor { tokio::pin!(timeout); for _ in 0..self.options.max_batch_size { tokio::select! { - _ = self.cancel.cancelled() => { - drop(tables); - transaction.commit().e()?; - return Ok(()); - } - _ = &mut timeout => break, - Some(msg) = self.recv.recv() => { - match msg { - Message::Get { key, res } => { - match get_packet(&tables.signed_packets, &key) { - Ok(packet) => { - trace!("get {key}: {}", packet.is_some()); - res.send(packet).ok(); - }, - Err(err) => { - warn!("get {key} failed: {err:#}"); - return Err(err).std_context(format!("get packet for {key} failed")) + _ = self.cancel.cancelled() => { + drop(tables); + transaction.commit().e()?; + return Ok(()); + } + _ = &mut timeout => break, + Some(msg) = self.recv.recv() => { + match msg { + Message::Get { key, res } => { + match get_packet(&tables.signed_packets, &key) { + Ok(packet) => { + trace!("get {key}: {}", packet.is_some()); + res.send(packet).ok(); + }, + Err(err) => { + warn!("get {key} failed: {err:#}"); + return Err(err).std_context(format!("get packet for {key} failed")) + } } } - } - Message::Upsert { packet, res } => { - let key = PublicKeyBytes::from_signed_packet(&packet); - trace!("upsert {}", key); - let replaced = match get_packet(&tables.signed_packets, &key)? { Some(existing) => { - if existing.more_recent_than(&packet) { - res.send(false).ok(); - continue; + Message::Upsert { packet, res } => { + let key = PublicKeyBytes::from_signed_packet(&packet); + trace!("upsert {}", key); + let replaced = match get_packet(&tables.signed_packets, &key)? { Some(existing) => { + if existing.more_recent_than(&packet) { + res.send(false).ok(); + continue; + } else { + // remove the old packet from the update time index + tables.update_time.remove(&existing.timestamp().to_bytes(), key.as_bytes()).e()?; + true + } + } _ => { + false + }}; + let value = packet.serialize(); + tables.signed_packets + .insert(key.as_bytes(), &value[..]).e()?; + tables.update_time + .insert(&packet.timestamp().to_bytes(), key.as_bytes()).e()?; + if replaced { + self.metrics.store_packets_updated.inc(); } else { - // remove the old packet from the update time index - tables.update_time.remove(&existing.timestamp().to_bytes(), key.as_bytes()).e()?; - true + self.metrics.store_packets_inserted.inc(); } - } _ => { - false - }}; - let value = packet.serialize(); - tables.signed_packets - .insert(key.as_bytes(), &value[..]).e()?; - tables.update_time - .insert(&packet.timestamp().to_bytes(), key.as_bytes()).e()?; - if replaced { - self.metrics.store_packets_updated.inc(); - } else { - self.metrics.store_packets_inserted.inc(); + res.send(true).ok(); } - res.send(true).ok(); - } - Message::Remove { key, res } => { - trace!("remove {}", key); - let updated = match tables.signed_packets.remove(key.as_bytes()).e()? { Some(row) => { - let packet = SignedPacket::deserialize(row.value()).e()?; - tables.update_time.remove(&packet.timestamp().to_bytes(), key.as_bytes()).e()?; - self.metrics.store_packets_removed.inc(); - true - } _ => { - false - }}; - res.send(updated).ok(); - } - Message::Snapshot { res } => { - trace!("snapshot"); - res.send(Snapshot::new(&self.db)?).ok(); - } - Message::CheckExpired { key, time } => { - trace!("check expired {} at {}", key, fmt_time(time)); - match get_packet(&tables.signed_packets, &key)? { Some(packet) => { - let expired = Timestamp::now() - expiry_us; - if packet.timestamp() < expired { - tables.update_time.remove(&time.to_bytes(), key.as_bytes()).e()?; - let _ = tables.signed_packets.remove(key.as_bytes()).e()?; - self.metrics.store_packets_expired.inc(); - debug!("removed expired packet {key}"); - } else { - debug!("packet {key} is no longer expired, removing obsolete expiry entry"); + Message::Remove { key, res } => { + trace!("remove {}", key); + let updated = match tables.signed_packets.remove(key.as_bytes()).e()? { Some(row) => { + let packet = SignedPacket::deserialize(row.value()).e()?; + tables.update_time.remove(&packet.timestamp().to_bytes(), key.as_bytes()).e()?; + self.metrics.store_packets_removed.inc(); + true + } _ => { + false + }}; + res.send(updated).ok(); + } + Message::Snapshot { res } => { + trace!("snapshot"); + res.send(Snapshot::new(&self.db)?).ok(); + } + Message::CheckExpired { key, time } => { + trace!("check expired {} at {}", key, fmt_time(time)); + match get_packet(&tables.signed_packets, &key)? { Some(packet) => { + let expired = Timestamp::now() - expiry_us; + if packet.timestamp() < expired { + tables.update_time.remove(&time.to_bytes(), key.as_bytes()).e()?; + let _ = tables.signed_packets.remove(key.as_bytes()).e()?; + self.metrics.store_packets_expired.inc(); + debug!("removed expired packet {key}"); + } else { + debug!("packet {key} is no longer expired, removing obsolete expiry entry"); + tables.update_time.remove(&time.to_bytes(), key.as_bytes()).e()?; + } + } _ => { + debug!("expired packet {key} not found, remove from expiry table"); tables.update_time.remove(&time.to_bytes(), key.as_bytes()).e()?; - } - } _ => { - debug!("expired packet {key} not found, remove from expiry table"); - tables.update_time.remove(&time.to_bytes(), key.as_bytes()).e()?; - }} + }} + } } } } - } } drop(tables); transaction.commit().e()?; diff --git a/iroh/bench/src/iroh.rs b/iroh/bench/src/iroh.rs index 4720e845917..9a2711c27c3 100644 --- a/iroh/bench/src/iroh.rs +++ b/iroh/bench/src/iroh.rs @@ -8,7 +8,7 @@ use iroh::{ Endpoint, EndpointAddr, RelayMode, RelayUrl, endpoint::{Connection, ConnectionError, RecvStream, SendStream, TransportConfig}, }; -use n0_error::{Result, StackResultExt, StdResultExt}; +use n0_error::{Result, StdResultExt}; use tracing::{trace, warn}; use crate::{ diff --git a/iroh/examples/0rtt.rs b/iroh/examples/0rtt.rs index 77f5cc14ff0..d28b9747965 100644 --- a/iroh/examples/0rtt.rs +++ b/iroh/examples/0rtt.rs @@ -7,7 +7,7 @@ use iroh::{ endpoint::{Connecting, Connection}, }; use iroh_base::ticket::EndpointTicket; -use n0_error::{Result, StdResultExt, StackResultExt, whatever}; +use n0_error::{Result, StackResultExt, StdResultExt, whatever}; use n0_future::{StreamExt, future}; use n0_watcher::Watcher; use tracing::{info, trace}; diff --git a/iroh/examples/locally-discovered-nodes.rs b/iroh/examples/locally-discovered-nodes.rs index 0a972d228c1..dce5fda31d5 100644 --- a/iroh/examples/locally-discovered-nodes.rs +++ b/iroh/examples/locally-discovered-nodes.rs @@ -10,8 +10,8 @@ use iroh::{ discovery::mdns::{DiscoveryEvent, MdnsDiscovery}, endpoint_info::UserData, }; -use n0_future::StreamExt; use n0_error::Result; +use n0_future::StreamExt; use tokio::task::JoinSet; #[tokio::main] diff --git a/iroh/examples/transfer.rs b/iroh/examples/transfer.rs index 8b3e4489500..e59f753845c 100644 --- a/iroh/examples/transfer.rs +++ b/iroh/examples/transfer.rs @@ -17,8 +17,8 @@ use iroh::{ endpoint::ConnectionError, }; use iroh_base::ticket::EndpointTicket; +use n0_error::{Result, StackResultExt, StdResultExt, whatever}; use n0_future::task::AbortOnDropHandle; -use n0_error::{Result, StdResultExt, StackResultExt, whatever}; use n0_watcher::Watcher as _; use tokio_stream::StreamExt; use tracing::{info, warn}; diff --git a/iroh/src/discovery.rs b/iroh/src/discovery.rs index f0c5b07a852..7d1fb312703 100644 --- a/iroh/src/discovery.rs +++ b/iroh/src/discovery.rs @@ -650,7 +650,7 @@ mod tests { }; use iroh_base::{EndpointAddr, SecretKey}; - use n0_error::{Result, StackResultExt, StdResultExt, AnyError as Error}; + use n0_error::{AnyError as Error, Result, StackResultExt, StdResultExt}; use quinn::{IdleTimeout, TransportConfig}; use rand::{CryptoRng, Rng, SeedableRng}; use tokio_util::task::AbortOnDropHandle; @@ -969,8 +969,8 @@ mod tests { mod test_dns_pkarr { use iroh_base::{EndpointAddr, SecretKey}; use iroh_relay::{RelayMap, endpoint_info::UserData}; + use n0_error::{AnyError as Error, Result, StackResultExt, StdResultExt}; use n0_future::time::Duration; - use n0_error::{Result, StackResultExt, StdResultExt, AnyError as Error}; use rand::{CryptoRng, SeedableRng}; use tokio_util::task::AbortOnDropHandle; use tracing_test::traced_test; @@ -1066,7 +1066,9 @@ mod test_dns_pkarr { async fn pkarr_publish_dns_discover() -> Result<()> { let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(0u64); - let dns_pkarr_server = DnsPkarrServer::run().await.std_context("DnsPkarrServer run")?; + let dns_pkarr_server = DnsPkarrServer::run() + .await + .std_context("DnsPkarrServer run")?; let (relay_map, _relay_url, _relay_guard) = run_relay_server().await?; let (ep1, _guard1) = ep_with_discovery(&mut rng, &relay_map, &dns_pkarr_server).await?; diff --git a/iroh/src/discovery/mdns.rs b/iroh/src/discovery/mdns.rs index a7515b1808c..2a181d944b5 100644 --- a/iroh/src/discovery/mdns.rs +++ b/iroh/src/discovery/mdns.rs @@ -544,10 +544,9 @@ mod tests { /// tests) mod run_in_isolation { use iroh_base::SecretKey; + use n0_error::{AnyError as Error, Result, StackResultExt, StdResultExt, whatever}; use n0_future::StreamExt; - use n0_error::{Result, StackResultExt, StdResultExt, AnyError as Error}; use rand::{CryptoRng, SeedableRng}; - use n0_error::whatever; use tracing_test::traced_test; use super::super::*; diff --git a/iroh/src/discovery/pkarr.rs b/iroh/src/discovery/pkarr.rs index 6f43ed81cd7..6f328f0c4c1 100644 --- a/iroh/src/discovery/pkarr.rs +++ b/iroh/src/discovery/pkarr.rs @@ -48,7 +48,7 @@ use std::sync::Arc; use iroh_base::{EndpointId, RelayUrl, SecretKey}; use iroh_relay::endpoint_info::{EncodingError, EndpointInfo}; -use n0_error::{add_meta, e, Error, Err}; +use n0_error::{Err, Error, add_meta, e}; use n0_future::{ boxed::BoxStream, task::{self, AbortOnDropHandle}, @@ -81,17 +81,29 @@ pub mod dht; #[non_exhaustive] pub enum PkarrError { #[display("Invalid public key")] - PublicKey { #[error(std_err)] source: PublicKeyError }, + PublicKey { + #[error(std_err)] + source: PublicKeyError, + }, #[display("Packet failed to verify")] - Verify { #[error(std_err)] source: SignedPacketVerifyError }, + Verify { + #[error(std_err)] + source: SignedPacketVerifyError, + }, #[display("Invalid relay URL")] InvalidRelayUrl { url: RelayUrl }, #[display("Error sending http request")] - HttpSend { #[error(std_err)] source: reqwest::Error }, + HttpSend { + #[error(std_err)] + source: reqwest::Error, + }, #[display("Error resolving http request")] HttpRequest { status: reqwest::StatusCode }, #[display("Http payload error")] - HttpPayload { #[error(std_err)] source: reqwest::Error }, + HttpPayload { + #[error(std_err)] + source: reqwest::Error, + }, #[display("EncodingError")] Encoding { source: EncodingError }, } @@ -555,7 +567,11 @@ impl PkarrRelayClient { let mut url = self.pkarr_relay_url.clone(); url.path_segments_mut() - .map_err(|_| e!(PkarrError::InvalidRelayUrl { url: self.pkarr_relay_url.clone().into() }))? + .map_err(|_| { + e!(PkarrError::InvalidRelayUrl { + url: self.pkarr_relay_url.clone().into() + }) + })? .push(&public_key.to_z32()); let response = self @@ -566,7 +582,10 @@ impl PkarrRelayClient { .map_err(|source| e!(PkarrError::HttpSend { source }))?; if !response.status().is_success() { - return Err(e!(PkarrError::HttpRequest { status: response.status() }).into()); + return Err(e!(PkarrError::HttpRequest { + status: response.status() + }) + .into()); } let payload = response @@ -583,7 +602,11 @@ impl PkarrRelayClient { pub async fn publish(&self, signed_packet: &SignedPacket) -> Result<(), PkarrError> { let mut url = self.pkarr_relay_url.clone(); url.path_segments_mut() - .map_err(|_| e!(PkarrError::InvalidRelayUrl { url: self.pkarr_relay_url.clone().into() }))? + .map_err(|_| { + e!(PkarrError::InvalidRelayUrl { + url: self.pkarr_relay_url.clone().into() + }) + })? .push(&signed_packet.public_key().to_z32()); let response = self @@ -595,7 +618,9 @@ impl PkarrRelayClient { .map_err(|source| e!(PkarrError::HttpSend { source }))?; if !response.status().is_success() { - return Err!(PkarrError::HttpRequest { status: response.status() }); + return Err!(PkarrError::HttpRequest { + status: response.status() + }); } Ok(()) diff --git a/iroh/src/discovery/static_provider.rs b/iroh/src/discovery/static_provider.rs index 0a09a460eeb..2347283c271 100644 --- a/iroh/src/discovery/static_provider.rs +++ b/iroh/src/discovery/static_provider.rs @@ -125,8 +125,8 @@ impl StaticProvider { /// # fn get_addrs() -> Vec { /// # Vec::new() /// # } -/// # #[tokio::main] -/// # async fn main() -> n0_error::Result<()> { + /// # #[tokio::main] + /// # async fn main() -> n0_error::Result<()> { /// // get addrs from somewhere /// let addrs = get_addrs(); /// diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 5455180a5b4..66c60605f65 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -487,9 +487,7 @@ pub struct Endpoint { #[non_exhaustive] pub enum ConnectWithOptsError { #[error(transparent)] - AddEndpointAddr { - source: AddEndpointAddrError, - }, + AddEndpointAddr { source: AddEndpointAddrError }, #[display("Connecting to ourself is not supported")] SelfConnect, #[display("No addressing information available")] @@ -510,7 +508,10 @@ pub enum ConnectError { #[error(transparent)] Connect { source: ConnectWithOptsError }, #[error(transparent)] - Connection { #[error(std_err)] source: ConnectionError }, + Connection { + #[error(std_err)] + source: ConnectionError, + }, } #[allow(missing_docs)] @@ -2120,8 +2121,8 @@ mod tests { use std::time::{Duration, Instant}; use iroh_base::{EndpointAddr, EndpointId, SecretKey}; - use n0_future::{BufferedStreamExt, StreamExt, stream, task::AbortOnDropHandle}; use n0_error::{AnyError as Error, StackResultExt, StdResultExt}; + use n0_future::{BufferedStreamExt, StreamExt, stream, task::AbortOnDropHandle}; type Result = std::result::Result; use n0_watcher::Watcher; use quinn::ConnectionError; @@ -2374,9 +2375,9 @@ mod tests { let task = tokio::spawn({ let server = server.clone(); async move { - let Some(conn) = server.accept().await else { - n0_error::whatever!("Expected an incoming connection"); - }; + let Some(conn) = server.accept().await else { + n0_error::whatever!("Expected an incoming connection"); + }; let conn = conn.await.e()?; let (mut send, mut recv) = conn.accept_bi().await.e()?; let data = recv.read_to_end(1000).await.e()?; diff --git a/iroh/src/lib.rs b/iroh/src/lib.rs index cb44baed13d..82ad318a0ff 100644 --- a/iroh/src/lib.rs +++ b/iroh/src/lib.rs @@ -196,8 +196,8 @@ //! //! ```no_run //! use iroh::{Endpoint, EndpointAddr}; -//! use n0_future::StreamExt; //! use n0_error::{Result, StackResultExt}; +//! use n0_future::StreamExt; //! //! async fn accept() -> Result<()> { //! // To accept connections at least one ALPN must be configured. diff --git a/iroh/src/magicsock.rs b/iroh/src/magicsock.rs index 8c8fcfcd827..5d905b9ab42 100644 --- a/iroh/src/magicsock.rs +++ b/iroh/src/magicsock.rs @@ -32,6 +32,7 @@ use bytes::Bytes; use data_encoding::HEXLOWER; use iroh_base::{EndpointAddr, EndpointId, PublicKey, RelayUrl, SecretKey}; use iroh_relay::{RelayConfig, RelayMap}; +use n0_error::{Err, Error, add_meta, e}; use n0_future::{ task::{self, AbortOnDropHandle}, time::{self, Duration, Instant}, @@ -43,7 +44,6 @@ use netwatch::{UdpSocket, ip::LocalAddresses}; use quinn::{AsyncUdpSocket, ServerConfig}; use rand::Rng; use smallvec::SmallVec; -use n0_error::{add_meta, e, Error, Err}; use tokio::sync::{Mutex as AsyncMutex, mpsc}; use tokio_util::sync::CancellationToken; use tracing::{ @@ -1334,15 +1334,30 @@ impl DirectAddrUpdateState { #[non_exhaustive] pub enum CreateHandleError { #[display("Failed to create bind sockets")] - BindSockets { #[error(std_err)] source: io::Error }, + BindSockets { + #[error(std_err)] + source: io::Error, + }, #[display("Failed to create internal quinn endpoint")] - CreateQuinnEndpoint { #[error(std_err)] source: io::Error }, + CreateQuinnEndpoint { + #[error(std_err)] + source: io::Error, + }, #[display("Failed to create socket state")] - CreateSocketState { #[error(std_err)] source: io::Error }, + CreateSocketState { + #[error(std_err)] + source: io::Error, + }, #[display("Failed to create netmon monitor")] - CreateNetmonMonitor { #[error(std_err)] source: netmon::Error }, + CreateNetmonMonitor { + #[error(std_err)] + source: netmon::Error, + }, #[display("Failed to subscribe netmon monitor")] - SubscribeNetmonMonitor { #[error(std_err)] source: netmon::Error }, + SubscribeNetmonMonitor { + #[error(std_err)] + source: netmon::Error, + }, } impl Handle { @@ -1673,8 +1688,7 @@ impl DiscoState { sealed_box: &[u8], ) -> Result { let mut sealed_box = sealed_box.to_vec(); - self - .get_secret(endpoint_id, |secret| secret.open(&mut sealed_box)) + self.get_secret(endpoint_id, |secret| secret.open(&mut sealed_box)) .map_err(|source| e!(DiscoBoxError::Open { source }))?; disco::Message::from_bytes(&sealed_box) .map_err(|source| e!(DiscoBoxError::Parse { source })) @@ -2523,7 +2537,7 @@ mod tests { use data_encoding::HEXLOWER; use iroh_base::{EndpointAddr, EndpointId, PublicKey}; - use n0_error::{Result, StackResultExt, StdResultExt, AnyError}; + use n0_error::{AnyError, Result, StackResultExt, StdResultExt}; use n0_future::{StreamExt, time}; use n0_watcher::Watcher; use quinn::ServerConfig; @@ -3275,7 +3289,10 @@ mod tests { .await .std_context("connecting")?; let mut stream = conn.accept_uni().await.std_context("accept uni")?; - stream.read_to_end(1 << 16).await.std_context("read to end")?; + stream + .read_to_end(1 << 16) + .await + .std_context("read to end")?; info!("accept finished"); Ok(()) } diff --git a/iroh/src/net_report/ip_mapped_addrs.rs b/iroh/src/net_report/ip_mapped_addrs.rs index f1fae4c45d5..9bf3792dc07 100644 --- a/iroh/src/net_report/ip_mapped_addrs.rs +++ b/iroh/src/net_report/ip_mapped_addrs.rs @@ -7,7 +7,7 @@ use std::{ }, }; -use n0_error::{add_meta, Error, Err, e}; +use n0_error::{Err, Error, add_meta, e}; /// Can occur when converting a [`SocketAddr`] to an [`IpMappedAddr`] #[add_meta] diff --git a/iroh/src/tls/resolver.rs b/iroh/src/tls/resolver.rs index 034068003ab..84657d84219 100644 --- a/iroh/src/tls/resolver.rs +++ b/iroh/src/tls/resolver.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use ed25519_dalek::pkcs8::{EncodePrivateKey, spki::der::pem::LineEnding}; use iroh_base::SecretKey; -use n0_error::{add_meta, Error}; +use n0_error::{Error, add_meta}; use webpki_types::{CertificateDer, PrivatePkcs8KeyDer, pem::PemObject}; #[derive(Debug)] diff --git a/iroh/tests/integration.rs b/iroh/tests/integration.rs index 6a470f578d9..b72dffc950e 100644 --- a/iroh/tests/integration.rs +++ b/iroh/tests/integration.rs @@ -13,11 +13,11 @@ use iroh::{ Endpoint, RelayMode, discovery::{Discovery, pkarr::PkarrResolver}, }; +use n0_error::{Result, StackResultExt, StdResultExt}; use n0_future::{ StreamExt, task, time::{self, Duration}, }; -use n0_error::{Result, StackResultExt, StdResultExt}; #[cfg(not(wasm_browser))] use tokio::test; use tracing::{Instrument, info_span}; From 8afe0b75885d9832756cd872019e59aecbf99752 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 23:24:50 +0200 Subject: [PATCH 15/58] chore: clippy fix & cargo fix & fmt --- iroh-dns-server/src/config.rs | 2 +- iroh-dns-server/src/http.rs | 2 +- iroh-dns-server/src/lib.rs | 8 ++++---- iroh/examples/0rtt.rs | 2 +- iroh/examples/dht_discovery.rs | 2 +- iroh/examples/listen.rs | 2 +- iroh/examples/locally-discovered-nodes.rs | 2 +- iroh/examples/screening-connection.rs | 4 +++- iroh/examples/transfer.rs | 12 ++++++------ 9 files changed, 19 insertions(+), 17 deletions(-) diff --git a/iroh-dns-server/src/config.rs b/iroh-dns-server/src/config.rs index bf15f9a693e..261317f0a5b 100644 --- a/iroh-dns-server/src/config.rs +++ b/iroh-dns-server/src/config.rs @@ -7,7 +7,7 @@ use std::{ time::Duration, }; -use n0_error::{Result, StackResultExt, StdResultExt}; +use n0_error::{Result, StdResultExt}; use serde::{Deserialize, Serialize}; use tracing::info; diff --git a/iroh-dns-server/src/http.rs b/iroh-dns-server/src/http.rs index c415355ca18..add5625776f 100644 --- a/iroh-dns-server/src/http.rs +++ b/iroh-dns-server/src/http.rs @@ -14,7 +14,7 @@ use axum::{ response::IntoResponse, routing::get, }; -use n0_error::{Result, StackResultExt, StdResultExt, whatever}; +use n0_error::{Result, StdResultExt, whatever}; use serde::{Deserialize, Serialize}; use tokio::{net::TcpListener, task::JoinSet}; use tower_http::{ diff --git a/iroh-dns-server/src/lib.rs b/iroh-dns-server/src/lib.rs index f17050d7cfc..af2e5e38287 100644 --- a/iroh-dns-server/src/lib.rs +++ b/iroh-dns-server/src/lib.rs @@ -43,7 +43,7 @@ mod tests { #[tokio::test] #[traced_test] async fn pkarr_publish_dns_resolve() -> Result { - let (server, nameserver, http_url) = Server::spawn_for_tests().await.e()?; + let (server, nameserver, http_url) = Server::spawn_for_tests().await?; let pkarr_relay_url = { let mut url = http_url.clone(); url.set_path("/pkarr"); @@ -158,7 +158,7 @@ mod tests { #[tokio::test] #[traced_test] async fn integration_smoke() -> Result { - let (server, nameserver, http_url) = Server::spawn_for_tests().await.e()?; + let (server, nameserver, http_url) = Server::spawn_for_tests().await?; let pkarr_relay = { let mut url = http_url.clone(); @@ -213,7 +213,7 @@ mod tests { tokio::time::sleep(Duration::from_secs(1)).await; for _ in 0..10 { - let entry = store.get_signed_packet(&key).await.e()?; + let entry = store.get_signed_packet(&key).await?; if entry.is_none() { return Ok(()); } @@ -264,7 +264,7 @@ mod tests { assert_eq!(res.endpoint_id, endpoint_id); assert_eq!(res.relay_url(), Some(&relay_url)); - server.shutdown().await.e()?; + server.shutdown().await?; Ok(()) } diff --git a/iroh/examples/0rtt.rs b/iroh/examples/0rtt.rs index d28b9747965..b433a0cbb7d 100644 --- a/iroh/examples/0rtt.rs +++ b/iroh/examples/0rtt.rs @@ -166,7 +166,7 @@ async fn accept(_args: Args) -> Result<()> { send.write_all(&data).await.e()?; send.finish().e()?; connection.closed().await; - Ok::<_, n0_error::Error>(()) + Ok::<_, n0_error::AnyError>(()) }); } }; diff --git a/iroh/examples/dht_discovery.rs b/iroh/examples/dht_discovery.rs index 33ca5a7302a..02ec9af4606 100644 --- a/iroh/examples/dht_discovery.rs +++ b/iroh/examples/dht_discovery.rs @@ -100,7 +100,7 @@ async fn chat_server(args: Args) -> Result<()> { tokio::spawn( async move { tokio::io::copy(&mut tokio::io::stdin(), &mut writer).await }, ); - Ok::<_, n0_error::Error>(()) + Ok::<_, n0_error::AnyError>(()) }); } Ok(()) diff --git a/iroh/examples/listen.rs b/iroh/examples/listen.rs index eac4e0b95c6..24b91353265 100644 --- a/iroh/examples/listen.rs +++ b/iroh/examples/listen.rs @@ -105,7 +105,7 @@ async fn main() -> Result<()> { if res.is_err() { println!("endpoint {endpoint_id} did not disconnect within 3 seconds"); } - Ok::<_, n0_error::Error>(()) + Ok::<_, n0_error::AnyError>(()) }); } // stop with SIGINT (ctrl-c) diff --git a/iroh/examples/locally-discovered-nodes.rs b/iroh/examples/locally-discovered-nodes.rs index dce5fda31d5..3b0274d343a 100644 --- a/iroh/examples/locally-discovered-nodes.rs +++ b/iroh/examples/locally-discovered-nodes.rs @@ -73,7 +73,7 @@ async fn main() -> Result<()> { ep.set_user_data_for_discovery(Some(ud)); tokio::time::sleep(Duration::from_secs(3)).await; ep.close().await; - Ok::<_, n0_error::Error>(()) + Ok::<_, n0_error::AnyError>(()) }); } diff --git a/iroh/examples/screening-connection.rs b/iroh/examples/screening-connection.rs index 632dab56347..e555243be17 100644 --- a/iroh/examples/screening-connection.rs +++ b/iroh/examples/screening-connection.rs @@ -110,7 +110,9 @@ impl ProtocolHandler for ScreenedEcho { // reject every other connection if count % 2 == 0 { println!("rejecting connection"); - return Err(AcceptError::NotAllowed {}); + return Err(AcceptError::NotAllowed { + meta: n0_error::Meta::new(), + }); } // To allow normal connection construction, await the connecting future & return diff --git a/iroh/examples/transfer.rs b/iroh/examples/transfer.rs index e59f753845c..dd459cea22e 100644 --- a/iroh/examples/transfer.rs +++ b/iroh/examples/transfer.rs @@ -246,7 +246,7 @@ impl EndpointArgs { if let Some(host) = self.dns_server { let addr = tokio::net::lookup_host(host) .await - .context("Failed to resolve DNS server address")? + .std_context("Failed to resolve DNS server address")? .next() .context("Failed to resolve DNS server address")?; builder = builder.dns_resolver(DnsResolver::with_nameserver(addr)); @@ -379,7 +379,7 @@ async fn provide(endpoint: Endpoint, size: u64) -> Result<()> { } else { println!("[{remote}] Disconnected"); } - Ok::<_, n0_error::Error>(()) + Ok::<_, n0_error::AnyError>(()) }); } @@ -493,21 +493,21 @@ async fn send_data_on_stream( stream .write_chunk(bytes_data.clone()) .await - .context("failed sending data")?; + .std_context("failed sending data")?; } if remaining != 0 { stream .write_chunk(bytes_data.slice(0..remaining)) .await - .context("failed sending data")?; + .std_context("failed sending data")?; } - stream.finish().context("failed finishing stream")?; + stream.finish().std_context("failed finishing stream")?; stream .stopped() .await - .context("failed to wait for stream to be stopped")?; + .std_context("failed to wait for stream to be stopped")?; Ok(()) } From 4365e910d7a2c211d81153fe819a9c4f19cd278b Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 23:38:40 +0200 Subject: [PATCH 16/58] fixup --- iroh/examples/transfer.rs | 9 +++++---- iroh/src/discovery.rs | 6 +++--- iroh/src/discovery/mdns.rs | 2 +- iroh/src/discovery/pkarr/dht.rs | 2 +- iroh/src/endpoint.rs | 2 +- iroh/src/magicsock.rs | 2 +- iroh/src/net_report.rs | 2 +- iroh/src/net_report/reportgen.rs | 2 +- iroh/tests/integration.rs | 2 +- 9 files changed, 15 insertions(+), 14 deletions(-) diff --git a/iroh/examples/transfer.rs b/iroh/examples/transfer.rs index dd459cea22e..db3477067a4 100644 --- a/iroh/examples/transfer.rs +++ b/iroh/examples/transfer.rs @@ -17,7 +17,7 @@ use iroh::{ endpoint::ConnectionError, }; use iroh_base::ticket::EndpointTicket; -use n0_error::{Result, StackResultExt, StdResultExt, whatever}; +use n0_error::{Result, StdResultExt}; use n0_future::task::AbortOnDropHandle; use n0_watcher::Watcher as _; use tokio_stream::StreamExt; @@ -183,8 +183,9 @@ impl EndpointArgs { let mut builder = Endpoint::builder(); let secret_key = match std::env::var("IROH_SECRET") { - Ok(s) => SecretKey::from_str(&s) - .context("Failed to parse IROH_SECRET environment variable as iroh secret key")?, + Ok(s) => SecretKey::from_str(&s).std_context( + "Failed to parse IROH_SECRET environment variable as iroh secret key", + )?, Err(_) => { let s = SecretKey::generate(&mut rand::rng()); println!("Generated a new endpoint secret. To reuse, set"); @@ -248,7 +249,7 @@ impl EndpointArgs { .await .std_context("Failed to resolve DNS server address")? .next() - .context("Failed to resolve DNS server address")?; + .std_context("Failed to resolve DNS server address")?; builder = builder.dns_resolver(DnsResolver::with_nameserver(addr)); } else if self.env == Env::Dev { let addr = DEV_DNS_SERVER.parse().expect("valid addr"); diff --git a/iroh/src/discovery.rs b/iroh/src/discovery.rs index 7d1fb312703..af030634ec8 100644 --- a/iroh/src/discovery.rs +++ b/iroh/src/discovery.rs @@ -650,7 +650,7 @@ mod tests { }; use iroh_base::{EndpointAddr, SecretKey}; - use n0_error::{AnyError as Error, Result, StackResultExt, StdResultExt}; + use n0_error::{AnyError as Error, Result, StdResultExt}; use quinn::{IdleTimeout, TransportConfig}; use rand::{CryptoRng, Rng, SeedableRng}; use tokio_util::task::AbortOnDropHandle; @@ -826,7 +826,7 @@ mod tests { let _conn = ep2 .connect(ep1_addr, TEST_ALPN) .await - .context("connecting")?; + .std_context("connecting")?; Ok(()) } @@ -969,7 +969,7 @@ mod tests { mod test_dns_pkarr { use iroh_base::{EndpointAddr, SecretKey}; use iroh_relay::{RelayMap, endpoint_info::UserData}; - use n0_error::{AnyError as Error, Result, StackResultExt, StdResultExt}; + use n0_error::{AnyError as Error, Result, StdResultExt}; use n0_future::time::Duration; use rand::{CryptoRng, SeedableRng}; use tokio_util::task::AbortOnDropHandle; diff --git a/iroh/src/discovery/mdns.rs b/iroh/src/discovery/mdns.rs index 2a181d944b5..b92a828c499 100644 --- a/iroh/src/discovery/mdns.rs +++ b/iroh/src/discovery/mdns.rs @@ -544,7 +544,7 @@ mod tests { /// tests) mod run_in_isolation { use iroh_base::SecretKey; - use n0_error::{AnyError as Error, Result, StackResultExt, StdResultExt, whatever}; + use n0_error::{AnyError as Error, Result, StdResultExt, whatever}; use n0_future::StreamExt; use rand::{CryptoRng, SeedableRng}; use tracing_test::traced_test; diff --git a/iroh/src/discovery/pkarr/dht.rs b/iroh/src/discovery/pkarr/dht.rs index 7599416220c..0af39f5ea4c 100644 --- a/iroh/src/discovery/pkarr/dht.rs +++ b/iroh/src/discovery/pkarr/dht.rs @@ -333,7 +333,7 @@ mod tests { use std::collections::BTreeSet; use iroh_base::RelayUrl; - use n0_error::{Result, StackResultExt, StdResultExt}; + use n0_error::{Result, StdResultExt}; use tracing_test::traced_test; use super::*; diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 66c60605f65..53ff826302b 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -2121,7 +2121,7 @@ mod tests { use std::time::{Duration, Instant}; use iroh_base::{EndpointAddr, EndpointId, SecretKey}; - use n0_error::{AnyError as Error, StackResultExt, StdResultExt}; + use n0_error::{AnyError as Error, StdResultExt}; use n0_future::{BufferedStreamExt, StreamExt, stream, task::AbortOnDropHandle}; type Result = std::result::Result; use n0_watcher::Watcher; diff --git a/iroh/src/magicsock.rs b/iroh/src/magicsock.rs index 5d905b9ab42..a73bb3fc6f3 100644 --- a/iroh/src/magicsock.rs +++ b/iroh/src/magicsock.rs @@ -2537,7 +2537,7 @@ mod tests { use data_encoding::HEXLOWER; use iroh_base::{EndpointAddr, EndpointId, PublicKey}; - use n0_error::{AnyError, Result, StackResultExt, StdResultExt}; + use n0_error::{Result, StdResultExt}; use n0_future::{StreamExt, time}; use n0_watcher::Watcher; use quinn::ServerConfig; diff --git a/iroh/src/net_report.rs b/iroh/src/net_report.rs index e39f6429e5c..a2a0889d5ee 100644 --- a/iroh/src/net_report.rs +++ b/iroh/src/net_report.rs @@ -963,7 +963,7 @@ mod tests { use iroh_base::RelayUrl; use iroh_relay::dns::DnsResolver; - use n0_error::{Result, StackResultExt, StdResultExt}; + use n0_error::{Result, StdResultExt}; use tokio_util::sync::CancellationToken; use tracing_test::traced_test; diff --git a/iroh/src/net_report/reportgen.rs b/iroh/src/net_report/reportgen.rs index ddb665654ae..2c6875d6281 100644 --- a/iroh/src/net_report/reportgen.rs +++ b/iroh/src/net_report/reportgen.rs @@ -865,7 +865,7 @@ mod tests { use std::net::Ipv4Addr; use iroh_relay::dns::DnsResolver; - use n0_error::{Result, StackResultExt, StdResultExt}; + use n0_error::{Result, StdResultExt}; use tracing_test::traced_test; use super::{super::test_utils, *}; diff --git a/iroh/tests/integration.rs b/iroh/tests/integration.rs index b72dffc950e..7b3c98f86bc 100644 --- a/iroh/tests/integration.rs +++ b/iroh/tests/integration.rs @@ -13,7 +13,7 @@ use iroh::{ Endpoint, RelayMode, discovery::{Discovery, pkarr::PkarrResolver}, }; -use n0_error::{Result, StackResultExt, StdResultExt}; +use n0_error::{Result, StdResultExt}; use n0_future::{ StreamExt, task, time::{self, Duration}, From 099e2b041ade173b59773de5fb454decf57ea6ef Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 23:46:13 +0200 Subject: [PATCH 17/58] fixup --- Cargo.lock | 4 ++-- iroh-relay/src/quic.rs | 4 ++-- iroh-relay/src/server.rs | 2 +- iroh-relay/src/server/client.rs | 12 ++++++------ iroh-relay/src/server/http_server.rs | 2 +- iroh/examples/screening-connection.rs | 6 ++---- 6 files changed, 14 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a85f45e577c..4ad097f6366 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2805,7 +2805,7 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error#a51431dba41021f1dd0bfbcb1115fc3c5ec75116" +source = "git+https://github.com/n0-computer/n0-error#0070b103873f285627240e3c772fecec3f0b4528" dependencies = [ "anyhow", "derive_more 2.0.1", @@ -2816,7 +2816,7 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error#a51431dba41021f1dd0bfbcb1115fc3c5ec75116" +source = "git+https://github.com/n0-computer/n0-error#0070b103873f285627240e3c772fecec3f0b4528" dependencies = [ "darling", "heck", diff --git a/iroh-relay/src/quic.rs b/iroh-relay/src/quic.rs index bde7c7925d6..98bffe1db2a 100644 --- a/iroh-relay/src/quic.rs +++ b/iroh-relay/src/quic.rs @@ -16,7 +16,7 @@ pub const QUIC_ADDR_DISC_CLOSE_REASON: &[u8] = b"finished"; #[cfg(feature = "server")] pub(crate) mod server { - use n0_error::{StdResultExt, e}; + use n0_error::e; use quinn::{ ApplicationClose, ConnectionError, crypto::rustls::{NoInitialCipherSuite, QuicServerConfig}, @@ -360,7 +360,7 @@ impl QuicClient { mod tests { use std::net::Ipv4Addr; - use n0_error::{Error, Result, StdResultExt}; + use n0_error::{Result, StdResultExt}; use n0_future::{ task::AbortOnDropHandle, time::{self, Instant}, diff --git a/iroh-relay/src/server.rs b/iroh-relay/src/server.rs index 3ac5c172a15..ce0a5efdae2 100644 --- a/iroh-relay/src/server.rs +++ b/iroh-relay/src/server.rs @@ -26,7 +26,7 @@ use hyper::body::Incoming; use iroh_base::EndpointId; #[cfg(feature = "test-utils")] use iroh_base::RelayUrl; -use n0_error::{Err, Error, StdResultExt, add_meta, e}; +use n0_error::{Error, add_meta, e}; use n0_future::{StreamExt, future::Boxed}; use tokio::{ net::TcpListener, diff --git a/iroh-relay/src/server/client.rs b/iroh-relay/src/server/client.rs index a7cb42b98f1..1cabaac0eb2 100644 --- a/iroh-relay/src/server/client.rs +++ b/iroh-relay/src/server/client.rs @@ -3,7 +3,7 @@ use std::{collections::HashSet, sync::Arc, time::Duration}; use iroh_base::EndpointId; -use n0_error::{Err, Error, StackResultExt, add_meta, e}; +use n0_error::{Err, Error, add_meta, e}; use n0_future::{SinkExt, StreamExt}; use rand::Rng; use time::{Date, OffsetDateTime}; @@ -500,7 +500,7 @@ pub(crate) enum SendError { #[add_meta] #[derive(Error)] #[display("failed to forward {scope:?} packet: {reason:?}")] -pub(crate) struct ForwardPacketError { +pub struct ForwardPacketError { scope: PacketScope, reason: SendError, } @@ -724,8 +724,8 @@ mod tests { // Send a frame, it should arrive. info!("-- send packet"); - frame_writer.send(frame.clone()).await.context("send")?; - frame_writer.flush().await.context("flush")?; + frame_writer.send(frame.clone()).await.std_context("send")?; + frame_writer.flush().await.std_context("flush")?; let recv_frame = tokio::time::timeout(Duration::from_millis(500), stream.next()) .await .expect("timeout") @@ -735,8 +735,8 @@ mod tests { // Next frame does not arrive. info!("-- send packet"); - frame_writer.send(frame.clone()).await.context("send")?; - frame_writer.flush().await.context("flush")?; + frame_writer.send(frame.clone()).await.std_context("send")?; + frame_writer.flush().await.std_context("flush")?; let res = tokio::time::timeout(Duration::from_millis(100), stream.next()).await; assert!(res.is_err(), "expecting a timeout"); info!("-- timeout happened"); diff --git a/iroh-relay/src/server/http_server.rs b/iroh-relay/src/server/http_server.rs index 45a24909ea7..2b8370a1b5d 100644 --- a/iroh-relay/src/server/http_server.rs +++ b/iroh-relay/src/server/http_server.rs @@ -15,7 +15,7 @@ use hyper::{ service::Service, upgrade::Upgraded, }; -use n0_error::{Err, Error, StackResultExt, StdResultExt, add_meta, e}; +use n0_error::{Err, Error, add_meta, e}; use n0_future::time::Elapsed; use tokio::net::{TcpListener, TcpStream}; use tokio_rustls_acme::AcmeAcceptor; diff --git a/iroh/examples/screening-connection.rs b/iroh/examples/screening-connection.rs index e555243be17..c12a090d058 100644 --- a/iroh/examples/screening-connection.rs +++ b/iroh/examples/screening-connection.rs @@ -17,7 +17,7 @@ use iroh::{ endpoint::{Connecting, Connection}, protocol::{AcceptError, ProtocolHandler, Router}, }; -use n0_error::{Result, StdResultExt}; +use n0_error::{Err, Result, StdResultExt}; /// Each protocol is identified by its ALPN string. /// @@ -110,9 +110,7 @@ impl ProtocolHandler for ScreenedEcho { // reject every other connection if count % 2 == 0 { println!("rejecting connection"); - return Err(AcceptError::NotAllowed { - meta: n0_error::Meta::new(), - }); + return Err!(AcceptError::NotAllowed); } // To allow normal connection construction, await the connecting future & return From 7f59c66af59e1f5257c79da295fe9bfafeff4963 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 20 Oct 2025 23:46:54 +0200 Subject: [PATCH 18/58] fixup --- iroh/src/net_report/ip_mapped_addrs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iroh/src/net_report/ip_mapped_addrs.rs b/iroh/src/net_report/ip_mapped_addrs.rs index 9bf3792dc07..b3468f0ab74 100644 --- a/iroh/src/net_report/ip_mapped_addrs.rs +++ b/iroh/src/net_report/ip_mapped_addrs.rs @@ -7,7 +7,7 @@ use std::{ }, }; -use n0_error::{Err, Error, add_meta, e}; +use n0_error::{Err, Error, add_meta}; /// Can occur when converting a [`SocketAddr`] to an [`IpMappedAddr`] #[add_meta] From 587c5c61e6ca591f694be6a3c5fe519c56769303 Mon Sep 17 00:00:00 2001 From: Frando Date: Tue, 21 Oct 2025 09:15:10 +0200 Subject: [PATCH 19/58] fixup --- iroh/tests/integration.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iroh/tests/integration.rs b/iroh/tests/integration.rs index 7b3c98f86bc..27ef7bc6431 100644 --- a/iroh/tests/integration.rs +++ b/iroh/tests/integration.rs @@ -52,7 +52,7 @@ async fn simple_endpoint_id_based_connection_transfer() -> Result { tracing::info!("waiting for server to go online"); time::timeout(Duration::from_secs(12), server.online()) .await - .context("server endpoint took too long to get online")?; + .std_context("server endpoint took too long to get online")?; // Make the server respond to requests with an echo task::spawn({ From 35fa204c606ba8db51363e31edf26055258b3894 Mon Sep 17 00:00:00 2001 From: Frando Date: Tue, 21 Oct 2025 09:35:16 +0200 Subject: [PATCH 20/58] fixup --- Cargo.lock | 18 ++- Cargo.toml | 3 + iroh-dns-server/examples/resolve.rs | 4 +- iroh-dns-server/src/config.rs | 5 +- iroh-dns-server/src/dns/node_authority.rs | 6 +- iroh-dns-server/src/http.rs | 4 +- iroh-dns-server/src/lib.rs | 13 +- iroh-dns-server/src/store/signed_packets.rs | 146 ++++++++++---------- iroh/src/endpoint.rs | 4 +- iroh/src/lib.rs | 18 +-- 10 files changed, 110 insertions(+), 111 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4ad097f6366..e9e379bba13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1980,7 +1980,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.0", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -2399,29 +2399,27 @@ dependencies = [ [[package]] name = "iroh-metrics" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090161e84532a0cb78ab13e70abb882b769ec67cf5a2d2dcea39bd002e1f7172" +version = "0.36.2" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#5242e5cde624bb37758d85cf0d11f5cf16fb5b4f" dependencies = [ "http-body-util", "hyper", "hyper-util", "iroh-metrics-derive", "itoa", + "n0-error", "postcard", "reqwest", "ryu", "serde", - "snafu", "tokio", "tracing", ] [[package]] name = "iroh-metrics-derive" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a39de3779d200dadde3a27b9fbdb34389a2af1b85ea445afca47bf4d7672573" +version = "0.3.1" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#5242e5cde624bb37758d85cf0d11f5cf16fb5b4f" dependencies = [ "heck", "proc-macro2", @@ -3701,7 +3699,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.6.0", + "socket2 0.5.10", "thiserror 2.0.17", "tokio", "tracing", @@ -3738,7 +3736,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.0", + "socket2 0.5.10", "tracing", "windows-sys 0.60.2", ] diff --git a/Cargo.toml b/Cargo.toml index 0d0681861f5..7332475992e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,3 +40,6 @@ unexpected_cfgs = { level = "warn", check-cfg = ["cfg(iroh_docsrs)", "cfg(iroh_l [workspace.lints.clippy] unused-async = "warn" + +[patch.crates-io] +iroh-metrics = { git = "https://github.com/n0-computer/iroh-metrics", branch = "Frando/n0-error" } diff --git a/iroh-dns-server/examples/resolve.rs b/iroh-dns-server/examples/resolve.rs index 579f0a49a35..83e0ee8f654 100644 --- a/iroh-dns-server/examples/resolve.rs +++ b/iroh-dns-server/examples/resolve.rs @@ -4,7 +4,7 @@ use iroh::{ discovery::dns::{N0_DNS_ENDPOINT_ORIGIN_PROD, N0_DNS_ENDPOINT_ORIGIN_STAGING}, dns::DnsResolver, }; -use n0_error::{Result, StdResultExt, format_err}; +use n0_error::{Result, StackResultExt, StdResultExt}; const DEV_DNS_SERVER: &str = "127.0.0.1:5300"; const DEV_DNS_ORIGIN_DOMAIN: &str = "irohdns.example"; @@ -51,7 +51,7 @@ async fn main() -> Result<()> { .await .e()? .next() - .ok_or_else(|| format_err!("failed to resolve DNS server address"))?; + .context("failed to resolve DNS server address")?; DnsResolver::with_nameserver(addr) } else { match args.env { diff --git a/iroh-dns-server/src/config.rs b/iroh-dns-server/src/config.rs index 261317f0a5b..d1770f6e4a4 100644 --- a/iroh-dns-server/src/config.rs +++ b/iroh-dns-server/src/config.rs @@ -162,10 +162,7 @@ impl Config { ); let s = tokio::fs::read_to_string(path.as_ref()) .await - .std_context(format!( - "failed to read {}", - path.as_ref().to_string_lossy() - ))?; + .with_std_context(|_| format!("failed to read {}", path.as_ref().to_string_lossy()))?; let config: Config = toml::from_str(&s).e()?; Ok(config) } diff --git a/iroh-dns-server/src/dns/node_authority.rs b/iroh-dns-server/src/dns/node_authority.rs index 9f948a09e62..88093c1ef5e 100644 --- a/iroh-dns-server/src/dns/node_authority.rs +++ b/iroh-dns-server/src/dns/node_authority.rs @@ -13,7 +13,7 @@ use hickory_server::{ server::RequestInfo, store::in_memory::InMemoryAuthority, }; -use n0_error::{Result, StdResultExt, whatever}; +use n0_error::{Result, StackResultExt, StdResultExt, whatever}; use tracing::{debug, trace}; use crate::{ @@ -190,8 +190,8 @@ fn parse_name_as_pkarr_with_origin( let mut labels_without_origin = labels.skip(origin.num_labels() as usize); let pkey_label = labels_without_origin.next().expect("length checked above"); let pkey_str = std::str::from_utf8(pkey_label).e()?; - let pkey = PublicKeyBytes::from_z32(pkey_str) - .std_context("not a valid pkarr name: invalid pubkey")?; + let pkey = + PublicKeyBytes::from_z32(pkey_str).context("not a valid pkarr name: invalid pubkey")?; let remaining_name = Name::from_labels(labels_without_origin.rev()).e()?; return Ok((remaining_name, pkey, origin.clone())); } diff --git a/iroh-dns-server/src/http.rs b/iroh-dns-server/src/http.rs index add5625776f..060f2e0f0e7 100644 --- a/iroh-dns-server/src/http.rs +++ b/iroh-dns-server/src/http.rs @@ -111,7 +111,9 @@ impl HttpServer { .join(config.cert_mode.to_string()); tokio::fs::create_dir_all(&cache_path) .await - .std_context(format!("failed to create cert cache dir at {cache_path:?}"))?; + .with_std_context(|_| { + format!("failed to create cert cache dir at {cache_path:?}") + })?; config .cert_mode .build( diff --git a/iroh-dns-server/src/lib.rs b/iroh-dns-server/src/lib.rs index af2e5e38287..beb02797a9b 100644 --- a/iroh-dns-server/src/lib.rs +++ b/iroh-dns-server/src/lib.rs @@ -200,7 +200,7 @@ mod tests { max_batch_time: Duration::from_millis(100), ..Default::default() }; - let store = ZoneStore::in_memory(options, Default::default()).e()?; + let store = ZoneStore::in_memory(options, Default::default())?; // create a signed packet let signed_packet = random_signed_packet(&mut rng)?; @@ -208,8 +208,7 @@ mod tests { store .insert(signed_packet, PacketSource::PkarrPublish) - .await - .e()?; + .await?; tokio::time::sleep(Duration::from_secs(1)).await; for _ in 0..10 { @@ -234,8 +233,7 @@ mod tests { // spawn our server with mainline support let (server, nameserver, _http_url) = Server::spawn_for_tests_with_options(Some(BootstrapOption::Custom(bootstrap)), None) - .await - .e()?; + .await?; let origin = "irohdns.example."; @@ -256,10 +254,7 @@ mod tests { // resolve via DNS from our server, which will lookup from our DHT let resolver = test_resolver(nameserver); - let res = resolver - .lookup_endpoint_by_id(&endpoint_id, origin) - .await - .e()?; + let res = resolver.lookup_endpoint_by_id(&endpoint_id, origin).await?; assert_eq!(res.endpoint_id, endpoint_id); assert_eq!(res.relay_url(), Some(&relay_url)); diff --git a/iroh-dns-server/src/store/signed_packets.rs b/iroh-dns-server/src/store/signed_packets.rs index 13d702f7979..20c9590ad9e 100644 --- a/iroh-dns-server/src/store/signed_packets.rs +++ b/iroh-dns-server/src/store/signed_packets.rs @@ -128,30 +128,31 @@ impl Actor { tokio::pin!(timeout); for _ in 0..self.options.max_batch_size { tokio::select! { - _ = self.cancel.cancelled() => { - drop(tables); - transaction.commit().e()?; - return Ok(()); - } - _ = &mut timeout => break, - Some(msg) = self.recv.recv() => { - match msg { - Message::Get { key, res } => { - match get_packet(&tables.signed_packets, &key) { - Ok(packet) => { - trace!("get {key}: {}", packet.is_some()); - res.send(packet).ok(); - }, - Err(err) => { - warn!("get {key} failed: {err:#}"); - return Err(err).std_context(format!("get packet for {key} failed")) - } + _ = self.cancel.cancelled() => { + drop(tables); + transaction.commit().e()?; + return Ok(()); } - } - Message::Upsert { packet, res } => { - let key = PublicKeyBytes::from_signed_packet(&packet); - trace!("upsert {}", key); - let replaced = match get_packet(&tables.signed_packets, &key)? { Some(existing) => { + _ = &mut timeout => break, + Some(msg) = self.recv.recv() => { + match msg { + Message::Get { key, res } => { + match get_packet(&tables.signed_packets, &key) { + Ok(packet) => { + trace!("get {key}: {}", packet.is_some()); + res.send(packet).ok(); + }, + Err(err) => { + warn!("get {key} failed: {err:#}"); + return Err(err).std_context(format!("get packet for {key} failed")) + } + } + } + Message::Upsert { packet, res } => { + let key = PublicKeyBytes::from_signed_packet(&packet); + trace!("upsert {}", key); + let replaced = match get_packet(&tables.signed_packets, &key)? { + Some(existing) => { if existing.more_recent_than(&packet) { res.send(false).ok(); continue; @@ -162,56 +163,57 @@ impl Actor { } } _ => { false - }}; - let value = packet.serialize(); - tables.signed_packets - .insert(key.as_bytes(), &value[..]).e()?; - tables.update_time - .insert(&packet.timestamp().to_bytes(), key.as_bytes()).e()?; - if replaced { - self.metrics.store_packets_updated.inc(); - } else { - self.metrics.store_packets_inserted.inc(); } - res.send(true).ok(); - } - Message::Remove { key, res } => { - trace!("remove {}", key); - let updated = match tables.signed_packets.remove(key.as_bytes()).e()? { Some(row) => { - let packet = SignedPacket::deserialize(row.value()).e()?; - tables.update_time.remove(&packet.timestamp().to_bytes(), key.as_bytes()).e()?; - self.metrics.store_packets_removed.inc(); - true - } _ => { - false - }}; - res.send(updated).ok(); - } - Message::Snapshot { res } => { - trace!("snapshot"); - res.send(Snapshot::new(&self.db)?).ok(); + }; + let value = packet.serialize(); + tables.signed_packets + .insert(key.as_bytes(), &value[..]).e()?; + tables.update_time + .insert(&packet.timestamp().to_bytes(), key.as_bytes()).e()?; + if replaced { + self.metrics.store_packets_updated.inc(); + } else { + self.metrics.store_packets_inserted.inc(); } - Message::CheckExpired { key, time } => { - trace!("check expired {} at {}", key, fmt_time(time)); - match get_packet(&tables.signed_packets, &key)? { Some(packet) => { - let expired = Timestamp::now() - expiry_us; - if packet.timestamp() < expired { - tables.update_time.remove(&time.to_bytes(), key.as_bytes()).e()?; - let _ = tables.signed_packets.remove(key.as_bytes()).e()?; - self.metrics.store_packets_expired.inc(); - debug!("removed expired packet {key}"); - } else { - debug!("packet {key} is no longer expired, removing obsolete expiry entry"); - tables.update_time.remove(&time.to_bytes(), key.as_bytes()).e()?; - } - } _ => { - debug!("expired packet {key} not found, remove from expiry table"); + res.send(true).ok(); + } + Message::Remove { key, res } => { + trace!("remove {}", key); + let updated = match tables.signed_packets.remove(key.as_bytes()).e()? { Some(row) => { + let packet = SignedPacket::deserialize(row.value()).e()?; + tables.update_time.remove(&packet.timestamp().to_bytes(), key.as_bytes()).e()?; + self.metrics.store_packets_removed.inc(); + true + } _ => { + false + }}; + res.send(updated).ok(); + } + Message::Snapshot { res } => { + trace!("snapshot"); + res.send(Snapshot::new(&self.db)?).ok(); + } + Message::CheckExpired { key, time } => { + trace!("check expired {} at {}", key, fmt_time(time)); + match get_packet(&tables.signed_packets, &key)? { Some(packet) => { + let expired = Timestamp::now() - expiry_us; + if packet.timestamp() < expired { tables.update_time.remove(&time.to_bytes(), key.as_bytes()).e()?; - }} - } + let _ = tables.signed_packets.remove(key.as_bytes()).e()?; + self.metrics.store_packets_expired.inc(); + debug!("removed expired packet {key}"); + } else { + debug!("packet {key} is no longer expired, removing obsolete expiry entry"); + tables.update_time.remove(&time.to_bytes(), key.as_bytes()).e()?; + } + } _ => { + debug!("expired packet {key} not found, remove from expiry table"); + tables.update_time.remove(&time.to_bytes(), key.as_bytes()).e()?; + }} } } } + } } drop(tables); transaction.commit().e()?; @@ -265,10 +267,12 @@ impl SignedPacketStore { let path = path.as_ref(); info!("loading packet database from {}", path.to_string_lossy()); if let Some(parent) = path.parent() { - std::fs::create_dir_all(parent).std_context(format!( - "failed to create database directory at {}", - path.to_string_lossy() - ))?; + std::fs::create_dir_all(parent).with_std_context(|_| { + format!( + "failed to create database directory at {}", + path.to_string_lossy() + ) + })?; } let mut db = Database::builder() .create(path) diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 53ff826302b..ee4fbc0ad96 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -1087,7 +1087,7 @@ impl Endpoint { /// # use std::{sync::{Arc, RwLock}, time::Duration}; /// # use iroh_metrics::{Registry, MetricsSource}; /// # use iroh::endpoint::Endpoint; - /// # use n0_error::StackResultExt; + /// # use n0_error::{StackResultExt, StdResultExt}; /// # async fn wrapper() -> n0_error::Result<()> { /// // Create a registry, wrapped in a read-write lock so that we can register and serve /// // the metrics independently. @@ -1109,7 +1109,7 @@ impl Endpoint { /// tokio::time::sleep(Duration::from_millis(500)); /// let res = reqwest::get("http://localhost:9100/metrics") /// .await - /// .context("get")? + /// .std_context("get")? /// .text() /// .await /// .context("text")?; diff --git a/iroh/src/lib.rs b/iroh/src/lib.rs index 82ad318a0ff..f8cbdf26da6 100644 --- a/iroh/src/lib.rs +++ b/iroh/src/lib.rs @@ -9,16 +9,16 @@ //! //! ```no_run //! # use iroh::{Endpoint, EndpointAddr}; -//! # use n0_error::StackResultExt; +//! # use n0_error::{StackResultExt, StdResultExt}; //! # async fn wrapper() -> n0_error::Result<()> { //! let addr: EndpointAddr = todo!(); //! let ep = Endpoint::bind().await?; //! let conn = ep.connect(addr, b"my-alpn").await?; -//! let mut send_stream = conn.open_uni().await.context("unable to open uni")?; +//! let mut send_stream = conn.open_uni().await.std_context("unable to open uni")?; //! send_stream //! .write_all(b"msg") //! .await -//! .context("unable to write all")?; +//! .std_context("unable to write all")?; //! # Ok(()) //! # } //! ``` @@ -27,7 +27,7 @@ //! //! ```no_run //! # use iroh::{Endpoint, EndpointAddr}; -//! # use n0_error::StackResultExt; +//! # use n0_error::{StackResultExt, StdResultExt}; //! # async fn wrapper() -> n0_error::Result<()> { //! let ep = Endpoint::builder() //! .alpns(vec![b"my-alpn".to_vec()]) @@ -39,7 +39,7 @@ //! .context("accept error")? //! .await //! .context("connecting error")?; -//! let mut recv_stream = conn.accept_uni().await.context("unable to open uni")?; +//! let mut recv_stream = conn.accept_uni().await.std_context("unable to open uni")?; //! let mut buf = [0u8; 3]; //! recv_stream //! .read_exact(&mut buf) @@ -213,10 +213,10 @@ //! .context("no incoming connection")? //! .await //! .context("accept conn")?; -//! let (mut send_stream, mut recv_stream) = conn.accept_bi().await.context("accept stream")?; -//! let _msg = recv_stream.read_to_end(10).await.context("read")?; -//! send_stream.write_all(b"world").await.context("write")?; -//! send_stream.finish().context("finish")?; +//! let (mut send_stream, mut recv_stream) = conn.accept_bi().await.std_context("accept stream")?; +//! let _msg = recv_stream.read_to_end(10).await.std_context("read")?; +//! send_stream.write_all(b"world").await.std_context("write")?; +//! send_stream.finish().std_context("finish")?; //! //! // Wait for the client to close the connection and gracefully close the endpoint. //! conn.closed().await; From 383ed048a41c533bd07972cf9796de3198c97690 Mon Sep 17 00:00:00 2001 From: Frando Date: Tue, 21 Oct 2025 09:35:57 +0200 Subject: [PATCH 21/58] fixup --- iroh/examples/transfer.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/iroh/examples/transfer.rs b/iroh/examples/transfer.rs index db3477067a4..154d43a1111 100644 --- a/iroh/examples/transfer.rs +++ b/iroh/examples/transfer.rs @@ -202,7 +202,7 @@ impl EndpointArgs { } #[cfg(not(feature = "test-utils"))] { - whatever!( + n0_error::whatever!( "Must have the `test-utils` feature enabled when using the `--env=dev` flag" ) } @@ -238,7 +238,7 @@ impl EndpointArgs { } #[cfg(not(feature = "test-utils"))] { - whatever!( + n0_error::whatever!( "Must have the `discovery-local-network` enabled when using the `--mdns` flag" ); } @@ -269,7 +269,7 @@ impl EndpointArgs { } #[cfg(not(feature = "discovery-local-network"))] { - whatever!( + n0_error::whatever!( "Must have the `test-utils` feature enabled when using the `--relay-only` flag" ); } From 7e9b9975483d0f11eebe10a7bbf4f607bc83cb0e Mon Sep 17 00:00:00 2001 From: Frando Date: Tue, 21 Oct 2025 09:36:13 +0200 Subject: [PATCH 22/58] fixup --- iroh/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/iroh/src/lib.rs b/iroh/src/lib.rs index f8cbdf26da6..442e3cf1923 100644 --- a/iroh/src/lib.rs +++ b/iroh/src/lib.rs @@ -213,7 +213,8 @@ //! .context("no incoming connection")? //! .await //! .context("accept conn")?; -//! let (mut send_stream, mut recv_stream) = conn.accept_bi().await.std_context("accept stream")?; +//! let (mut send_stream, mut recv_stream) = +//! conn.accept_bi().await.std_context("accept stream")?; //! let _msg = recv_stream.read_to_end(10).await.std_context("read")?; //! send_stream.write_all(b"world").await.std_context("write")?; //! send_stream.finish().std_context("finish")?; From 6969f68d8cdcfef0e511674e1c096e11b5ea99a8 Mon Sep 17 00:00:00 2001 From: Frando Date: Tue, 21 Oct 2025 09:41:36 +0200 Subject: [PATCH 23/58] fixup --- iroh/src/endpoint.rs | 2 +- iroh/src/lib.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index ee4fbc0ad96..bfe287b155f 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -1112,7 +1112,7 @@ impl Endpoint { /// .std_context("get")? /// .text() /// .await - /// .context("text")?; + /// .std_context("text")?; /// /// assert!(res.contains(r#"TYPE magicsock_recv_datagrams counter"#)); /// assert!(res.contains(r#"magicsock_recv_datagrams_total 0"#)); diff --git a/iroh/src/lib.rs b/iroh/src/lib.rs index 442e3cf1923..09484f16028 100644 --- a/iroh/src/lib.rs +++ b/iroh/src/lib.rs @@ -38,7 +38,7 @@ //! .await //! .context("accept error")? //! .await -//! .context("connecting error")?; +//! .std_context("connecting error")?; //! let mut recv_stream = conn.accept_uni().await.std_context("unable to open uni")?; //! let mut buf = [0u8; 3]; //! recv_stream @@ -179,10 +179,10 @@ //! //! // Establish a QUIC connection, open a bi-directional stream, exchange messages. //! let conn = ep.connect(addr, b"hello-world").await?; -//! let (mut send_stream, mut recv_stream) = conn.open_bi().await.context("open bi")?; -//! send_stream.write_all(b"hello").await.context("write")?; -//! send_stream.finish().context("finish")?; -//! let _msg = recv_stream.read_to_end(10).await.context("read")?; +//! let (mut send_stream, mut recv_stream) = conn.open_bi().await.std_context("open bi")?; +//! send_stream.write_all(b"hello").await.std_context("write")?; +//! send_stream.finish().std_context("finish")?; +//! let _msg = recv_stream.read_to_end(10).await.std_context("read")?; //! //! // Gracefully close the connection and endpoint. //! conn.close(1u8.into(), b"done"); @@ -212,7 +212,7 @@ //! .await //! .context("no incoming connection")? //! .await -//! .context("accept conn")?; +//! .std_context("accept conn")?; //! let (mut send_stream, mut recv_stream) = //! conn.accept_bi().await.std_context("accept stream")?; //! let _msg = recv_stream.read_to_end(10).await.std_context("read")?; From ea9b541711e73514808f879ab4cebea55c65b6d4 Mon Sep 17 00:00:00 2001 From: Frando Date: Tue, 21 Oct 2025 09:48:14 +0200 Subject: [PATCH 24/58] fixup --- iroh/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/iroh/src/lib.rs b/iroh/src/lib.rs index 09484f16028..919e380f675 100644 --- a/iroh/src/lib.rs +++ b/iroh/src/lib.rs @@ -44,7 +44,7 @@ //! recv_stream //! .read_exact(&mut buf) //! .await -//! .context("unable to read")?; +//! .std_context("unable to read")?; //! # Ok(()) //! # } //! ``` @@ -171,7 +171,7 @@ //! //! ```no_run //! use iroh::{Endpoint, EndpointAddr}; -//! use n0_error::{Result, StackResultExt}; +//! use n0_error::{Result, StackResultExt, StdResultExt}; //! //! async fn connect(addr: EndpointAddr) -> Result<()> { //! // The Endpoint is the central object that manages an iroh node. @@ -196,7 +196,7 @@ //! //! ```no_run //! use iroh::{Endpoint, EndpointAddr}; -//! use n0_error::{Result, StackResultExt}; +//! use n0_error::{Result, StackResultExt, StdResultExt}; //! use n0_future::StreamExt; //! //! async fn accept() -> Result<()> { From 8c5694eff0a9c4c3d0807c4cbe1eb58595696289 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 27 Oct 2025 09:38:05 +0100 Subject: [PATCH 25/58] update n0-error --- Cargo.lock | 14 +++++++------- iroh-base/Cargo.toml | 2 +- iroh-dns-server/Cargo.toml | 2 +- iroh-relay/Cargo.toml | 2 +- iroh/Cargo.toml | 2 +- iroh/bench/Cargo.toml | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e9e379bba13..5ba3d28d5ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1980,7 +1980,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.0", "tokio", "tower-service", "tracing", @@ -2400,7 +2400,7 @@ dependencies = [ [[package]] name = "iroh-metrics" version = "0.36.2" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#5242e5cde624bb37758d85cf0d11f5cf16fb5b4f" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#a3f936680259bec8e07e50f1c76370aff7bacd97" dependencies = [ "http-body-util", "hyper", @@ -2419,7 +2419,7 @@ dependencies = [ [[package]] name = "iroh-metrics-derive" version = "0.3.1" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#5242e5cde624bb37758d85cf0d11f5cf16fb5b4f" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#a3f936680259bec8e07e50f1c76370aff7bacd97" dependencies = [ "heck", "proc-macro2", @@ -2803,7 +2803,7 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error#0070b103873f285627240e3c772fecec3f0b4528" +source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#6b46dafc04efe0d8a4b9bdd0889cae6c0890a72d" dependencies = [ "anyhow", "derive_more 2.0.1", @@ -2814,7 +2814,7 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error#0070b103873f285627240e3c772fecec3f0b4528" +source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#6b46dafc04efe0d8a4b9bdd0889cae6c0890a72d" dependencies = [ "darling", "heck", @@ -3699,7 +3699,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.5.10", + "socket2 0.6.0", "thiserror 2.0.17", "tokio", "tracing", @@ -3736,7 +3736,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.0", "tracing", "windows-sys 0.60.2", ] diff --git a/iroh-base/Cargo.toml b/iroh-base/Cargo.toml index 4ea900d4514..305bd44ba9b 100644 --- a/iroh-base/Cargo.toml +++ b/iroh-base/Cargo.toml @@ -23,7 +23,7 @@ url = { version = "2.5.3", features = ["serde"], optional = true } postcard = { version = "1", default-features = false, features = ["alloc", "use-std", "experimental-derive"], optional = true } rand_core = { version = "0.9.3", optional = true } serde = { version = "1", features = ["derive", "rc"] } -n0-error = { git = "https://github.com/n0-computer/n0-error" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/dev" } zeroize = { version = "1.8.2", optional = true, features = ["derive"] } zeroize_derive = { version = "1.4.2", optional = true } # needed for minimal versions diff --git a/iroh-dns-server/Cargo.toml b/iroh-dns-server/Cargo.toml index 5eee90e8a01..d0a24acca12 100644 --- a/iroh-dns-server/Cargo.toml +++ b/iroh-dns-server/Cargo.toml @@ -39,7 +39,7 @@ rustls = { version = "0.23.33", default-features = false, features = ["ring"] } rustls-pemfile = { version = "2.1" } serde = { version = "1", features = ["derive"] } struct_iterable = "0.1.1" -n0-error = { git = "https://github.com/n0-computer/n0-error" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/dev" } strum = { version = "0.27", features = ["derive"] } tokio = { version = "1", features = ["full"] } tokio-rustls = { version = "0.26", default-features = false, features = [ diff --git a/iroh-relay/Cargo.toml b/iroh-relay/Cargo.toml index 5dc241c073f..a90851a0a30 100644 --- a/iroh-relay/Cargo.toml +++ b/iroh-relay/Cargo.toml @@ -71,7 +71,7 @@ webpki_types = { package = "rustls-pki-types", version = "1.12" } data-encoding = "2.6.0" lru = "0.16" z32 = "1.0.3" -n0-error = { git = "https://github.com/n0-computer/n0-error" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/dev" } # server feature clap = { version = "4", features = ["derive"], optional = true } diff --git a/iroh/Cargo.toml b/iroh/Cargo.toml index 2cea5b25a98..a6b5caddb52 100644 --- a/iroh/Cargo.toml +++ b/iroh/Cargo.toml @@ -40,7 +40,7 @@ http = "1" iroh-base = { version = "0.93.2", default-features = false, features = ["key", "relay"], path = "../iroh-base" } iroh-relay = { version = "0.93", path = "../iroh-relay", default-features = false } n0-future = "0.3.0" -n0-error = { git = "https://github.com/n0-computer/n0-error" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/dev" } n0-watcher = "0.3" nested_enum_utils = "0.2.1" netwatch = { version = "0.10" } diff --git a/iroh/bench/Cargo.toml b/iroh/bench/Cargo.toml index 34a7140e64f..b8a474b9741 100644 --- a/iroh/bench/Cargo.toml +++ b/iroh/bench/Cargo.toml @@ -11,7 +11,7 @@ hdrhistogram = { version = "7.2", default-features = false } iroh = { path = ".." } iroh-metrics = "0.36" n0-future = "0.3.0" -n0-error = { git = "https://github.com/n0-computer/n0-error" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/dev" } quinn = { package = "iroh-quinn", version = "0.14" } rand = "0.9.2" rcgen = "0.14" From ad783e383e15d2ae8d5242fbb550f00ba26d8c8b Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 27 Oct 2025 09:59:48 +0100 Subject: [PATCH 26/58] wip --- Cargo.lock | 4 ++-- iroh-base/src/key.rs | 16 +++++++--------- iroh-dns-server/src/dns/node_authority.rs | 8 ++++---- iroh-dns-server/src/http.rs | 4 ++-- iroh-dns-server/src/http/doh/response.rs | 8 ++++---- iroh-dns-server/src/http/tls.rs | 6 +++--- iroh-dns-server/src/store/signed_packets.rs | 2 +- iroh-relay/src/main.rs | 18 +++++++++--------- iroh-relay/src/server/client.rs | 4 ++-- iroh-relay/src/server/clients.rs | 4 ++-- iroh-relay/src/server/http_server.rs | 18 +++++++++--------- iroh/examples/0rtt.rs | 4 ++-- iroh/examples/transfer.rs | 6 +++--- iroh/src/discovery/mdns.rs | 4 ++-- iroh/src/endpoint.rs | 6 +++--- 15 files changed, 55 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5ba3d28d5ae..1016353e5f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2803,7 +2803,7 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#6b46dafc04efe0d8a4b9bdd0889cae6c0890a72d" +source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#74db31b779f2c1d6a748d3a76494d76792892564" dependencies = [ "anyhow", "derive_more 2.0.1", @@ -2814,7 +2814,7 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#6b46dafc04efe0d8a4b9bdd0889cae6c0890a72d" +source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#74db31b779f2c1d6a748d3a76494d76792892564" dependencies = [ "darling", "heck", diff --git a/iroh-base/src/key.rs b/iroh-base/src/key.rs index 691ec877c73..08c79861975 100644 --- a/iroh-base/src/key.rs +++ b/iroh-base/src/key.rs @@ -11,7 +11,7 @@ use std::{ use curve25519_dalek::edwards::CompressedEdwardsY; use ed25519_dalek::{SigningKey, VerifyingKey}; -use n0_error::{Err, Error, add_meta, e}; +use n0_error::{Error, add_meta, e}; use rand_core::CryptoRng; use serde::{Deserialize, Serialize}; @@ -127,7 +127,7 @@ impl PublicKey { pub fn verify(&self, message: &[u8], signature: &Signature) -> Result<(), SignatureError> { self.as_verifying_key() .verify_strict(message, &signature.0) - .map_err(|_| e!(SignatureError)) + .map_err(|_| SignatureError::new()) } /// Convert to a hex string limited to the first 5 bytes for a friendly string @@ -210,15 +210,13 @@ impl Display for PublicKey { pub enum KeyParsingError { /// Error when decoding. #[error(transparent)] - Decode { source: data_encoding::DecodeError }, + Decode(data_encoding::DecodeError), /// Error when decoding the public key. #[error(transparent)] - Key { - source: ed25519_dalek::SignatureError, - }, + Key(ed25519_dalek::SignatureError), /// The encoded information had the wrong length. #[display("invalid length")] - DecodeInvalidLength {}, + DecodeInvalidLength, } /// Deserialises the [`PublicKey`] from it's base32 encoding. @@ -380,14 +378,14 @@ fn decode_base32_hex(s: &str) -> Result<[u8; 32], KeyParsingError> { let input = s.to_ascii_uppercase(); let input = input.as_bytes(); if data_encoding::BASE32_NOPAD.decode_len(input.len())? != bytes.len() { - return Err!(KeyParsingError::DecodeInvalidLength); + return Err(e!(KeyParsingError::DecodeInvalidLength)); } data_encoding::BASE32_NOPAD.decode_mut(input, &mut bytes) }; match res { Ok(len) => { if len != PublicKey::LENGTH { - return Err!(KeyParsingError::DecodeInvalidLength); + return Err(e!(KeyParsingError::DecodeInvalidLength)); } } Err(partial) => return Err(partial.error.into()), diff --git a/iroh-dns-server/src/dns/node_authority.rs b/iroh-dns-server/src/dns/node_authority.rs index 88093c1ef5e..1beecda9527 100644 --- a/iroh-dns-server/src/dns/node_authority.rs +++ b/iroh-dns-server/src/dns/node_authority.rs @@ -13,7 +13,7 @@ use hickory_server::{ server::RequestInfo, store::in_memory::InMemoryAuthority, }; -use n0_error::{Result, StackResultExt, StdResultExt, whatever}; +use n0_error::{Result, StackResultExt, StdResultExt, bail}; use tracing::{debug, trace}; use crate::{ @@ -41,7 +41,7 @@ impl NodeAuthority { serial: u32, ) -> Result { if origins.is_empty() { - whatever!("at least one origin is required"); + bail!("at least one origin is required"); } let first_origin = LowerName::from(&origins[0]); Ok(Self { @@ -183,7 +183,7 @@ fn parse_name_as_pkarr_with_origin( continue; } if name.num_labels() < origin.num_labels() + 1 { - whatever!("not a valid pkarr name: missing pubkey"); + bail!("not a valid pkarr name: missing pubkey"); } trace!("parse {origin}"); let labels = name.iter().rev(); @@ -195,7 +195,7 @@ fn parse_name_as_pkarr_with_origin( let remaining_name = Name::from_labels(labels_without_origin.rev()).e()?; return Ok((remaining_name, pkey, origin.clone())); } - whatever!("name does not match any allowed origin"); + bail!("name does not match any allowed origin"); } fn err_refused(e: impl fmt::Debug) -> LookupError { diff --git a/iroh-dns-server/src/http.rs b/iroh-dns-server/src/http.rs index 060f2e0f0e7..1eaa654744c 100644 --- a/iroh-dns-server/src/http.rs +++ b/iroh-dns-server/src/http.rs @@ -14,7 +14,7 @@ use axum::{ response::IntoResponse, routing::get, }; -use n0_error::{Result, StdResultExt, whatever}; +use n0_error::{Result, StdResultExt, bail}; use serde::{Deserialize, Serialize}; use tokio::{net::TcpListener, task::JoinSet}; use tower_http::{ @@ -74,7 +74,7 @@ impl HttpServer { state: AppState, ) -> Result { if http_config.is_none() && https_config.is_none() { - whatever!("Either http or https config is required"); + bail!("Either http or https config is required"); } let app = create_app(state, &rate_limit_config); diff --git a/iroh-dns-server/src/http/doh/response.rs b/iroh-dns-server/src/http/doh/response.rs index ccd4624a729..482661c7dd4 100644 --- a/iroh-dns-server/src/http/doh/response.rs +++ b/iroh-dns-server/src/http/doh/response.rs @@ -4,7 +4,7 @@ // https://github.com/fission-codes/fission-server/blob/394de877fad021260c69fdb1edd7bb4b2f98108c/fission-core/src/dns.rs use hickory_server::proto; -use n0_error::{Result, whatever}; +use n0_error::{Result, bail}; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] @@ -48,15 +48,15 @@ impl DnsResponse { /// Create a new JSON response from a DNS message pub fn from_message(message: proto::op::Message) -> Result { if message.message_type() != proto::op::MessageType::Response { - whatever!("Expected message type to be response"); + bail!("Expected message type to be response"); } if message.query_count() != message.queries().len() as u16 { - whatever!("Query count mismatch"); + bail!("Query count mismatch"); } if message.answer_count() != message.answers().len() as u16 { - whatever!("Answer count mismatch"); + bail!("Answer count mismatch"); } let status: u32 = diff --git a/iroh-dns-server/src/http/tls.rs b/iroh-dns-server/src/http/tls.rs index 655b3f0675b..96b5125c6cc 100644 --- a/iroh-dns-server/src/http/tls.rs +++ b/iroh-dns-server/src/http/tls.rs @@ -9,7 +9,7 @@ use axum_server::{ accept::Accept, tls_rustls::{RustlsAcceptor, RustlsConfig}, }; -use n0_error::{Result, StdResultExt, whatever}; +use n0_error::{Result, StdResultExt, bail}; use n0_future::{FutureExt, future::Boxed as BoxFuture}; use serde::{Deserialize, Serialize}; use tokio::io::{AsyncRead, AsyncWrite}; @@ -86,7 +86,7 @@ impl TlsAcceptor { async fn manual(domains: Vec, dir: PathBuf) -> Result { let config = rustls::ServerConfig::builder().with_no_client_auth(); if domains.len() != 1 { - whatever!("Multiple domains in manual mode are not supported"); + bail!("Multiple domains in manual mode are not supported"); } let keyname = escape_hostname(&domains[0]); @@ -174,7 +174,7 @@ async fn load_secret_key( } } - whatever!( + bail!( "no keys found in {} (encrypted keys not supported)", filename.as_ref().display() ); diff --git a/iroh-dns-server/src/store/signed_packets.rs b/iroh-dns-server/src/store/signed_packets.rs index 20c9590ad9e..7c77867b607 100644 --- a/iroh-dns-server/src/store/signed_packets.rs +++ b/iroh-dns-server/src/store/signed_packets.rs @@ -391,7 +391,7 @@ async fn evict_task(send: mpsc::Sender, options: Options, cancel: Cance if let Err(cause) = evict_task_inner(send, options).await { error!("evict task failed: {:?}", cause); } - // when we are done for whatever reason we want to shut down the actor + // when we are done for bail reason we want to shut down the actor cancel.cancel(); }) .await; diff --git a/iroh-relay/src/main.rs b/iroh-relay/src/main.rs index 5c571786145..719af93d27d 100644 --- a/iroh-relay/src/main.rs +++ b/iroh-relay/src/main.rs @@ -19,7 +19,7 @@ use iroh_relay::{ }, server::{self as relay, ClientRateLimit, QuicConfig}, }; -use n0_error::{AnyError as Error, Result, StdResultExt, whatever}; +use n0_error::{AnyError as Error, Result, StdResultExt, bail}; use n0_future::FutureExt; use serde::{Deserialize, Serialize}; use tokio_rustls_acme::{AcmeConfig, caches::DirCache}; @@ -98,7 +98,7 @@ fn load_secret_key( } } - whatever!( + bail!( "no keys found in {} (encrypted keys not supported)", filename.display() ); @@ -299,10 +299,10 @@ async fn http_access_check_inner( } Ok(res) if res.status() == StatusCode::OK => match res.text().await { Ok(text) if text == "true" => Ok(()), - Ok(_) => whatever!("Invalid response text (must be 'true')"), + Ok(_) => bail!("Invalid response text (must be 'true')"), Err(err) => Err(err).std_context("Failed to read response"), }, - Ok(res) => whatever!("Received invalid status code ({})", res.status()), + Ok(res) => bail!("Received invalid status code ({})", res.status()), } } @@ -507,7 +507,7 @@ impl Config { async fn read_from_file(path: impl AsRef) -> Result { if !path.as_ref().is_file() { - whatever!("config-path must be a file"); + bail!("config-path must be a file"); } let config_ser = tokio::fs::read_to_string(&path) .await @@ -526,7 +526,7 @@ async fn main() -> Result<()> { let cli = Cli::parse(); let mut cfg = Config::load(&cli).await?; if cfg.enable_quic_addr_discovery && cfg.tls.is_none() { - whatever!("TLS must be configured in order to spawn a QUIC endpoint"); + bail!("TLS must be configured in order to spawn a QUIC endpoint"); } if cli.dev { // When in `--dev` mode, do not use https, even when tls is configured. @@ -538,7 +538,7 @@ async fn main() -> Result<()> { } } if cfg.tls.is_none() && cfg.enable_quic_addr_discovery { - whatever!("If QUIC address discovery is enabled, TLS must also be configured"); + bail!("If QUIC address discovery is enabled, TLS must also be configured"); }; let relay_config = build_relay_config(cfg).await?; debug!("{relay_config:#?}"); @@ -664,7 +664,7 @@ async fn build_relay_config(cfg: Config) -> Result Result { if rx.bytes_per_second.is_none() && rx.max_burst_bytes.is_some() { - whatever!("bytes_per_seconds must be specified to enable the rate-limiter"); + bail!("bytes_per_seconds must be specified to enable the rate-limiter"); } match rx.bytes_per_second { Some(bps) => Some(ClientRateLimit { diff --git a/iroh-relay/src/server/client.rs b/iroh-relay/src/server/client.rs index 1cabaac0eb2..106cc5795cb 100644 --- a/iroh-relay/src/server/client.rs +++ b/iroh-relay/src/server/client.rs @@ -559,7 +559,7 @@ mod tests { match stream.next().await { Some(Ok(frame)) => { if frame_type != frame.typ() { - n0_error::whatever!( + n0_error::bail!( "Unexpected frame, got {:?}, but expected {:?}", frame.typ(), frame_type @@ -568,7 +568,7 @@ mod tests { Ok(frame) } Some(Err(err)) => Err(err).e(), - None => n0_error::whatever!("Unexpected EOF, expected frame {frame_type:?}"), + None => n0_error::bail!("Unexpected EOF, expected frame {frame_type:?}"), } } diff --git a/iroh-relay/src/server/clients.rs b/iroh-relay/src/server/clients.rs index ffbc9651f11..8dd1e041345 100644 --- a/iroh-relay/src/server/clients.rs +++ b/iroh-relay/src/server/clients.rs @@ -215,7 +215,7 @@ mod tests { match stream.next().await { Some(Ok(frame)) => { if frame_type != frame.typ() { - n0_error::whatever!( + n0_error::bail!( "Unexpected frame, got {:?}, but expected {:?}", frame.typ(), frame_type @@ -224,7 +224,7 @@ mod tests { Ok(frame) } Some(Err(err)) => Err(err).e(), - None => n0_error::whatever!("Unexpected EOF, expected frame {frame_type:?}"), + None => n0_error::bail!("Unexpected EOF, expected frame {frame_type:?}"), } } diff --git a/iroh-relay/src/server/http_server.rs b/iroh-relay/src/server/http_server.rs index 2b8370a1b5d..4f9e37b1c2e 100644 --- a/iroh-relay/src/server/http_server.rs +++ b/iroh-relay/src/server/http_server.rs @@ -858,7 +858,7 @@ mod tests { use std::sync::Arc; use iroh_base::{PublicKey, SecretKey}; - use n0_error::{Result, StdResultExt, whatever}; + use n0_error::{Result, StdResultExt, bail}; use n0_future::{SinkExt, StreamExt}; use rand::SeedableRng; use reqwest::Url; @@ -917,7 +917,7 @@ mod tests { let addr = if let std::net::IpAddr::V4(ipv4_addr) = addr.ip() { ipv4_addr } else { - whatever!("cannot get ipv4 addr from socket addr {addr:?}"); + bail!("cannot get ipv4 addr from socket addr {addr:?}"); }; info!("addr: {addr}:{port}"); @@ -1038,7 +1038,7 @@ mod tests { let addr = if let std::net::IpAddr::V4(ipv4_addr) = addr.ip() { ipv4_addr } else { - whatever!("cannot get ipv4 addr from socket addr {addr:?}"); + bail!("cannot get ipv4 addr from socket addr {addr:?}"); }; info!("Relay listening on: {addr}:{port}"); @@ -1158,7 +1158,7 @@ mod tests { assert_eq!(msg, datagrams); } msg => { - whatever!("expected ReceivedDatagrams msg, got {msg:?}"); + bail!("expected ReceivedDatagrams msg, got {msg:?}"); } } @@ -1179,7 +1179,7 @@ mod tests { assert_eq!(msg, datagrams); } msg => { - whatever!("expected ReceivedDatagrams msg, got {msg:?}"); + bail!("expected ReceivedDatagrams msg, got {msg:?}"); } } @@ -1258,7 +1258,7 @@ mod tests { assert_eq!(msg, datagrams); } msg => { - whatever!("expected ReceivedDatagrams msg, got {msg:?}"); + bail!("expected ReceivedDatagrams msg, got {msg:?}"); } } @@ -1279,7 +1279,7 @@ mod tests { assert_eq!(msg, datagrams); } msg => { - whatever!("expected ReceivedDatagrams msg, got {msg:?}"); + bail!("expected ReceivedDatagrams msg, got {msg:?}"); } } @@ -1310,7 +1310,7 @@ mod tests { assert_eq!(msg, datagrams); } msg => { - whatever!("expected ReceivedDatagrams msg, got {msg:?}"); + bail!("expected ReceivedDatagrams msg, got {msg:?}"); } } @@ -1331,7 +1331,7 @@ mod tests { assert_eq!(msg, datagrams); } msg => { - whatever!("expected ReceivedDatagrams msg, got {msg:?}"); + bail!("expected ReceivedDatagrams msg, got {msg:?}"); } } diff --git a/iroh/examples/0rtt.rs b/iroh/examples/0rtt.rs index b433a0cbb7d..ae15b16b2ec 100644 --- a/iroh/examples/0rtt.rs +++ b/iroh/examples/0rtt.rs @@ -7,7 +7,7 @@ use iroh::{ endpoint::{Connecting, Connection}, }; use iroh_base::ticket::EndpointTicket; -use n0_error::{Result, StackResultExt, StdResultExt, whatever}; +use n0_error::{Result, StackResultExt, StdResultExt, bail}; use n0_future::{StreamExt, future}; use n0_watcher::Watcher; use tracing::{info, trace}; @@ -142,7 +142,7 @@ async fn accept(_args: Args) -> Result<()> { let mut addrs = endpoint.watch_addr().stream(); let addr = loop { let Some(addr) = addrs.next().await else { - whatever!("Address stream closed"); + bail!("Address stream closed"); }; if !addr.direct_addresses.is_empty() { break addr; diff --git a/iroh/examples/transfer.rs b/iroh/examples/transfer.rs index 154d43a1111..66e57817f82 100644 --- a/iroh/examples/transfer.rs +++ b/iroh/examples/transfer.rs @@ -202,7 +202,7 @@ impl EndpointArgs { } #[cfg(not(feature = "test-utils"))] { - n0_error::whatever!( + n0_error::bail!( "Must have the `test-utils` feature enabled when using the `--env=dev` flag" ) } @@ -238,7 +238,7 @@ impl EndpointArgs { } #[cfg(not(feature = "test-utils"))] { - n0_error::whatever!( + n0_error::bail!( "Must have the `discovery-local-network` enabled when using the `--mdns` flag" ); } @@ -269,7 +269,7 @@ impl EndpointArgs { } #[cfg(not(feature = "discovery-local-network"))] { - n0_error::whatever!( + n0_error::bail!( "Must have the `test-utils` feature enabled when using the `--relay-only` flag" ); } diff --git a/iroh/src/discovery/mdns.rs b/iroh/src/discovery/mdns.rs index b92a828c499..38179831f9d 100644 --- a/iroh/src/discovery/mdns.rs +++ b/iroh/src/discovery/mdns.rs @@ -544,7 +544,7 @@ mod tests { /// tests) mod run_in_isolation { use iroh_base::SecretKey; - use n0_error::{AnyError as Error, Result, StdResultExt, whatever}; + use n0_error::{AnyError as Error, Result, StdResultExt, bail}; use n0_future::StreamExt; use rand::{CryptoRng, SeedableRng}; use tracing_test::traced_test; @@ -705,7 +705,7 @@ mod tests { got_ids.insert((endpoint_info.endpoint_id, data)); } } else { - whatever!( + bail!( "no more events, only got {} ids, expected {num_endpoints}\n", got_ids.len() ); diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index bfe287b155f..64748d7a278 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -2376,7 +2376,7 @@ mod tests { let server = server.clone(); async move { let Some(conn) = server.accept().await else { - n0_error::whatever!("Expected an incoming connection"); + n0_error::bail!("Expected an incoming connection"); }; let conn = conn.await.e()?; let (mut send, mut recv) = conn.accept_bi().await.e()?; @@ -2427,7 +2427,7 @@ mod tests { for i in 0..2 { println!("accept: round {i}"); let Some(conn) = server.accept().await else { - n0_error::whatever!("Expected an incoming connection"); + n0_error::bail!("Expected an incoming connection"); }; let conn = conn.await.e()?; let (mut send, mut recv) = conn.accept_bi().await.e()?; @@ -2646,7 +2646,7 @@ mod tests { return Ok(()); } } - n0_error::whatever!("conn_type stream ended before `ConnectionType::Direct`"); + n0_error::bail!("conn_type stream ended before `ConnectionType::Direct`"); } async fn accept(ep: &Endpoint) -> Result { From 836e80a6b90e6e3d65b1577be146c0527cf1299f Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 27 Oct 2025 10:11:33 +0100 Subject: [PATCH 27/58] fix: adapt to n0-error API changes --- iroh-relay/src/client.rs | 6 ++--- iroh-relay/src/client/tls.rs | 6 ++--- iroh-relay/src/protos/handshake.rs | 14 +++++----- iroh-relay/src/protos/relay.rs | 6 ++--- iroh-relay/src/server/client.rs | 4 +-- iroh-relay/src/server/http_server.rs | 6 ++--- iroh/examples/screening-connection.rs | 4 +-- iroh/src/disco.rs | 4 +-- iroh/src/discovery.rs | 4 +-- iroh/src/discovery/pkarr.rs | 6 ++--- iroh/src/endpoint.rs | 16 +++++------ iroh/src/magicsock.rs | 8 +++--- iroh/src/magicsock/transports/relay/actor.rs | 26 +++++++++--------- iroh/src/net_report/ip_mapped_addrs.rs | 4 +-- iroh/src/net_report/reportgen.rs | 28 +++++++++----------- iroh/src/protocol.rs | 4 +-- 16 files changed, 72 insertions(+), 74 deletions(-) diff --git a/iroh-relay/src/client.rs b/iroh-relay/src/client.rs index 781672b3faa..46a21c21019 100644 --- a/iroh-relay/src/client.rs +++ b/iroh-relay/src/client.rs @@ -11,7 +11,7 @@ use std::{ use conn::Conn; use iroh_base::{RelayUrl, SecretKey}; -use n0_error::{Err, Error, add_meta, e}; +use n0_error::{Error, add_meta, e}; use n0_future::{ Sink, Stream, split::{SplitSink, SplitStream, split}, @@ -286,9 +286,9 @@ impl ClientBuilder { let (conn, response) = builder.connect_on(stream).await?; if response.status() != hyper::StatusCode::SWITCHING_PROTOCOLS { - return Err!(ConnectError::UnexpectedUpgradeStatus { + return Err(e!(ConnectError::UnexpectedUpgradeStatus { code: response.status() - }); + })); } let conn = Conn::new(conn, self.key_cache.clone(), &self.secret_key).await?; diff --git a/iroh-relay/src/client/tls.rs b/iroh-relay/src/client/tls.rs index eb71831c5d9..b5c585c4685 100644 --- a/iroh-relay/src/client/tls.rs +++ b/iroh-relay/src/client/tls.rs @@ -10,7 +10,7 @@ use bytes::Bytes; use data_encoding::BASE64URL; use http_body_util::Empty; use hyper::{Request, upgrade::Parts}; -use n0_error::{Err, e}; +use n0_error::e; use n0_future::{task, time}; use rustls::client::Resumption; use tracing::error; @@ -257,9 +257,9 @@ impl MaybeTlsStreamBuilder { .await .map_err(|err| e!(DialError::ProxyConnect, err))?; if !res.status().is_success() { - return Err!(DialError::ProxyConnectInvalidStatus { + return Err(e!(DialError::ProxyConnectInvalidStatus { status: res.status() - }); + })); } let upgraded = hyper::upgrade::on(res) diff --git a/iroh-relay/src/protos/handshake.rs b/iroh-relay/src/protos/handshake.rs index a08b0e56af7..7be217e5e06 100644 --- a/iroh-relay/src/protos/handshake.rs +++ b/iroh-relay/src/protos/handshake.rs @@ -31,7 +31,7 @@ use http::HeaderValue; #[cfg(feature = "server")] use iroh_base::Signature; use iroh_base::{PublicKey, SecretKey}; -use n0_error::{Err, Error, add_meta, e}; +use n0_error::{Error, add_meta, e}; use n0_future::{SinkExt, TryStreamExt}; #[cfg(feature = "server")] use rand::CryptoRng; @@ -356,9 +356,9 @@ pub(crate) async fn clientside( } FrameType::ServerDeniesAuth => { let denial: ServerDeniesAuth = deserialize_frame(frame)?; - Err!(Error::ServerDeniedAuth { + Err(e!(Error::ServerDeniedAuth { reason: denial.reason - }) + })) } _ => unreachable!(), } @@ -444,9 +444,9 @@ pub(crate) async fn serverside( reason: "signature invalid".into(), }; write_frame(io, denial.clone()).await?; - Err!(Error::ServerDeniedAuth { + Err(e!(Error::ServerDeniedAuth { reason: denial.reason - }) + })) } else { trace!(?client_auth.public_key, "authentication succeeded via challenge"); Ok(SuccessfulAuthentication { @@ -473,9 +473,9 @@ impl SuccessfulAuthentication { reason: "not authorized".into(), }; write_frame(io, denial.clone()).await?; - Err!(Error::ServerDeniedAuth { + Err(e!(Error::ServerDeniedAuth { reason: denial.reason - }) + })) } } } diff --git a/iroh-relay/src/protos/relay.rs b/iroh-relay/src/protos/relay.rs index 91885057dba..212acc031d9 100644 --- a/iroh-relay/src/protos/relay.rs +++ b/iroh-relay/src/protos/relay.rs @@ -11,7 +11,7 @@ use std::num::NonZeroU16; use bytes::{Buf, BufMut, Bytes, BytesMut}; use iroh_base::{EndpointId, KeyParsingError}; -use n0_error::{Err, Error, add_meta, e}; +use n0_error::{Error, add_meta, e}; use n0_future::time::Duration; use super::common::{FrameType, FrameTypeError}; @@ -391,7 +391,7 @@ impl RelayToClientMsg { } } _ => { - return Err!(Error::InvalidFrameType { frame_type }); + return Err(e!(Error::InvalidFrameType { frame_type })); } }; Ok(res) @@ -489,7 +489,7 @@ impl ClientToRelayMsg { Self::Pong(data) } _ => { - return Err!(Error::InvalidFrameType { frame_type }); + return Err(e!(Error::InvalidFrameType { frame_type })); } }; Ok(res) diff --git a/iroh-relay/src/server/client.rs b/iroh-relay/src/server/client.rs index 106cc5795cb..6be21b34583 100644 --- a/iroh-relay/src/server/client.rs +++ b/iroh-relay/src/server/client.rs @@ -3,7 +3,7 @@ use std::{collections::HashSet, sync::Arc, time::Duration}; use iroh_base::EndpointId; -use n0_error::{Err, Error, add_meta, e}; +use n0_error::{Error, add_meta, e}; use n0_future::{SinkExt, StreamExt}; use rand::Rng; use time::{Date, OffsetDateTime}; @@ -438,7 +438,7 @@ impl Actor { trace!(?maybe_frame, "handle incoming frame"); let frame = match maybe_frame { Some(frame) => frame?, - None => return Err!(HandleFrameError::StreamTerminated), + None => return Err(e!(HandleFrameError::StreamTerminated)), }; match frame { diff --git a/iroh-relay/src/server/http_server.rs b/iroh-relay/src/server/http_server.rs index 4f9e37b1c2e..6026c6618a0 100644 --- a/iroh-relay/src/server/http_server.rs +++ b/iroh-relay/src/server/http_server.rs @@ -15,7 +15,7 @@ use hyper::{ service::Service, upgrade::Upgraded, }; -use n0_error::{Err, Error, add_meta, e}; +use n0_error::{Error, add_meta, e}; use n0_future::time::Elapsed; use tokio::net::{TcpListener, TcpStream}; use tokio_rustls_acme::AcmeAcceptor; @@ -76,7 +76,7 @@ fn body_full(content: impl Into) -> BytesBody { fn downcast_upgrade(upgraded: Upgraded) -> Result<(MaybeTlsStream, Bytes), ConnectionHandlerError> { match upgraded.downcast::>() { Ok(parts) => Ok((parts.io.into_inner(), parts.read_buf)), - Err(_) => Err!(ConnectionHandlerError::DowncastUpgrade), + Err(_) => Err(e!(ConnectionHandlerError::DowncastUpgrade)), } } @@ -626,7 +626,7 @@ impl Inner { debug!("relay_connection upgraded"); let (io, read_buf) = downcast_upgrade(upgraded)?; if !read_buf.is_empty() { - return Err!(ConnectionHandlerError::BufferNotEmpty { buf: read_buf }); + return Err(e!(ConnectionHandlerError::BufferNotEmpty { buf: read_buf })); } self.accept(io, client_auth_header).await?; diff --git a/iroh/examples/screening-connection.rs b/iroh/examples/screening-connection.rs index c12a090d058..734f74af24c 100644 --- a/iroh/examples/screening-connection.rs +++ b/iroh/examples/screening-connection.rs @@ -17,7 +17,7 @@ use iroh::{ endpoint::{Connecting, Connection}, protocol::{AcceptError, ProtocolHandler, Router}, }; -use n0_error::{Err, Result, StdResultExt}; +use n0_error::{Result, StdResultExt, e}; /// Each protocol is identified by its ALPN string. /// @@ -110,7 +110,7 @@ impl ProtocolHandler for ScreenedEcho { // reject every other connection if count % 2 == 0 { println!("rejecting connection"); - return Err!(AcceptError::NotAllowed); + return Err(e!(AcceptError::NotAllowed)); } // To allow normal connection construction, await the connecting future & return diff --git a/iroh/src/disco.rs b/iroh/src/disco.rs index c99f45571a6..cf08c7f2364 100644 --- a/iroh/src/disco.rs +++ b/iroh/src/disco.rs @@ -25,7 +25,7 @@ use std::{ use data_encoding::HEXLOWER; use iroh_base::{PublicKey, RelayUrl}; -use n0_error::{Err, Error, add_meta, e}; +use n0_error::{Error, add_meta, e}; use rand::Rng; use serde::{Deserialize, Serialize}; // use n0_error ensure macro path-qualified @@ -268,7 +268,7 @@ fn send_addr_from_bytes(p: &[u8]) -> Result { let u: Url = s.parse().map_err(|_| e!(ParseError::InvalidEncoding))?; Ok(SendAddr::Relay(u.into())) } - _ => Err!(ParseError::UnknownFormat), + _ => Err(e!(ParseError::UnknownFormat)), } } diff --git a/iroh/src/discovery.rs b/iroh/src/discovery.rs index af030634ec8..2a8498cb666 100644 --- a/iroh/src/discovery.rs +++ b/iroh/src/discovery.rs @@ -113,7 +113,7 @@ use std::sync::{Arc, RwLock}; use iroh_base::{EndpointAddr, EndpointId}; -use n0_error::{AnyError, Err, Error, add_meta, e}; +use n0_error::{AnyError, Error, add_meta, e}; use n0_future::{ boxed::BoxStream, stream::StreamExt, @@ -634,7 +634,7 @@ impl DiscoveryTask { } } if let Some(tx) = on_first_tx.take() { - tx.send(Err!(DiscoveryError::NoResults { endpoint_id })) + tx.send(Err(e!(DiscoveryError::NoResults { endpoint_id }))) .ok(); } } diff --git a/iroh/src/discovery/pkarr.rs b/iroh/src/discovery/pkarr.rs index 6f328f0c4c1..273b385fe76 100644 --- a/iroh/src/discovery/pkarr.rs +++ b/iroh/src/discovery/pkarr.rs @@ -48,7 +48,7 @@ use std::sync::Arc; use iroh_base::{EndpointId, RelayUrl, SecretKey}; use iroh_relay::endpoint_info::{EncodingError, EndpointInfo}; -use n0_error::{Err, Error, add_meta, e}; +use n0_error::{Error, add_meta, e}; use n0_future::{ boxed::BoxStream, task::{self, AbortOnDropHandle}, @@ -618,9 +618,9 @@ impl PkarrRelayClient { .map_err(|source| e!(PkarrError::HttpSend { source }))?; if !response.status().is_success() { - return Err!(PkarrError::HttpRequest { + return Err(e!(PkarrError::HttpRequest { status: response.status() - }); + })); } Ok(()) diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 64748d7a278..361ad78a31b 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -23,7 +23,7 @@ use std::{ use ed25519_dalek::{VerifyingKey, pkcs8::DecodePublicKey}; use iroh_base::{EndpointAddr, EndpointId, RelayUrl, SecretKey}; use iroh_relay::{RelayConfig, RelayMap}; -use n0_error::{Err, Error, add_meta, e}; +use n0_error::{Error, add_meta, e}; use n0_future::time::Duration; use n0_watcher::Watcher; use pin_project::pin_project; @@ -787,7 +787,7 @@ impl Endpoint { source: Source, ) -> Result<(), AddEndpointAddrError> { if endpoint_addr.endpoint_id == self.id() { - return Err!(AddEndpointAddrError::OwnAddress); + return Err(e!(AddEndpointAddrError::OwnAddress)); } self.msock.add_endpoint_addr(endpoint_addr, source) } @@ -1292,7 +1292,7 @@ impl Endpoint { if let Some(addr) = self.msock.get_mapping_addr(endpoint_id) { Ok((addr, Some(discovery))) } else { - Err!(GetMappingAddressError::NoAddress) + Err(e!(GetMappingAddressError::NoAddress)) } } } @@ -1620,9 +1620,9 @@ impl Connecting { match data.downcast::() { Ok(data) => match data.protocol { Some(protocol) => Ok(protocol), - None => Err!(AlpnError::Unavailable), + None => Err(e!(AlpnError::Unavailable)), }, - Err(_) => Err!(AlpnError::UnknownHandshake), + Err(_) => Err(e!(AlpnError::UnknownHandshake)), } } } @@ -1913,7 +1913,7 @@ impl Connection { match data { None => { warn!("no peer certificate found"); - Err!(RemoteEndpointIdError) + Err(e!(RemoteEndpointIdError)) } Some(data) => match data.downcast::>() { Ok(certs) => { @@ -1922,7 +1922,7 @@ impl Connection { "expected a single peer certificate, but {} found", certs.len() ); - return Err!(RemoteEndpointIdError); + return Err(e!(RemoteEndpointIdError)); } let peer_id = EndpointId::from_verifying_key( @@ -1934,7 +1934,7 @@ impl Connection { } Err(err) => { warn!("invalid peer certificate: {:?}", err); - Err!(RemoteEndpointIdError) + Err(e!(RemoteEndpointIdError)) } }, } diff --git a/iroh/src/magicsock.rs b/iroh/src/magicsock.rs index a73bb3fc6f3..ac025e300dd 100644 --- a/iroh/src/magicsock.rs +++ b/iroh/src/magicsock.rs @@ -32,7 +32,7 @@ use bytes::Bytes; use data_encoding::HEXLOWER; use iroh_base::{EndpointAddr, EndpointId, PublicKey, RelayUrl, SecretKey}; use iroh_relay::{RelayConfig, RelayMap}; -use n0_error::{Err, Error, add_meta, e}; +use n0_error::{Error, add_meta, e}; use n0_future::{ task::{self, AbortOnDropHandle}, time::{self, Duration, Instant}, @@ -415,9 +415,9 @@ impl MagicSock { .add_endpoint_addr(addr, source, have_ipv6, &self.metrics.magicsock); Ok(()) } else if pruned != 0 { - Err!(AddEndpointAddrError::EmptyPruned { pruned }) + Err(e!(AddEndpointAddrError::EmptyPruned { pruned })) } else { - Err!(AddEndpointAddrError::Empty) + Err(e!(AddEndpointAddrError::Empty)) } } @@ -2453,7 +2453,7 @@ impl TryFrom for EndpointIdMappedAddr { { return Ok(Self(value)); } - Err!(EndpointIdMappedAddrError) + Err(e!(EndpointIdMappedAddrError)) } } diff --git a/iroh/src/magicsock/transports/relay/actor.rs b/iroh/src/magicsock/transports/relay/actor.rs index 56701b219a1..b661c9c6dba 100644 --- a/iroh/src/magicsock/transports/relay/actor.rs +++ b/iroh/src/magicsock/transports/relay/actor.rs @@ -44,7 +44,7 @@ use iroh_relay::{ client::{Client, ConnectError, RecvError, SendError}, protos::relay::{ClientToRelayMsg, Datagrams, RelayToClientMsg}, }; -use n0_error::{Err, Error, add_meta, e}; +use n0_error::{Error, add_meta, e}; use n0_future::{ FuturesUnorderedBounded, SinkExt, StreamExt, task::JoinSet, @@ -489,10 +489,10 @@ impl ActiveRelayActor { async move { match time::timeout(CONNECT_TIMEOUT, client_builder.connect()).await { Ok(Ok(client)) => Ok(client), - Ok(Err(err)) => Err!(DialError::Connect { source: err }), - Err(_) => Err!(DialError::Timeout { + Ok(Err(err)) => Err(e!(DialError::Connect { source: err })), + Err(_) => Err(e!(DialError::Timeout { timeout: CONNECT_TIMEOUT - }), + })), } } } @@ -560,7 +560,7 @@ impl ActiveRelayActor { } } _ = state.ping_tracker.timeout() => { - break Err!(RunError::PingTimeout); + break Err(e!(RunError::PingTimeout)); } _ = ping_interval.tick() => { let data = state.ping_tracker.new_ping(); @@ -583,8 +583,8 @@ impl ActiveRelayActor { let fut = client_sink.send(ClientToRelayMsg::Ping(data)); self.run_sending(fut, &mut state, &mut client_stream).await?; } - Some(_) => break Err!(RunError::LocalIpInvalid), - None => break Err!(RunError::LocalAddrMissing), + Some(_) => break Err(e!(RunError::LocalIpInvalid)), + None => break Err(e!(RunError::LocalAddrMissing)), } } #[cfg(test)] @@ -625,7 +625,7 @@ impl ActiveRelayActor { } msg = client_stream.next() => { let Some(msg) = msg else { - break Err!(RunError::StreamClosedServer); + break Err(e!(RunError::StreamClosedServer)); }; match msg { Ok(msg) => { @@ -633,7 +633,7 @@ impl ActiveRelayActor { // reset the ping timer, we have just received a message ping_interval.reset(); }, - Err(err) => break Err!(RunError::ClientStreamRead { source: err }), + Err(err) => break Err(e!(RunError::ClientStreamRead, err)), } } _ = &mut self.inactive_timeout, if !self.is_home_relay => { @@ -735,7 +735,7 @@ impl ActiveRelayActor { break Ok(()); } _ = &mut timeout => { - break Err!(RunError::SendTimeout); + break Err(e!(RunError::SendTimeout)); } msg = self.prio_inbox.recv() => { let Some(msg) = msg else { @@ -756,16 +756,16 @@ impl ActiveRelayActor { } } _ = state.ping_tracker.timeout() => { - break Err!(RunError::PingTimeout); + break Err(e!(RunError::PingTimeout)); } // No need to read the inbox or datagrams to send. msg = client_stream.next() => { let Some(msg) = msg else { - break Err!(RunError::StreamClosedServer); + break Err(e!(RunError::StreamClosedServer)); }; match msg { Ok(msg) => self.handle_relay_msg(msg, state), - Err(err) => break Err!(RunError::ClientStreamRead { source: err }), + Err(err) => break Err(e!(RunError::ClientStreamRead, err)), } } _ = &mut self.inactive_timeout, if !self.is_home_relay => { diff --git a/iroh/src/net_report/ip_mapped_addrs.rs b/iroh/src/net_report/ip_mapped_addrs.rs index b3468f0ab74..dea24243f02 100644 --- a/iroh/src/net_report/ip_mapped_addrs.rs +++ b/iroh/src/net_report/ip_mapped_addrs.rs @@ -7,7 +7,7 @@ use std::{ }, }; -use n0_error::{Err, Error, add_meta}; +use n0_error::{Error, add_meta, e}; /// Can occur when converting a [`SocketAddr`] to an [`IpMappedAddr`] #[add_meta] @@ -74,7 +74,7 @@ impl TryFrom for IpMappedAddr { { return Ok(Self(value)); } - Err!(IpMappedAddrError) + Err(e!(IpMappedAddrError)) } } diff --git a/iroh/src/net_report/reportgen.rs b/iroh/src/net_report/reportgen.rs index 2c6875d6281..6757bcd93c2 100644 --- a/iroh/src/net_report/reportgen.rs +++ b/iroh/src/net_report/reportgen.rs @@ -33,7 +33,7 @@ use iroh_relay::{ dns::{DnsResolver, DnsStaggeredError as StaggeredError}, quic::QuicClient, }; -use n0_error::{Err, Error, add_meta, e}; +use n0_error::{Error, add_meta, e}; #[cfg(wasm_browser)] use n0_future::future::Pending; use n0_future::{ @@ -385,12 +385,10 @@ impl Actor { Some(Ok(Ok(report))) => Ok(report), Some(Ok(Err(err))) => { warn!("probe failed: {:#}", err); - Err!(ProbesError::ProbeFailure { source: err }) + Err(e!(ProbesError::ProbeFailure { source: err })) } - Some(Err(time::Elapsed { .. })) => { - Err!(ProbesError::Timeout) - } - None => Err!(ProbesError::Cancelled), + Some(Err(time::Elapsed { .. })) => Err(e!(ProbesError::Timeout)), + None => Err(e!(ProbesError::Cancelled)), }; ProbeFinished::Regular(res) } @@ -514,7 +512,7 @@ impl Probe { .await { Ok(report) => Ok(ProbeReport::Https(report)), - Err(err) => Err!(ProbeError::Https { source: err }), + Err(err) => Err(e!(ProbeError::Https { source: err })), } } #[cfg(not(wasm_browser))] @@ -714,12 +712,12 @@ async fn relay_lookup_ipv4_staggered( IpAddr::V6(_) => unreachable!("bad DNS lookup: {:?}", addr), }) .ok_or_else(|| e!(GetRelayAddrError::NoAddrFound)), - Err(err) => Err!(GetRelayAddrError::DnsLookup { source: err }), + Err(err) => Err(e!(GetRelayAddrError::DnsLookup { source: err })), } } Some(url::Host::Ipv4(addr)) => Ok(SocketAddrV4::new(addr, port)), - Some(url::Host::Ipv6(_addr)) => Err!(GetRelayAddrError::NoAddrFound), - None => Err!(GetRelayAddrError::InvalidHostname), + Some(url::Host::Ipv6(_addr)) => Err(e!(GetRelayAddrError::NoAddrFound)), + None => Err(e!(GetRelayAddrError::InvalidHostname)), } } @@ -746,12 +744,12 @@ async fn relay_lookup_ipv6_staggered( IpAddr::V6(ip) => SocketAddrV6::new(ip, port, 0, 0), }) .ok_or_else(|| e!(GetRelayAddrError::NoAddrFound)), - Err(err) => Err!(GetRelayAddrError::DnsLookup { source: err }), + Err(err) => Err(e!(GetRelayAddrError::DnsLookup { source: err })), } } - Some(url::Host::Ipv4(_addr)) => Err!(GetRelayAddrError::NoAddrFound), + Some(url::Host::Ipv4(_addr)) => Err(e!(GetRelayAddrError::NoAddrFound)), Some(url::Host::Ipv6(addr)) => Ok(SocketAddrV6::new(addr, port, 0, 0)), - None => Err!(GetRelayAddrError::InvalidHostname), + None => Err(e!(GetRelayAddrError::InvalidHostname)), } } @@ -854,9 +852,9 @@ async fn run_https_probe( Ok(HttpsProbeReport { relay, latency }) } else { - Err!(MeasureHttpsLatencyError::InvalidResponse { + Err(e!(MeasureHttpsLatencyError::InvalidResponse { status: response.status() - }) + })) } } diff --git a/iroh/src/protocol.rs b/iroh/src/protocol.rs index 6e374ea3d96..b2b3f9f95e6 100644 --- a/iroh/src/protocol.rs +++ b/iroh/src/protocol.rs @@ -43,7 +43,7 @@ use std::{ }; use iroh_base::EndpointId; -use n0_error::{AnyError, Err, Error, add_meta, e}; +use n0_error::{AnyError, Error, add_meta, e}; use n0_future::{ join_all, task::{self, AbortOnDropHandle, JoinSet}, @@ -558,7 +558,7 @@ impl ProtocolHandler for AccessLimit

{ let is_allowed = (self.limiter)(remote); if !is_allowed { conn.close(0u32.into(), b"not allowed"); - return Err!(AcceptError::NotAllowed); + return Err(e!(AcceptError::NotAllowed)); } self.proto.accept(conn).await?; Ok(()) From e8b7690822ef4107f0f0061c903fe19d2d9d1b1d Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 27 Oct 2025 10:15:13 +0100 Subject: [PATCH 28/58] cleanup --- iroh/src/endpoint.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 361ad78a31b..e62b62660ed 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -1913,7 +1913,7 @@ impl Connection { match data { None => { warn!("no peer certificate found"); - Err(e!(RemoteEndpointIdError)) + Err(RemoteEndpointIdError::new()) } Some(data) => match data.downcast::>() { Ok(certs) => { @@ -1922,19 +1922,19 @@ impl Connection { "expected a single peer certificate, but {} found", certs.len() ); - return Err(e!(RemoteEndpointIdError)); + return Err(RemoteEndpointIdError::new()); } let peer_id = EndpointId::from_verifying_key( VerifyingKey::from_public_key_der(&certs[0]) - .map_err(|_| e!(RemoteEndpointIdError))?, + .map_err(|_| RemoteEndpointIdError::new())?, ); Ok(peer_id) } Err(err) => { warn!("invalid peer certificate: {:?}", err); - Err(e!(RemoteEndpointIdError)) + Err(RemoteEndpointIdError::new()) } }, } From b466519778967dde17ba05b1519291aeb02427f7 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 27 Oct 2025 10:16:26 +0100 Subject: [PATCH 29/58] more cleanup --- iroh-relay/src/dns.rs | 4 ++-- iroh-relay/src/endpoint_info.rs | 2 +- iroh-relay/src/server/client.rs | 2 +- iroh/src/endpoint.rs | 6 +++--- iroh/src/magicsock/transports/relay/actor.rs | 10 +++++----- iroh/src/net_report/reportgen.rs | 8 ++++---- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/iroh-relay/src/dns.rs b/iroh-relay/src/dns.rs index 7d7d44a0517..a9fb5079b17 100644 --- a/iroh-relay/src/dns.rs +++ b/iroh-relay/src/dns.rs @@ -422,7 +422,7 @@ impl DnsResolver { let lookup = self .lookup_txt(name.clone(), DNS_TIMEOUT) .await - .map_err(|err| e!(LookupError::LookupFailed { source: err }))?; + .map_err(|err| e!(LookupError::LookupFailed, err))?; let info = EndpointInfo::from_txt_lookup(name, lookup).map_err(|err| { e!(LookupError::ParseError { source: Box::new(err) @@ -440,7 +440,7 @@ impl DnsResolver { let lookup = self .lookup_txt(name.clone(), DNS_TIMEOUT) .await - .map_err(|err| e!(LookupError::LookupFailed { source: err }))?; + .map_err(|err| e!(LookupError::LookupFailed, err))?; let info = EndpointInfo::from_txt_lookup(name, lookup).map_err(|err| { e!(LookupError::ParseError { source: Box::new(err) diff --git a/iroh-relay/src/endpoint_info.rs b/iroh-relay/src/endpoint_info.rs index e77eecea2a1..dbbde577e81 100644 --- a/iroh-relay/src/endpoint_info.rs +++ b/iroh-relay/src/endpoint_info.rs @@ -106,7 +106,7 @@ impl EndpointIdExt for EndpointId { .try_into() .map_err(|_| e!(DecodingError::InvalidLength { len: s.len() }))?; let endpoint_id = EndpointId::from_bytes(bytes) - .map_err(|err| e!(DecodingError::InvalidKey { source: err }))?; + .map_err(|err| e!(DecodingError::InvalidKey, err))?; Ok(endpoint_id) } } diff --git a/iroh-relay/src/server/client.rs b/iroh-relay/src/server/client.rs index 6be21b34583..bfb9dcb9a72 100644 --- a/iroh-relay/src/server/client.rs +++ b/iroh-relay/src/server/client.rs @@ -380,7 +380,7 @@ impl Actor { async fn write_frame(&mut self, frame: RelayToClientMsg) -> Result<(), WriteFrameError> { tokio::time::timeout(self.timeout, self.stream.send(frame)) .await? - .map_err(|err| e!(WriteFrameError::Stream { source: err }))?; + .map_err(|err| e!(WriteFrameError::Stream, err))?; Ok(()) } diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index e62b62660ed..0165be68b6b 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -683,7 +683,7 @@ impl Endpoint { if !endpoint_addr.is_empty() { self.add_endpoint_addr(endpoint_addr.clone(), Source::App) - .map_err(|err| e!(ConnectWithOptsError::AddEndpointAddr { source: err }))?; + .map_err(|err| e!(ConnectWithOptsError::AddEndpointAddr, err))?; } let endpoint_id = endpoint_addr.endpoint_id; let direct_addresses = endpoint_addr.direct_addresses.clone(); @@ -696,7 +696,7 @@ impl Endpoint { let (mapped_addr, _discovery_drop_guard) = self .get_mapping_addr_and_maybe_start_discovery(endpoint_addr) .await - .map_err(|err| e!(ConnectWithOptsError::NoAddress { source: err }))?; + .map_err(|err| e!(ConnectWithOptsError::NoAddress, err))?; let transport_config = options .transport_config @@ -732,7 +732,7 @@ impl Endpoint { mapped_addr.private_socket_addr(), server_name, ) - .map_err(|err| e!(ConnectWithOptsError::Quinn { source: err }))?; + .map_err(|err| e!(ConnectWithOptsError::Quinn, err))?; Ok(Connecting { inner: connect, diff --git a/iroh/src/magicsock/transports/relay/actor.rs b/iroh/src/magicsock/transports/relay/actor.rs index b661c9c6dba..1bc31c2d1ff 100644 --- a/iroh/src/magicsock/transports/relay/actor.rs +++ b/iroh/src/magicsock/transports/relay/actor.rs @@ -366,7 +366,7 @@ impl ActiveRelayActor { async fn run_once(&mut self) -> Result<(), RelayConnectionError> { let client = match self.run_dialing().instrument(info_span!("dialing")).await { Some(client_res) => { - client_res.map_err(|err| e!(RelayConnectionError::Dial { source: err }))? + client_res.map_err(|err| e!(RelayConnectionError::Dial, err))? } None => return Ok(()), }; @@ -489,7 +489,7 @@ impl ActiveRelayActor { async move { match time::timeout(CONNECT_TIMEOUT, client_builder.connect()).await { Ok(Ok(client)) => Ok(client), - Ok(Err(err)) => Err(e!(DialError::Connect { source: err })), + Ok(Err(err)) => Err(e!(DialError::Connect, err)), Err(_) => Err(e!(DialError::Timeout { timeout: CONNECT_TIMEOUT })), @@ -515,7 +515,7 @@ impl ActiveRelayActor { let (mut client_stream, client_sink) = client.split(); let mut client_sink = - client_sink.sink_map_err(|e| e!(RunError::ClientStreamWrite { source: e })); + client_sink.sink_map_err(|e| e!(RunError::ClientStreamWrite, e)); let mut state = ConnectedRelayState { ping_tracker: PingTracker::default(), @@ -806,9 +806,9 @@ struct ConnectedRelayState { impl ConnectedRelayState { fn map_err(&self, error: RunError) -> RelayConnectionError { if self.established { - e!(RelayConnectionError::Established { source: error }) + e!(RelayConnectionError::Established, error) } else { - e!(RelayConnectionError::Handshake { source: error }) + e!(RelayConnectionError::Handshake, error) } } } diff --git a/iroh/src/net_report/reportgen.rs b/iroh/src/net_report/reportgen.rs index 6757bcd93c2..3dac6674175 100644 --- a/iroh/src/net_report/reportgen.rs +++ b/iroh/src/net_report/reportgen.rs @@ -385,7 +385,7 @@ impl Actor { Some(Ok(Ok(report))) => Ok(report), Some(Ok(Err(err))) => { warn!("probe failed: {:#}", err); - Err(e!(ProbesError::ProbeFailure { source: err })) + Err(e!(ProbesError::ProbeFailure, err)) } Some(Err(time::Elapsed { .. })) => Err(e!(ProbesError::Timeout)), None => Err(e!(ProbesError::Cancelled)), @@ -512,7 +512,7 @@ impl Probe { .await { Ok(report) => Ok(ProbeReport::Https(report)), - Err(err) => Err(e!(ProbeError::Https { source: err })), + Err(err) => Err(e!(ProbeError::Https, err)), } } #[cfg(not(wasm_browser))] @@ -712,7 +712,7 @@ async fn relay_lookup_ipv4_staggered( IpAddr::V6(_) => unreachable!("bad DNS lookup: {:?}", addr), }) .ok_or_else(|| e!(GetRelayAddrError::NoAddrFound)), - Err(err) => Err(e!(GetRelayAddrError::DnsLookup { source: err })), + Err(err) => Err(e!(GetRelayAddrError::DnsLookup, err)), } } Some(url::Host::Ipv4(addr)) => Ok(SocketAddrV4::new(addr, port)), @@ -744,7 +744,7 @@ async fn relay_lookup_ipv6_staggered( IpAddr::V6(ip) => SocketAddrV6::new(ip, port, 0, 0), }) .ok_or_else(|| e!(GetRelayAddrError::NoAddrFound)), - Err(err) => Err(e!(GetRelayAddrError::DnsLookup { source: err })), + Err(err) => Err(e!(GetRelayAddrError::DnsLookup, err)), } } Some(url::Host::Ipv4(_addr)) => Err(e!(GetRelayAddrError::NoAddrFound)), From d94e61ccca7a54cf852604b85804cfd5c00cd10b Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 27 Oct 2025 10:34:22 +0100 Subject: [PATCH 30/58] cleanup --- Cargo.lock | 4 ++-- iroh-relay/src/client/conn.rs | 9 +++------ iroh-relay/src/dns.rs | 2 -- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1016353e5f8..903e0454ba8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2803,7 +2803,7 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#74db31b779f2c1d6a748d3a76494d76792892564" +source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#38505e4aadc691a5a374dd67ad69f10a03f93f4c" dependencies = [ "anyhow", "derive_more 2.0.1", @@ -2814,7 +2814,7 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#74db31b779f2c1d6a748d3a76494d76792892564" +source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#38505e4aadc691a5a374dd67ad69f10a03f93f4c" dependencies = [ "darling", "heck", diff --git a/iroh-relay/src/client/conn.rs b/iroh-relay/src/client/conn.rs index 75742f4f97d..6e1955670d0 100644 --- a/iroh-relay/src/client/conn.rs +++ b/iroh-relay/src/client/conn.rs @@ -139,15 +139,12 @@ impl Sink for Conn { fn start_send(mut self: Pin<&mut Self>, frame: ClientToRelayMsg) -> Result<(), Self::Error> { let size = frame.encoded_len(); - n0_error::ensure!( + n0_error::ensure_e!( size <= MAX_PACKET_SIZE, - n0_error::e!(SendError::ExceedsMaxPacketSize { size }) + SendError::ExceedsMaxPacketSize { size } ); if let ClientToRelayMsg::Datagrams { datagrams, .. } = &frame { - n0_error::ensure!( - !datagrams.contents.is_empty(), - n0_error::e!(SendError::EmptyPacket) - ); + n0_error::ensure_e!(!datagrams.contents.is_empty(), SendError::EmptyPacket); } Pin::new(&mut self.conn) diff --git a/iroh-relay/src/dns.rs b/iroh-relay/src/dns.rs index a9fb5079b17..f5314d934d0 100644 --- a/iroh-relay/src/dns.rs +++ b/iroh-relay/src/dns.rs @@ -121,8 +121,6 @@ pub struct LookupStaggeredError { errors: Vec, } -// no manual new; use e!(Type { errors }) - /// Builder for [`DnsResolver`]. #[derive(Debug, Clone, Default)] pub struct Builder { From 40b812320d15cda80b4d258a4f494c6dd1451ad9 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 27 Oct 2025 10:42:26 +0100 Subject: [PATCH 31/58] updates and cleanups --- Cargo.lock | 4 +-- iroh-relay/src/endpoint_info.rs | 8 +++--- iroh-relay/src/protos/handshake.rs | 12 ++++----- iroh-relay/src/protos/relay.rs | 26 ++++++++++---------- iroh-relay/src/server/http_server.rs | 16 ++++++------ iroh-relay/src/server/streams.rs | 14 +++++------ iroh/src/disco.rs | 10 ++++---- iroh/src/discovery.rs | 12 ++++----- iroh/src/endpoint.rs | 4 +-- iroh/src/key.rs | 2 +- iroh/src/magicsock/transports/relay/actor.rs | 7 ++---- 11 files changed, 56 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 903e0454ba8..22fc77d3c2e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2803,7 +2803,7 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#38505e4aadc691a5a374dd67ad69f10a03f93f4c" +source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#52da5e34a1d791ddb9e4588814bad6be1427b50e" dependencies = [ "anyhow", "derive_more 2.0.1", @@ -2814,7 +2814,7 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#38505e4aadc691a5a374dd67ad69f10a03f93f4c" +source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#52da5e34a1d791ddb9e4588814bad6be1427b50e" dependencies = [ "darling", "heck", diff --git a/iroh-relay/src/endpoint_info.rs b/iroh-relay/src/endpoint_info.rs index dbbde577e81..ba9ead503d8 100644 --- a/iroh-relay/src/endpoint_info.rs +++ b/iroh-relay/src/endpoint_info.rs @@ -105,8 +105,8 @@ impl EndpointIdExt for EndpointId { let bytes: &[u8; 32] = &bytes .try_into() .map_err(|_| e!(DecodingError::InvalidLength { len: s.len() }))?; - let endpoint_id = EndpointId::from_bytes(bytes) - .map_err(|err| e!(DecodingError::InvalidKey, err))?; + let endpoint_id = + EndpointId::from_bytes(bytes).map_err(|err| e!(DecodingError::InvalidKey, err))?; Ok(endpoint_id) } } @@ -234,7 +234,7 @@ impl TryFrom for UserData { type Error = MaxLengthExceededError; fn try_from(value: String) -> Result { - n0_error::ensure!(value.len() <= Self::MAX_LENGTH, e!(MaxLengthExceededError)); + n0_error::ensure_e!(value.len() <= Self::MAX_LENGTH, MaxLengthExceededError); Ok(Self(value)) } } @@ -243,7 +243,7 @@ impl FromStr for UserData { type Err = MaxLengthExceededError; fn from_str(s: &str) -> std::result::Result { - n0_error::ensure!(s.len() <= Self::MAX_LENGTH, e!(MaxLengthExceededError)); + n0_error::ensure_e!(s.len() <= Self::MAX_LENGTH, MaxLengthExceededError); Ok(Self(s.to_string())) } } diff --git a/iroh-relay/src/protos/handshake.rs b/iroh-relay/src/protos/handshake.rs index 7be217e5e06..0b211062663 100644 --- a/iroh-relay/src/protos/handshake.rs +++ b/iroh-relay/src/protos/handshake.rs @@ -301,12 +301,12 @@ impl KeyMaterialClientAuth { // there must be something wrong with the client's secret key or signature. let (message, suffix) = key_material.split_at(16); let suffix: [u8; 16] = suffix.try_into().expect("hardcoded length"); - n0_error::ensure!( + n0_error::ensure_e!( suffix == self.key_material_suffix, - e!(VerificationError::MismatchedSuffix { + VerificationError::MismatchedSuffix { expected: self.key_material_suffix, actual: suffix - }) + } ); // NOTE: We don't blake3-hash here as we do it in [`ServerChallenge::message_to_sign`], // because we already have a domain separation string and keyed hashing step in @@ -511,12 +511,12 @@ async fn read_frame( let frame_type = FrameType::from_bytes(&mut payload).map_err(|err| e!(Error::FrameTypeError, err))?; trace!(?frame_type, "Reading frame"); - n0_error::ensure!( + n0_error::ensure_e!( expected_types.contains(&frame_type), - e!(Error::UnexpectedFrameType { + Error::UnexpectedFrameType { frame_type, expected_types: expected_types.to_vec() - }) + } ); Ok((frame_type, payload)) diff --git a/iroh-relay/src/protos/relay.rs b/iroh-relay/src/protos/relay.rs index 212acc031d9..b702165eac6 100644 --- a/iroh-relay/src/protos/relay.rs +++ b/iroh-relay/src/protos/relay.rs @@ -222,9 +222,9 @@ impl Datagrams { fn from_bytes(mut bytes: Bytes, is_batch: bool) -> Result { if is_batch { // 1 bytes ECN, 2 bytes segment size - n0_error::ensure!(bytes.len() >= 3, e!(Error::InvalidFrame)); + n0_error::ensure_e!(bytes.len() >= 3, Error::InvalidFrame); } else { - n0_error::ensure!(bytes.len() >= 1, e!(Error::InvalidFrame)); + n0_error::ensure_e!(bytes.len() >= 1, Error::InvalidFrame); } let ecn_byte = bytes.get_u8(); @@ -331,14 +331,14 @@ impl RelayToClientMsg { pub(crate) fn from_bytes(mut content: Bytes, cache: &KeyCache) -> Result { let frame_type = FrameType::from_bytes(&mut content)?; let frame_len = content.len(); - n0_error::ensure!( + n0_error::ensure_e!( frame_len <= MAX_PACKET_SIZE, - e!(Error::FrameTooLarge { frame_len }) + Error::FrameTooLarge { frame_len } ); let res = match frame_type { FrameType::RelayToClientDatagram | FrameType::RelayToClientDatagramBatch => { - n0_error::ensure!(content.len() >= EndpointId::LENGTH, e!(Error::InvalidFrame)); + n0_error::ensure_e!(content.len() >= EndpointId::LENGTH, Error::InvalidFrame); let remote_endpoint_id = cache.key_from_slice(&content[..EndpointId::LENGTH])?; let datagrams = Datagrams::from_bytes( @@ -351,18 +351,18 @@ impl RelayToClientMsg { } } FrameType::EndpointGone => { - n0_error::ensure!(content.len() == EndpointId::LENGTH, e!(Error::InvalidFrame)); + n0_error::ensure_e!(content.len() == EndpointId::LENGTH, Error::InvalidFrame); let endpoint_id = cache.key_from_slice(content.as_ref())?; Self::EndpointGone(endpoint_id) } FrameType::Ping => { - n0_error::ensure!(content.len() == 8, e!(Error::InvalidFrame)); + n0_error::ensure_e!(content.len() == 8, Error::InvalidFrame); let mut data = [0u8; 8]; data.copy_from_slice(&content[..8]); Self::Ping(data) } FrameType::Pong => { - n0_error::ensure!(content.len() == 8, e!(Error::InvalidFrame)); + n0_error::ensure_e!(content.len() == 8, Error::InvalidFrame); let mut data = [0u8; 8]; data.copy_from_slice(&content[..8]); Self::Pong(data) @@ -372,7 +372,7 @@ impl RelayToClientMsg { Self::Health { problem } } FrameType::Restarting => { - n0_error::ensure!(content.len() == 4 + 4, e!(Error::InvalidFrame)); + n0_error::ensure_e!(content.len() == 4 + 4, Error::InvalidFrame); let reconnect_in = u32::from_be_bytes( content[..4] .try_into() @@ -459,9 +459,9 @@ impl ClientToRelayMsg { pub(crate) fn from_bytes(mut content: Bytes, cache: &KeyCache) -> Result { let frame_type = FrameType::from_bytes(&mut content)?; let frame_len = content.len(); - n0_error::ensure!( + n0_error::ensure_e!( frame_len <= MAX_PACKET_SIZE, - e!(Error::FrameTooLarge { frame_len }) + Error::FrameTooLarge { frame_len } ); let res = match frame_type { @@ -477,13 +477,13 @@ impl ClientToRelayMsg { } } FrameType::Ping => { - n0_error::ensure!(content.len() == 8, e!(Error::InvalidFrame)); + n0_error::ensure_e!(content.len() == 8, Error::InvalidFrame); let mut data = [0u8; 8]; data.copy_from_slice(&content[..8]); Self::Ping(data) } FrameType::Pong => { - n0_error::ensure!(content.len() == 8, e!(Error::InvalidFrame)); + n0_error::ensure_e!(content.len() == 8, Error::InvalidFrame); let mut data = [0u8; 8]; data.copy_from_slice(&content[..8]); Self::Pong(data) diff --git a/iroh-relay/src/server/http_server.rs b/iroh-relay/src/server/http_server.rs index 6026c6618a0..506aaa79440 100644 --- a/iroh-relay/src/server/http_server.rs +++ b/iroh-relay/src/server/http_server.rs @@ -464,20 +464,20 @@ impl RelayService { } let upgrade_header = expect_header(&req, UPGRADE)?; - n0_error::ensure!( + n0_error::ensure_e!( upgrade_header == HeaderValue::from_static(WEBSOCKET_UPGRADE_PROTOCOL), - e!(RelayUpgradeReqError::InvalidHeader { + RelayUpgradeReqError::InvalidHeader { header: UPGRADE, details: format!("value must be {WEBSOCKET_UPGRADE_PROTOCOL}") - }) + } ); let key = expect_header(&req, SEC_WEBSOCKET_KEY)?.clone(); let version = expect_header(&req, SEC_WEBSOCKET_VERSION)?.clone(); - n0_error::ensure!( + n0_error::ensure_e!( version.as_bytes() == SUPPORTED_WEBSOCKET_VERSION.as_bytes(), - e!(RelayUpgradeReqError::UnsupportedWebsocketVersion) + RelayUpgradeReqError::UnsupportedWebsocketVersion ); let subprotocols = expect_header(&req, SEC_WEBSOCKET_PROTOCOL)? @@ -492,12 +492,12 @@ impl RelayService { let supports_our_version = subprotocols .split_whitespace() .any(|p| p == RELAY_PROTOCOL_VERSION); - n0_error::ensure!( + n0_error::ensure_e!( supports_our_version, - e!(RelayUpgradeReqError::UnsupportedRelayVersion { + RelayUpgradeReqError::UnsupportedRelayVersion { we_support: RELAY_PROTOCOL_VERSION, you_support: subprotocols.to_string() - }) + } ); let client_auth_header = req.headers().get(CLIENT_AUTH_HEADER).cloned(); diff --git a/iroh-relay/src/server/streams.rs b/iroh-relay/src/server/streams.rs index 032c04f930b..bd1723f245a 100644 --- a/iroh-relay/src/server/streams.rs +++ b/iroh-relay/src/server/streams.rs @@ -6,7 +6,7 @@ use std::{ task::{Context, Poll}, }; -use n0_error::{Error, add_meta, e}; +use n0_error::{Error, add_meta}; use n0_future::{FutureExt, Sink, Stream, ready, time}; use tokio::io::{AsyncRead, AsyncWrite}; use tracing::instrument; @@ -99,12 +99,12 @@ impl Sink for RelayedStream { fn start_send(mut self: Pin<&mut Self>, item: RelayToClientMsg) -> Result<(), Self::Error> { let size = item.encoded_len(); - n0_error::ensure!( + n0_error::ensure_e!( size <= MAX_PACKET_SIZE, - e!(SendError::ExceedsMaxPacketSize { size }) + SendError::ExceedsMaxPacketSize { size } ); if let RelayToClientMsg::Datagrams { datagrams, .. } = &item { - n0_error::ensure!(!datagrams.contents.is_empty(), e!(SendError::EmptyPacket)); + n0_error::ensure_e!(!datagrams.contents.is_empty(), SendError::EmptyPacket); } Pin::new(&mut self.inner) @@ -306,13 +306,13 @@ impl Bucket { ) -> Result { // milliseconds is the tokio timer resolution let refill = bytes_per_second.saturating_mul(refill_period.as_millis() as i64) / 1000; - n0_error::ensure!( + n0_error::ensure_e!( max > 0 && bytes_per_second > 0 && refill_period.as_millis() as u32 > 0 && refill > 0, - e!(InvalidBucketConfig { + InvalidBucketConfig { max, bytes_per_second, refill_period - }), + } ); Ok(Self { fill: max, diff --git a/iroh/src/disco.rs b/iroh/src/disco.rs index cf08c7f2364..3d8d1a77c5f 100644 --- a/iroh/src/disco.rs +++ b/iroh/src/disco.rs @@ -217,7 +217,7 @@ pub struct CallMeMaybe { impl Ping { fn from_bytes(p: &[u8]) -> Result { // Deliberately lax on longer-than-expected messages, for future compatibility. - n0_error::ensure!(p.len() >= PING_LEN, e!(ParseError::TooShort)); + n0_error::ensure_e!(p.len() >= PING_LEN, ParseError::TooShort); let tx_id: [u8; TX_LEN] = p[..TX_LEN].try_into().expect("length checked"); let raw_key = &p[TX_LEN..TX_LEN + iroh_base::PublicKey::LENGTH]; let endpoint_key = @@ -256,7 +256,7 @@ pub enum ParseError { } fn send_addr_from_bytes(p: &[u8]) -> Result { - n0_error::ensure!(p.len() > 2, e!(ParseError::TooShort)); + n0_error::ensure_e!(p.len() > 2, ParseError::TooShort); match p[0] { 0u8 => { let bytes: [u8; EP_LENGTH] = p[1..].try_into().map_err(|_| e!(ParseError::TooShort))?; @@ -340,7 +340,7 @@ impl Pong { impl CallMeMaybe { fn from_bytes(p: &[u8]) -> Result { - n0_error::ensure!(p.len() % EP_LENGTH == 0, e!(ParseError::InvalidEncoding)); + n0_error::ensure_e!(p.len() % EP_LENGTH == 0, ParseError::InvalidEncoding); let num_entries = p.len() / EP_LENGTH; let mut m = CallMeMaybe { @@ -379,11 +379,11 @@ impl CallMeMaybe { impl Message { /// Parses the encrypted part of the message from inside the nacl secretbox. pub fn from_bytes(p: &[u8]) -> Result { - n0_error::ensure!(p.len() >= 2, e!(ParseError::TooShort)); + n0_error::ensure_e!(p.len() >= 2, ParseError::TooShort); let t = MessageType::try_from(p[0]).map_err(|_| e!(ParseError::UnknownFormat))?; let version = p[1]; - n0_error::ensure!(version == V0, e!(ParseError::UnknownFormat)); + n0_error::ensure_e!(version == V0, ParseError::UnknownFormat); let p = &p[2..]; match t { diff --git a/iroh/src/discovery.rs b/iroh/src/discovery.rs index 2a8498cb666..cbe6dbb2906 100644 --- a/iroh/src/discovery.rs +++ b/iroh/src/discovery.rs @@ -507,9 +507,9 @@ pub(super) struct DiscoveryTask { impl DiscoveryTask { /// Starts a discovery task. pub(super) fn start(ep: Endpoint, endpoint_id: EndpointId) -> Result { - n0_error::ensure!( + n0_error::ensure_e!( !ep.discovery().is_empty(), - e!(DiscoveryError::NoServiceConfigured) + DiscoveryError::NoServiceConfigured ); let (on_first_tx, on_first_rx) = oneshot::channel(); let me = ep.id(); @@ -541,9 +541,9 @@ impl DiscoveryTask { if !ep.needs_discovery(endpoint_id, MAX_AGE) { return Ok(None); } - n0_error::ensure!( + n0_error::ensure_e!( !ep.discovery().is_empty(), - e!(DiscoveryError::NoServiceConfigured) + DiscoveryError::NoServiceConfigured ); let (on_first_tx, on_first_rx) = oneshot::channel(); let ep = ep.clone(); @@ -582,9 +582,9 @@ impl DiscoveryTask { ep: &Endpoint, endpoint_id: EndpointId, ) -> Result>, DiscoveryError> { - n0_error::ensure!( + n0_error::ensure_e!( !ep.discovery().is_empty(), - e!(DiscoveryError::NoServiceConfigured) + DiscoveryError::NoServiceConfigured ); let stream = ep .discovery() diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 0165be68b6b..ad529f25f53 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -676,9 +676,9 @@ impl Endpoint { ); // Connecting to ourselves is not supported. - n0_error::ensure!( + n0_error::ensure_e!( endpoint_addr.endpoint_id != self.id(), - e!(ConnectWithOptsError::SelfConnect) + ConnectWithOptsError::SelfConnect ); if !endpoint_addr.is_empty() { diff --git a/iroh/src/key.rs b/iroh/src/key.rs index 1a4be8026d3..fa9e23f11e2 100644 --- a/iroh/src/key.rs +++ b/iroh/src/key.rs @@ -65,7 +65,7 @@ impl SharedSecret { /// Opens the ciphertext, which must have been created using `Self::seal`, and places the clear text into the provided buffer. pub fn open(&self, buffer: &mut dyn Buffer) -> Result<(), DecryptionError> { - n0_error::ensure!(buffer.len() >= NONCE_LEN, e!(DecryptionError::InvalidNonce)); + n0_error::ensure_e!(buffer.len() >= NONCE_LEN, DecryptionError::InvalidNonce); let offset = buffer.len() - NONCE_LEN; let nonce: [u8; NONCE_LEN] = buffer.as_ref()[offset..] diff --git a/iroh/src/magicsock/transports/relay/actor.rs b/iroh/src/magicsock/transports/relay/actor.rs index 1bc31c2d1ff..a34fc6ae459 100644 --- a/iroh/src/magicsock/transports/relay/actor.rs +++ b/iroh/src/magicsock/transports/relay/actor.rs @@ -365,9 +365,7 @@ impl ActiveRelayActor { /// be retried with a backoff. async fn run_once(&mut self) -> Result<(), RelayConnectionError> { let client = match self.run_dialing().instrument(info_span!("dialing")).await { - Some(client_res) => { - client_res.map_err(|err| e!(RelayConnectionError::Dial, err))? - } + Some(client_res) => client_res.map_err(|err| e!(RelayConnectionError::Dial, err))?, None => return Ok(()), }; self.run_connected(client) @@ -514,8 +512,7 @@ impl ActiveRelayActor { ); let (mut client_stream, client_sink) = client.split(); - let mut client_sink = - client_sink.sink_map_err(|e| e!(RunError::ClientStreamWrite, e)); + let mut client_sink = client_sink.sink_map_err(|e| e!(RunError::ClientStreamWrite, e)); let mut state = ConnectedRelayState { ping_tracker: PingTracker::default(), From b8564ddb0ae41874035a49051b77067596acf64d Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 27 Oct 2025 11:17:19 +0100 Subject: [PATCH 32/58] self-review --- iroh-dns-server/examples/publish.rs | 4 +-- iroh-dns-server/src/http.rs | 6 ++--- iroh-dns-server/src/http/doh/response.rs | 23 ++++++++++-------- iroh-dns-server/src/http/tls.rs | 6 ++--- iroh-dns-server/src/store/signed_packets.rs | 2 +- iroh-relay/src/protos/handshake.rs | 27 ++++++++++----------- iroh-relay/src/server/client.rs | 22 ++++++++--------- 7 files changed, 46 insertions(+), 44 deletions(-) diff --git a/iroh-dns-server/examples/publish.rs b/iroh-dns-server/examples/publish.rs index d3f051ba925..d8fd5acffb2 100644 --- a/iroh-dns-server/examples/publish.rs +++ b/iroh-dns-server/examples/publish.rs @@ -10,7 +10,7 @@ use iroh::{ }, endpoint_info::{EndpointIdExt, EndpointInfo, IROH_TXT_NAME}, }; -use n0_error::{Result, StdResultExt}; +use n0_error::{Result, StackResultExt}; use url::Url; const DEV_PKARR_RELAY_URL: &str = "http://localhost:8080/pkarr"; @@ -61,7 +61,7 @@ async fn main() -> Result<()> { let secret_key = match std::env::var("IROH_SECRET") { Ok(s) => SecretKey::from_str(&s) - .std_context("failed to parse IROH_SECRET environment variable as iroh secret key")?, + .context("failed to parse IROH_SECRET environment variable as iroh secret key")?, Err(_) => { let s = SecretKey::generate(&mut rand::rng()); println!("Generated a new endpoint secret. To reuse, set"); diff --git a/iroh-dns-server/src/http.rs b/iroh-dns-server/src/http.rs index 1eaa654744c..73671e04765 100644 --- a/iroh-dns-server/src/http.rs +++ b/iroh-dns-server/src/http.rs @@ -14,7 +14,7 @@ use axum::{ response::IntoResponse, routing::get, }; -use n0_error::{Result, StdResultExt, bail}; +use n0_error::{Result, StdResultExt, anyerr, bail}; use serde::{Deserialize, Serialize}; use tokio::{net::TcpListener, task::JoinSet}; use tower_http::{ @@ -172,11 +172,11 @@ impl HttpServer { Err(err) if err.is_cancelled() => {} Ok(Err(err)) => { warn!(?err, "task failed"); - final_res = Err(err).std_context("task"); + final_res = Err(anyerr!(err, "task")); } Err(err) => { warn!(?err, "task panicked"); - final_res = Err(err).std_context("join"); + final_res = Err(anyerr!(err, "join")); } } } diff --git a/iroh-dns-server/src/http/doh/response.rs b/iroh-dns-server/src/http/doh/response.rs index 482661c7dd4..acf1b78a382 100644 --- a/iroh-dns-server/src/http/doh/response.rs +++ b/iroh-dns-server/src/http/doh/response.rs @@ -4,7 +4,7 @@ // https://github.com/fission-codes/fission-server/blob/394de877fad021260c69fdb1edd7bb4b2f98108c/fission-core/src/dns.rs use hickory_server::proto; -use n0_error::{Result, bail}; +use n0_error::{Result, bail, ensure_any}; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] @@ -47,17 +47,20 @@ pub struct DnsResponse { impl DnsResponse { /// Create a new JSON response from a DNS message pub fn from_message(message: proto::op::Message) -> Result { - if message.message_type() != proto::op::MessageType::Response { - bail!("Expected message type to be response"); - } + ensure_any!( + message.message_type() != proto::op::MessageType::Response, + "Expected message type to be response" + ); - if message.query_count() != message.queries().len() as u16 { - bail!("Query count mismatch"); - } + ensure_any!( + message.query_count() != message.queries().len() as u16, + "Query count mismatch" + ); - if message.answer_count() != message.answers().len() as u16 { - bail!("Answer count mismatch"); - } + ensure_any!( + message.answer_count() != message.answers().len() as u16, + "Answer count mismatch" + ); let status: u32 = >::from(message.response_code()) as u32; diff --git a/iroh-dns-server/src/http/tls.rs b/iroh-dns-server/src/http/tls.rs index 96b5125c6cc..ca2f4f246d4 100644 --- a/iroh-dns-server/src/http/tls.rs +++ b/iroh-dns-server/src/http/tls.rs @@ -9,7 +9,7 @@ use axum_server::{ accept::Accept, tls_rustls::{RustlsAcceptor, RustlsConfig}, }; -use n0_error::{Result, StdResultExt, bail}; +use n0_error::{Result, StackResultExt, StdResultExt, bail}; use n0_future::{FutureExt, future::Boxed as BoxFuture}; use serde::{Deserialize, Serialize}; use tokio::io::{AsyncRead, AsyncWrite}; @@ -42,8 +42,8 @@ impl CertMode { CertMode::Manual => TlsAcceptor::manual(domains, cert_cache).await?, CertMode::SelfSigned => TlsAcceptor::self_signed(domains).await?, CertMode::LetsEncrypt => { - let contact = letsencrypt_contact - .std_context("contact is required for letsencrypt cert mode")?; + let contact = + letsencrypt_contact.context("contact is required for letsencrypt cert mode")?; TlsAcceptor::letsencrypt(domains, &contact, letsencrypt_prod, cert_cache)? } }) diff --git a/iroh-dns-server/src/store/signed_packets.rs b/iroh-dns-server/src/store/signed_packets.rs index 7c77867b607..20c9590ad9e 100644 --- a/iroh-dns-server/src/store/signed_packets.rs +++ b/iroh-dns-server/src/store/signed_packets.rs @@ -391,7 +391,7 @@ async fn evict_task(send: mpsc::Sender, options: Options, cancel: Cance if let Err(cause) = evict_task_inner(send, options).await { error!("evict task failed: {:?}", cause); } - // when we are done for bail reason we want to shut down the actor + // when we are done for whatever reason we want to shut down the actor cancel.cancel(); }) .await; diff --git a/iroh-relay/src/protos/handshake.rs b/iroh-relay/src/protos/handshake.rs index 0b211062663..1e8dc1375c4 100644 --- a/iroh-relay/src/protos/handshake.rs +++ b/iroh-relay/src/protos/handshake.rs @@ -140,16 +140,19 @@ pub enum Error { #[error(transparent)] Websocket { #[cfg(not(wasm_browser))] - #[error(std_err)] + #[error(from, std_err)] source: tokio_websockets::Error, #[cfg(wasm_browser)] - #[error(std_err)] + #[error(from, std_err)] source: ws_stream_wasm::WsErr, }, #[display("Handshake stream ended prematurely")] UnexpectedEnd {}, #[error(transparent)] - FrameTypeError { source: FrameTypeError }, + FrameTypeError { + #[error(from)] + source: FrameTypeError, + }, #[display("The relay denied our authentication ({reason})")] ServerDeniedAuth { reason: String }, #[display("Unexpected tag, got {frame_type:?}, but expected one of {expected_types:?}")] @@ -491,10 +494,8 @@ async fn write_frame( .expect("serialization failed") // buffer can't become "full" without being a critical failure, datastructures shouldn't ever fail serialization .into_inner() .freeze(); - io.send(bytes) - .await - .map_err(|err| e!(Error::Websocket, err))?; - io.flush().await.map_err(|err| e!(Error::Websocket, err))?; + io.send(bytes).await?; + io.flush().await?; Ok(()) } @@ -504,12 +505,10 @@ async fn read_frame( ) -> Result<(FrameType, Bytes), Error> { let mut payload = io .try_next() - .await - .map_err(|err| e!(Error::Websocket, err))? + .await? .ok_or_else(|| e!(Error::UnexpectedEnd))?; - let frame_type = - FrameType::from_bytes(&mut payload).map_err(|err| e!(Error::FrameTypeError, err))?; + let frame_type = FrameType::from_bytes(&mut payload)?; trace!(?frame_type, "Reading frame"); n0_error::ensure_e!( expected_types.contains(&frame_type), @@ -535,7 +534,7 @@ fn deserialize_frame(frame: Bytes) -> Re mod tests { use bytes::BytesMut; use iroh_base::{PublicKey, SecretKey}; - use n0_error::{Result, StdResultExt}; + use n0_error::{Result, StackResultExt, StdResultExt}; use n0_future::{Sink, SinkExt, Stream, TryStreamExt}; use rand::SeedableRng; use tokio_util::codec::{Framed, LengthDelimitedCodec}; @@ -650,13 +649,13 @@ mod tests { async { super::clientside(&mut client_io, secret_key) .await - .std_context("clientside") + .context("clientside") } .instrument(info_span!("clientside")), async { let auth_n = super::serverside(&mut server_io, client_auth_header) .await - .std_context("serverside")?; + .context("serverside")?; let mechanism = auth_n.mechanism; let is_authorized = restricted_to.is_none_or(|key| key == auth_n.client_key); let key = auth_n.authorize_if(is_authorized, &mut server_io).await?; diff --git a/iroh-relay/src/server/client.rs b/iroh-relay/src/server/client.rs index bfb9dcb9a72..216edcac97e 100644 --- a/iroh-relay/src/server/client.rs +++ b/iroh-relay/src/server/client.rs @@ -327,28 +327,30 @@ impl Actor { maybe_frame = self.stream.next() => { self .handle_frame(maybe_frame) - .await - .map_err(|source| e!(RunError::HandleFrame { source }))?; + .await?; // reset the ping interval, we just received a message ping_interval.reset(); } // First priority, disco packets packet = self.disco_send_queue.recv() => { - let packet = packet.ok_or_else(|| e!(RunError::DiscoSendQueuePacketDrop))?; - self.send_disco_packet(packet).await + let packet = packet.ok_or_else(|| e!(RunError::DiscoSendQueuePacketDrop))?; + self.send_disco_packet(packet) + .await .map_err(|err| e!(RunError::DiscoPacketSend, err))?; } // Second priority, sending regular packets packet = self.send_queue.recv() => { - let packet = packet.ok_or_else(|| e!(RunError::SendQueuePacketDrop))?; - self.send_packet(packet).await + let packet = packet.ok_or_else(|| e!(RunError::SendQueuePacketDrop))?; + self.send_packet(packet) + .await .map_err(|err| e!(RunError::PacketSend, err))?; } // Last priority, sending left endpoints endpoint_id = self.endpoint_gone.recv() => { - let endpoint_id = endpoint_id.ok_or_else(|| e!(RunError::EndpointGoneDrop))?; + let endpoint_id = endpoint_id.ok_or_else(|| e!(RunError::EndpointGoneDrop))?; trace!("endpoint_id gone: {:?}", endpoint_id); - self.write_frame(RelayToClientMsg::EndpointGone(endpoint_id)).await + self.write_frame(RelayToClientMsg::EndpointGone(endpoint_id)) + .await .map_err(|err| e!(RunError::EndpointGoneWriteFrame, err))?; } _ = self.ping_tracker.timeout() => { @@ -378,9 +380,7 @@ impl Actor { /// /// Errors if the send does not happen within the `timeout` duration async fn write_frame(&mut self, frame: RelayToClientMsg) -> Result<(), WriteFrameError> { - tokio::time::timeout(self.timeout, self.stream.send(frame)) - .await? - .map_err(|err| e!(WriteFrameError::Stream, err))?; + tokio::time::timeout(self.timeout, self.stream.send(frame)).await??; Ok(()) } From 19aab317b939be85cf125196c05ef0e144415a2f Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 27 Oct 2025 12:10:39 +0100 Subject: [PATCH 33/58] more self-review --- Cargo.lock | 4 ++-- iroh-dns-server/src/http/doh/response.rs | 2 +- iroh-relay/src/client.rs | 5 +---- iroh-relay/src/dns.rs | 19 ++++++++++--------- iroh-relay/src/server.rs | 6 +++++- iroh-relay/src/server/http_server.rs | 16 ++++++---------- 6 files changed, 25 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f1935188258..4e416060394 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2720,7 +2720,7 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#52da5e34a1d791ddb9e4588814bad6be1427b50e" +source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#967eefdcf718532ff20479b1f9bc8372b6a43e90" dependencies = [ "anyhow", "derive_more 2.0.1", @@ -2731,7 +2731,7 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#52da5e34a1d791ddb9e4588814bad6be1427b50e" +source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#967eefdcf718532ff20479b1f9bc8372b6a43e90" dependencies = [ "darling", "heck", diff --git a/iroh-dns-server/src/http/doh/response.rs b/iroh-dns-server/src/http/doh/response.rs index acf1b78a382..22eeaa5e554 100644 --- a/iroh-dns-server/src/http/doh/response.rs +++ b/iroh-dns-server/src/http/doh/response.rs @@ -4,7 +4,7 @@ // https://github.com/fission-codes/fission-server/blob/394de877fad021260c69fdb1edd7bb4b2f98108c/fission-core/src/dns.rs use hickory_server::proto; -use n0_error::{Result, bail, ensure_any}; +use n0_error::{Result, ensure_any}; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] diff --git a/iroh-relay/src/client.rs b/iroh-relay/src/client.rs index 46a21c21019..70cd3cad7c9 100644 --- a/iroh-relay/src/client.rs +++ b/iroh-relay/src/client.rs @@ -104,10 +104,7 @@ pub enum DialError { InvalidTargetPort {}, #[error(transparent)] #[cfg(not(wasm_browser))] - Dns { - #[error(std_err)] - source: DnsError, - }, + Dns { source: DnsError }, #[error(transparent)] Timeout { #[error(std_err)] diff --git a/iroh-relay/src/dns.rs b/iroh-relay/src/dns.rs index f5314d934d0..11d21cddcdd 100644 --- a/iroh-relay/src/dns.rs +++ b/iroh-relay/src/dns.rs @@ -68,10 +68,7 @@ pub type BoxIter = Box + Send + 'static>; #[non_exhaustive] pub enum DnsError { #[error(transparent)] - Timeout { - #[error(std_err)] - source: tokio::time::error::Elapsed, - }, + Timeout { source: tokio::time::error::Elapsed }, #[display("No response")] NoResponse {}, #[display("Resolve failed ipv4: {ipv4}, ipv6 {ipv6}")] @@ -83,7 +80,6 @@ pub enum DnsError { MissingHost {}, #[error(transparent)] Resolve { - #[error(std_err)] source: hickory_resolver::ResolveError, }, #[display("invalid DNS response: not a query for _iroh.z32encodedpubkey")] @@ -97,14 +93,19 @@ pub enum DnsError { #[non_exhaustive] pub enum LookupError { #[display("Malformed txt from lookup")] - ParseError { - #[error(std_err)] - source: Box, - }, + ParseError { source: ParseError }, #[display("Failed to resolve TXT record")] LookupFailed { source: DnsError }, } +/// Error returned when an input value is too long for [`crate::endpoint_info::UserData`]. +#[add_meta] +#[derive(Error)] +pub struct StaggeredError { + #[display("no calls succeeded: [{}]", errors.iter().map(|e| e.to_string()).collect::>().join(""))] + errors: Vec, +} + /// Error returned when an input value is too long for [`crate::endpoint_info::UserData`]. #[add_meta] #[derive(Error)] diff --git a/iroh-relay/src/server.rs b/iroh-relay/src/server.rs index ce0a5efdae2..ee8a24863b9 100644 --- a/iroh-relay/src/server.rs +++ b/iroh-relay/src/server.rs @@ -295,7 +295,11 @@ pub enum SpawnError { source: std::io::Error, }, #[display("Failed to bind server socket to {addr}")] - BindTcpListener { addr: SocketAddr }, + BindTcpListener { + #[error(std_err)] + source: std::io::Error, + addr: SocketAddr, + }, } /// Server task errors diff --git a/iroh-relay/src/server/http_server.rs b/iroh-relay/src/server/http_server.rs index 506aaa79440..4913ef96475 100644 --- a/iroh-relay/src/server/http_server.rs +++ b/iroh-relay/src/server/http_server.rs @@ -197,12 +197,10 @@ pub enum ServeConnectionError { #[add_meta] #[derive(Error)] #[non_exhaustive] +#[error(from_sources)] pub enum AcceptError { #[error(transparent)] - Handshake { - #[error(from)] - source: handshake::Error, - }, + Handshake { source: handshake::Error }, #[display("rate limiting misconfigured")] RateLimitingMisconfigured { source: InvalidBucketConfig }, } @@ -212,12 +210,10 @@ pub enum AcceptError { #[add_meta] #[derive(Error)] #[non_exhaustive] +#[error(from_sources)] pub enum ConnectionHandlerError { #[error(transparent)] - Accept { - #[error(from)] - source: AcceptError, - }, + Accept { source: AcceptError }, #[display("Could not downcast the upgraded connection to MaybeTlsStream")] DowncastUpgrade {}, #[display("Cannot deal with buffered data yet: {buf:?}")] @@ -342,11 +338,11 @@ impl ServerBuilder { let listener = TcpListener::bind(&addr) .await - .map_err(|_| e!(super::SpawnError::BindTcpListener { addr }))?; + .map_err(|err| e!(super::SpawnError::BindTcpListener { addr }, err))?; let addr = listener .local_addr() - .map_err(|source| e!(super::SpawnError::NoLocalAddr { source }))?; + .map_err(|err| e!(super::SpawnError::NoLocalAddr, err))?; let http_str = tls_config.as_ref().map_or("HTTP/WS", |_| "HTTPS/WSS"); info!("[{http_str}] relay: serving on {addr}"); From 83b6459648c7677bdd3b29b904878946f20e5b5d Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 27 Oct 2025 12:57:10 +0100 Subject: [PATCH 34/58] self review --- Cargo.lock | 26 +++--- iroh-relay/src/dns.rs | 98 +++++++---------------- iroh-relay/src/main.rs | 6 +- iroh-relay/src/server.rs | 27 ++----- iroh/bench/src/iroh.rs | 6 +- iroh/bench/src/quinn.rs | 2 +- iroh/examples/0rtt.rs | 2 +- iroh/examples/dht_discovery.rs | 2 +- iroh/examples/listen.rs | 2 +- iroh/examples/locally-discovered-nodes.rs | 2 +- iroh/examples/transfer.rs | 9 +-- iroh/src/disco.rs | 13 ++- iroh/src/discovery.rs | 35 +++++--- iroh/src/discovery/dns.rs | 2 +- iroh/src/discovery/pkarr.rs | 12 +-- iroh/src/endpoint.rs | 27 +++---- iroh/src/endpoint/presets.rs | 2 +- iroh/src/magicsock.rs | 8 +- iroh/src/net_report/probes.rs | 2 - iroh/src/net_report/reportgen.rs | 34 ++++---- iroh/src/protocol.rs | 1 + iroh/tests/integration.rs | 2 +- 22 files changed, 134 insertions(+), 186 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4e416060394..f1394d8cbbe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1162,7 +1162,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -1925,7 +1925,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -2330,7 +2330,7 @@ dependencies = [ [[package]] name = "iroh-metrics" version = "0.36.2" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#a3f936680259bec8e07e50f1c76370aff7bacd97" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#693a32d5dfb4bebece701b2fbfc2e965f82ef4dc" dependencies = [ "http-body-util", "hyper", @@ -2349,7 +2349,7 @@ dependencies = [ [[package]] name = "iroh-metrics-derive" version = "0.3.1" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#a3f936680259bec8e07e50f1c76370aff7bacd97" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#693a32d5dfb4bebece701b2fbfc2e965f82ef4dc" dependencies = [ "heck", "proc-macro2", @@ -2720,7 +2720,7 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#967eefdcf718532ff20479b1f9bc8372b6a43e90" +source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#652923bf05d9d27ec368c9d86d265ac258c5aa4a" dependencies = [ "anyhow", "derive_more 2.0.1", @@ -2731,7 +2731,7 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#967eefdcf718532ff20479b1f9bc8372b6a43e90" +source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#652923bf05d9d27ec368c9d86d265ac258c5aa4a" dependencies = [ "darling", "heck", @@ -2927,7 +2927,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -3398,7 +3398,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.6.1", + "socket2 0.5.10", "thiserror 2.0.17", "tokio", "tracing", @@ -3435,9 +3435,9 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.1", + "socket2 0.5.10", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -3736,7 +3736,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -4427,7 +4427,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -5213,7 +5213,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.48.0", ] [[package]] diff --git a/iroh-relay/src/dns.rs b/iroh-relay/src/dns.rs index 11d21cddcdd..a033fc75ad9 100644 --- a/iroh-relay/src/dns.rs +++ b/iroh-relay/src/dns.rs @@ -13,7 +13,7 @@ use hickory_resolver::{ name_server::TokioConnectionProvider, }; use iroh_base::EndpointId; -use n0_error::{Error, add_meta, e}; +use n0_error::{Error, StackError, add_meta, e}; use n0_future::{ StreamExt, boxed::BoxFuture, @@ -91,6 +91,7 @@ pub enum DnsError { #[add_meta] #[derive(Error)] #[non_exhaustive] +#[error(from_sources)] pub enum LookupError { #[display("Malformed txt from lookup")] ParseError { source: ParseError }, @@ -98,28 +99,19 @@ pub enum LookupError { LookupFailed { source: DnsError }, } -/// Error returned when an input value is too long for [`crate::endpoint_info::UserData`]. +/// Error returned when a staggered call fails. #[add_meta] #[derive(Error)] -pub struct StaggeredError { - #[display("no calls succeeded: [{}]", errors.iter().map(|e| e.to_string()).collect::>().join(""))] +#[display("no calls succeeded: [{}]", errors.iter().map(|e| e.to_string()).collect::>().join(""))] +pub struct StaggeredError { errors: Vec, } -/// Error returned when an input value is too long for [`crate::endpoint_info::UserData`]. -#[add_meta] -#[derive(Error)] -pub struct DnsStaggeredError { - #[display("no calls succeeded: [{}]", errors.iter().map(|e| e.to_string()).collect::>().join(""))] - errors: Vec, -} - -/// Aggregates all the lookup errors when all staggered attempts fail. -#[add_meta] -#[derive(Error)] -pub struct LookupStaggeredError { - #[display("no calls succeeded: [{}]", errors.iter().map(|e| e.to_string()).collect::>().join(""))] - errors: Vec, +impl StaggeredError { + /// Returns an iterator over all encountered errors. + pub fn iter(&self) -> impl Iterator { + self.errors.iter() + } } /// Builder for [`DnsResolver`]. @@ -253,9 +245,7 @@ impl DnsResolver { timeout: Duration, ) -> Result, DnsError> { let host = host.to_string(); - let res = time::timeout(timeout, self.0.lookup_txt(host)) - .await - .map_err(|err| e!(DnsError::Timeout, err))??; + let res = time::timeout(timeout, self.0.lookup_txt(host)).await??; Ok(res) } @@ -266,9 +256,7 @@ impl DnsResolver { timeout: Duration, ) -> Result + use, DnsError> { let host = host.to_string(); - let addrs = time::timeout(timeout, self.0.lookup_ipv4(host)) - .await - .map_err(|err| e!(DnsError::Timeout, err))??; + let addrs = time::timeout(timeout, self.0.lookup_ipv4(host)).await??; Ok(addrs.into_iter().map(IpAddr::V4)) } @@ -279,9 +267,7 @@ impl DnsResolver { timeout: Duration, ) -> Result + use, DnsError> { let host = host.to_string(); - let addrs = time::timeout(timeout, self.0.lookup_ipv6(host)) - .await - .map_err(|err| e!(DnsError::Timeout, err))??; + let addrs = time::timeout(timeout, self.0.lookup_ipv6(host)).await??; Ok(addrs.into_iter().map(IpAddr::V6)) } @@ -360,12 +346,10 @@ impl DnsResolver { host: impl ToString, timeout: Duration, delays_ms: &[u64], - ) -> Result, DnsStaggeredError> { + ) -> Result, StaggeredError> { let host = host.to_string(); let f = || self.lookup_ipv4(host.clone(), timeout); - stagger_call(f, delays_ms) - .await - .map_err(|errors| e!(DnsStaggeredError { errors })) + stagger_call(f, delays_ms).await } /// Performs an IPv6 lookup with a timeout in a staggered fashion. @@ -379,12 +363,10 @@ impl DnsResolver { host: impl ToString, timeout: Duration, delays_ms: &[u64], - ) -> Result, DnsStaggeredError> { + ) -> Result, StaggeredError> { let host = host.to_string(); let f = || self.lookup_ipv6(host.clone(), timeout); - stagger_call(f, delays_ms) - .await - .map_err(|errors| e!(DnsStaggeredError { errors })) + stagger_call(f, delays_ms).await } /// Races an IPv4 and IPv6 lookup with a timeout in a staggered fashion. @@ -399,12 +381,10 @@ impl DnsResolver { host: impl ToString, timeout: Duration, delays_ms: &[u64], - ) -> Result, DnsStaggeredError> { + ) -> Result, StaggeredError> { let host = host.to_string(); let f = || self.lookup_ipv4_ipv6(host.clone(), timeout); - stagger_call(f, delays_ms) - .await - .map_err(|errors| e!(DnsStaggeredError { errors })) + stagger_call(f, delays_ms).await } /// Looks up endpoint info by [`EndpointId`] and origin domain name. @@ -418,15 +398,8 @@ impl DnsResolver { ) -> Result { let name = endpoint_info::endpoint_domain(endpoint_id, origin); let name = endpoint_info::ensure_iroh_txt_label(name); - let lookup = self - .lookup_txt(name.clone(), DNS_TIMEOUT) - .await - .map_err(|err| e!(LookupError::LookupFailed, err))?; - let info = EndpointInfo::from_txt_lookup(name, lookup).map_err(|err| { - e!(LookupError::ParseError { - source: Box::new(err) - }) - })?; + let lookup = self.lookup_txt(name.clone(), DNS_TIMEOUT).await?; + let info = EndpointInfo::from_txt_lookup(name, lookup)?; Ok(info) } @@ -436,15 +409,8 @@ impl DnsResolver { name: &str, ) -> Result { let name = endpoint_info::ensure_iroh_txt_label(name.to_string()); - let lookup = self - .lookup_txt(name.clone(), DNS_TIMEOUT) - .await - .map_err(|err| e!(LookupError::LookupFailed, err))?; - let info = EndpointInfo::from_txt_lookup(name, lookup).map_err(|err| { - e!(LookupError::ParseError { - source: Box::new(err) - }) - })?; + let lookup = self.lookup_txt(name.clone(), DNS_TIMEOUT).await?; + let info = EndpointInfo::from_txt_lookup(name, lookup)?; Ok(info) } @@ -458,11 +424,9 @@ impl DnsResolver { &self, name: &str, delays_ms: &[u64], - ) -> Result { + ) -> Result> { let f = || self.lookup_endpoint_by_domain_name(name); - stagger_call(f, delays_ms) - .await - .map_err(|errors| e!(LookupStaggeredError { errors })) + stagger_call(f, delays_ms).await } /// Looks up endpoint info by [`EndpointId`] and origin domain name. @@ -476,11 +440,9 @@ impl DnsResolver { endpoint_id: &EndpointId, origin: &str, delays_ms: &[u64], - ) -> Result { + ) -> Result> { let f = || self.lookup_endpoint_by_id(endpoint_id, origin); - stagger_call(f, delays_ms) - .await - .map_err(|errors| e!(LookupStaggeredError { errors })) + stagger_call(f, delays_ms).await } } @@ -773,13 +735,13 @@ impl, B: Iterator> Iterator for Lookup /// ignoring any previous error. If all calls fail, an error summarizing all errors is returned. async fn stagger_call< T, - E: std::fmt::Debug + std::fmt::Display, + E: StackError + 'static, F: Fn() -> Fut, Fut: Future>, >( f: F, delays_ms: &[u64], -) -> Result> { +) -> Result> { let mut calls = n0_future::FuturesUnorderedBounded::new(delays_ms.len() + 1); // NOTE: we add the 0 delay here to have a uniform set of futures. This is more performant than // using alternatives that allow futures of different types. @@ -801,7 +763,7 @@ async fn stagger_call< } } - Err(errors) + Err(e!(StaggeredError { errors })) } fn add_jitter(delay: &u64) -> Duration { diff --git a/iroh-relay/src/main.rs b/iroh-relay/src/main.rs index 719af93d27d..cefbba46432 100644 --- a/iroh-relay/src/main.rs +++ b/iroh-relay/src/main.rs @@ -74,10 +74,8 @@ fn load_secret_key( filename: impl AsRef, ) -> Result> { let filename = filename.as_ref(); - let keyfile = std::fs::File::open(filename).std_context(format!( - "cannot open secret key file {}", - filename.display() - ))?; + let keyfile = std::fs::File::open(filename) + .with_std_context(|_| format!("cannot open secret key file {}", filename.display()))?; let mut reader = std::io::BufReader::new(keyfile); loop { diff --git a/iroh-relay/src/server.rs b/iroh-relay/src/server.rs index ee8a24863b9..81cd23e769e 100644 --- a/iroh-relay/src/server.rs +++ b/iroh-relay/src/server.rs @@ -268,35 +268,20 @@ pub struct Server { #[add_meta] #[derive(Error)] #[non_exhaustive] +#[error(std_sources)] pub enum SpawnError { #[display("Unable to get local address")] - LocalAddr { - #[error(std_err)] - source: std::io::Error, - }, + LocalAddr { source: std::io::Error }, #[display("Failed to bind QAD listener")] - QuicSpawn { - #[error(std_err)] - source: QuicSpawnError, - }, + QuicSpawn { source: QuicSpawnError }, #[display("Failed to parse TLS header")] - TlsHeaderParse { - #[error(std_err)] - source: InvalidHeaderValue, - }, + TlsHeaderParse { source: InvalidHeaderValue }, #[display("Failed to bind TcpListener")] - BindTlsListener { - #[error(std_err)] - source: std::io::Error, - }, + BindTlsListener { source: std::io::Error }, #[display("No local address")] - NoLocalAddr { - #[error(std_err)] - source: std::io::Error, - }, + NoLocalAddr { source: std::io::Error }, #[display("Failed to bind server socket to {addr}")] BindTcpListener { - #[error(std_err)] source: std::io::Error, addr: SocketAddr, }, diff --git a/iroh/bench/src/iroh.rs b/iroh/bench/src/iroh.rs index a3a23de424e..ae22a7d25e2 100644 --- a/iroh/bench/src/iroh.rs +++ b/iroh/bench/src/iroh.rs @@ -8,7 +8,7 @@ use iroh::{ Endpoint, EndpointAddr, RelayMode, RelayUrl, endpoint::{Connection, ConnectionError, RecvStream, SendStream, TransportConfig}, }; -use n0_error::{Result, StdResultExt}; +use n0_error::{Result, StackResultExt, StdResultExt}; use tracing::{trace, warn}; use crate::{ @@ -120,7 +120,7 @@ pub async fn connect_client( let connection = endpoint .connect(server_addr, ALPN) .await - .std_context("unable to connect")?; + .context("unable to connect")?; trace!("connected"); Ok((endpoint, connection)) @@ -275,7 +275,7 @@ pub async fn server(endpoint: Endpoint, opt: Opt) -> Result<()> { tokio::spawn(async move { drain_stream(&mut recv_stream, opt.read_unordered).await?; send_data_on_stream(&mut send_stream, opt.download_size).await?; - Ok::<_, n0_error::AnyError>(()) + n0_error::Ok(()) }); } diff --git a/iroh/bench/src/quinn.rs b/iroh/bench/src/quinn.rs index 9021a32a5e2..b36880b0059 100644 --- a/iroh/bench/src/quinn.rs +++ b/iroh/bench/src/quinn.rs @@ -246,7 +246,7 @@ pub async fn server(endpoint: Endpoint, opt: Opt) -> Result<()> { tokio::spawn(async move { drain_stream(&mut recv_stream, opt.read_unordered).await?; send_data_on_stream(&mut send_stream, opt.download_size).await?; - Ok::<_, n0_error::AnyError>(()) + n0_error::Ok(()) }); } diff --git a/iroh/examples/0rtt.rs b/iroh/examples/0rtt.rs index 171d7d22b12..df324519a75 100644 --- a/iroh/examples/0rtt.rs +++ b/iroh/examples/0rtt.rs @@ -163,7 +163,7 @@ async fn accept(_args: Args) -> Result<()> { send.write_all(&data).await.e()?; send.finish().e()?; connection.closed().await; - Ok::<_, n0_error::AnyError>(()) + n0_error::Ok(()) }); } }; diff --git a/iroh/examples/dht_discovery.rs b/iroh/examples/dht_discovery.rs index 02ec9af4606..213c863f9a9 100644 --- a/iroh/examples/dht_discovery.rs +++ b/iroh/examples/dht_discovery.rs @@ -100,7 +100,7 @@ async fn chat_server(args: Args) -> Result<()> { tokio::spawn( async move { tokio::io::copy(&mut tokio::io::stdin(), &mut writer).await }, ); - Ok::<_, n0_error::AnyError>(()) + n0_error::Ok(()) }); } Ok(()) diff --git a/iroh/examples/listen.rs b/iroh/examples/listen.rs index 20119419e41..5e28f4a9648 100644 --- a/iroh/examples/listen.rs +++ b/iroh/examples/listen.rs @@ -104,7 +104,7 @@ async fn main() -> Result<()> { if res.is_err() { println!("endpoint {endpoint_id} did not disconnect within 3 seconds"); } - Ok::<_, n0_error::AnyError>(()) + n0_error::Ok(()) }); } // stop with SIGINT (ctrl-c) diff --git a/iroh/examples/locally-discovered-nodes.rs b/iroh/examples/locally-discovered-nodes.rs index 3b0274d343a..eb7cd9783b2 100644 --- a/iroh/examples/locally-discovered-nodes.rs +++ b/iroh/examples/locally-discovered-nodes.rs @@ -73,7 +73,7 @@ async fn main() -> Result<()> { ep.set_user_data_for_discovery(Some(ud)); tokio::time::sleep(Duration::from_secs(3)).await; ep.close().await; - Ok::<_, n0_error::AnyError>(()) + n0_error::Ok(()) }); } diff --git a/iroh/examples/transfer.rs b/iroh/examples/transfer.rs index bea3f12e599..2a33c1cef1c 100644 --- a/iroh/examples/transfer.rs +++ b/iroh/examples/transfer.rs @@ -17,7 +17,7 @@ use iroh::{ dns::{DnsResolver, N0_DNS_ENDPOINT_ORIGIN_PROD, N0_DNS_ENDPOINT_ORIGIN_STAGING}, endpoint::ConnectionError, }; -use n0_error::{Result, StdResultExt}; +use n0_error::{Result, StackResultExt, StdResultExt}; use n0_future::task::AbortOnDropHandle; use n0_watcher::Watcher as _; use tokio_stream::StreamExt; @@ -194,9 +194,8 @@ impl EndpointArgs { let mut builder = Endpoint::builder(); let secret_key = match std::env::var("IROH_SECRET") { - Ok(s) => SecretKey::from_str(&s).std_context( - "Failed to parse IROH_SECRET environment variable as iroh secret key", - )?, + Ok(s) => SecretKey::from_str(&s) + .context("Failed to parse IROH_SECRET environment variable as iroh secret key")?, Err(_) => { let s = SecretKey::generate(&mut rand::rng()); println!("Generated a new endpoint secret. To reuse, set"); @@ -387,7 +386,7 @@ async fn provide(endpoint: Endpoint, size: u64) -> Result<()> { } else { println!("[{remote}] Disconnected"); } - Ok::<_, n0_error::AnyError>(()) + n0_error::Ok(()) }); } diff --git a/iroh/src/disco.rs b/iroh/src/disco.rs index 3d8d1a77c5f..5d5825f5786 100644 --- a/iroh/src/disco.rs +++ b/iroh/src/disco.rs @@ -25,10 +25,9 @@ use std::{ use data_encoding::HEXLOWER; use iroh_base::{PublicKey, RelayUrl}; -use n0_error::{Error, add_meta, e}; +use n0_error::{Error, add_meta, e, ensure_e}; use rand::Rng; use serde::{Deserialize, Serialize}; -// use n0_error ensure macro path-qualified use url::Url; use crate::magicsock::transports; @@ -217,7 +216,7 @@ pub struct CallMeMaybe { impl Ping { fn from_bytes(p: &[u8]) -> Result { // Deliberately lax on longer-than-expected messages, for future compatibility. - n0_error::ensure_e!(p.len() >= PING_LEN, ParseError::TooShort); + ensure_e!(p.len() >= PING_LEN, ParseError::TooShort); let tx_id: [u8; TX_LEN] = p[..TX_LEN].try_into().expect("length checked"); let raw_key = &p[TX_LEN..TX_LEN + iroh_base::PublicKey::LENGTH]; let endpoint_key = @@ -256,7 +255,7 @@ pub enum ParseError { } fn send_addr_from_bytes(p: &[u8]) -> Result { - n0_error::ensure_e!(p.len() > 2, ParseError::TooShort); + ensure_e!(p.len() > 2, ParseError::TooShort); match p[0] { 0u8 => { let bytes: [u8; EP_LENGTH] = p[1..].try_into().map_err(|_| e!(ParseError::TooShort))?; @@ -340,7 +339,7 @@ impl Pong { impl CallMeMaybe { fn from_bytes(p: &[u8]) -> Result { - n0_error::ensure_e!(p.len() % EP_LENGTH == 0, ParseError::InvalidEncoding); + ensure_e!(p.len() % EP_LENGTH == 0, ParseError::InvalidEncoding); let num_entries = p.len() / EP_LENGTH; let mut m = CallMeMaybe { @@ -379,11 +378,11 @@ impl CallMeMaybe { impl Message { /// Parses the encrypted part of the message from inside the nacl secretbox. pub fn from_bytes(p: &[u8]) -> Result { - n0_error::ensure_e!(p.len() >= 2, ParseError::TooShort); + ensure_e!(p.len() >= 2, ParseError::TooShort); let t = MessageType::try_from(p[0]).map_err(|_| e!(ParseError::UnknownFormat))?; let version = p[1]; - n0_error::ensure_e!(version == V0, ParseError::UnknownFormat); + ensure_e!(version == V0, ParseError::UnknownFormat); let p = &p[2..]; match t { diff --git a/iroh/src/discovery.rs b/iroh/src/discovery.rs index 44eb52452f8..15d59236b31 100644 --- a/iroh/src/discovery.rs +++ b/iroh/src/discovery.rs @@ -113,7 +113,7 @@ use std::sync::{Arc, RwLock}; use iroh_base::{EndpointAddr, EndpointId}; -use n0_error::{AnyError, Error, add_meta, e}; +use n0_error::{AnyError, Error, add_meta, e, ensure_e}; use n0_future::{ boxed::BoxStream, stream::StreamExt, @@ -235,6 +235,7 @@ pub enum DiscoveryError { impl DiscoveryError { /// Creates a new user error from an arbitrary error type. + #[track_caller] pub fn from_err( provenance: &'static str, source: T, @@ -246,6 +247,7 @@ impl DiscoveryError { } /// Creates a new user error from an arbitrary boxed error type. + #[track_caller] pub fn from_err_box( provenance: &'static str, source: Box, @@ -255,6 +257,15 @@ impl DiscoveryError { source: AnyError::from_std_box(source) }) } + + /// Creates a new user error from an arbitrary error type that can be converted into [`AnyError`]. + #[track_caller] + pub fn from_err_any(provenance: &'static str, source: impl Into) -> Self { + e!(DiscoveryError::User { + provenance, + source: source.into() + }) + } } /// Endpoint discovery for [`super::Endpoint`]. @@ -507,7 +518,7 @@ pub(super) struct DiscoveryTask { impl DiscoveryTask { /// Starts a discovery task. pub(super) fn start(ep: Endpoint, endpoint_id: EndpointId) -> Result { - n0_error::ensure_e!( + ensure_e!( !ep.discovery().is_empty(), DiscoveryError::NoServiceConfigured ); @@ -541,7 +552,7 @@ impl DiscoveryTask { if !ep.needs_discovery(endpoint_id, MAX_AGE) { return Ok(None); } - n0_error::ensure_e!( + ensure_e!( !ep.discovery().is_empty(), DiscoveryError::NoServiceConfigured ); @@ -582,7 +593,7 @@ impl DiscoveryTask { ep: &Endpoint, endpoint_id: EndpointId, ) -> Result>, DiscoveryError> { - n0_error::ensure_e!( + ensure_e!( !ep.discovery().is_empty(), DiscoveryError::NoServiceConfigured ); @@ -970,7 +981,7 @@ mod tests { mod test_dns_pkarr { use iroh_base::{EndpointAddr, SecretKey, TransportAddr}; use iroh_relay::{RelayMap, endpoint_info::UserData}; - use n0_error::{AnyError as Error, Result, StdResultExt}; + use n0_error::{AnyError as Error, Result, StackResultExt, StdResultExt}; use n0_future::time::Duration; use rand::{CryptoRng, SeedableRng}; use tokio_util::task::AbortOnDropHandle; @@ -996,7 +1007,7 @@ mod test_dns_pkarr { let state = State::new(origin.clone()); let (nameserver, _dns_drop_guard) = run_dns_server(state.clone()) .await - .std_context("Running DNS server")?; + .context("Running DNS server")?; let secret_key = SecretKey::generate(&mut rng); let endpoint_info = EndpointInfo::new(secret_key.public()) @@ -1004,7 +1015,7 @@ mod test_dns_pkarr { let signed_packet = endpoint_info.to_pkarr_signed_packet(&secret_key, 30)?; state .upsert(signed_packet) - .std_context("update and insert signed packet")?; + .context("update and insert signed packet")?; let resolver = DnsResolver::with_nameserver(nameserver); let resolved = resolver @@ -1024,7 +1035,7 @@ mod test_dns_pkarr { let dns_pkarr_server = DnsPkarrServer::run_with_origin(origin.clone()) .await - .std_context("DnsPkarrServer")?; + .context("DnsPkarrServer")?; let secret_key = SecretKey::generate(&mut rng); let endpoint_id = secret_key.public(); @@ -1044,7 +1055,7 @@ mod test_dns_pkarr { dns_pkarr_server .on_endpoint(&endpoint_id, PUBLISH_TIMEOUT) .await - .std_context("wait for on endpoint update")?; + .context("wait for on endpoint update")?; let resolved = resolver .lookup_endpoint_by_id(&endpoint_id, &origin) .await?; @@ -1067,9 +1078,7 @@ mod test_dns_pkarr { async fn pkarr_publish_dns_discover() -> Result<()> { let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(0u64); - let dns_pkarr_server = DnsPkarrServer::run() - .await - .std_context("DnsPkarrServer run")?; + let dns_pkarr_server = DnsPkarrServer::run().await.context("DnsPkarrServer run")?; let (relay_map, _relay_url, _relay_guard) = run_relay_server().await?; let (ep1, _guard1) = ep_with_discovery(&mut rng, &relay_map, &dns_pkarr_server).await?; @@ -1079,7 +1088,7 @@ mod test_dns_pkarr { dns_pkarr_server .on_endpoint(&ep1.id(), PUBLISH_TIMEOUT) .await - .std_context("wait for on endpoint update")?; + .context("wait for on endpoint update")?; // we connect only by endpoint id! let _conn = ep2.connect(ep1.id(), TEST_ALPN).await?; diff --git a/iroh/src/discovery/dns.rs b/iroh/src/discovery/dns.rs index bcfe90cef74..52437dbd0ef 100644 --- a/iroh/src/discovery/dns.rs +++ b/iroh/src/discovery/dns.rs @@ -113,7 +113,7 @@ impl Discovery for DnsDiscovery { let endpoint_info = resolver .lookup_endpoint_by_id_staggered(&endpoint_id, &origin_domain, DNS_STAGGERING_MS) .await - .map_err(|e| DiscoveryError::from_err("dns", e))?; + .map_err(|e| DiscoveryError::from_err_any("dns", e))?; Ok(DiscoveryItem::new(endpoint_info, "dns", None)) }; let stream = n0_future::stream::once_future(fut); diff --git a/iroh/src/discovery/pkarr.rs b/iroh/src/discovery/pkarr.rs index 4478654bd6a..5821ba8ce59 100644 --- a/iroh/src/discovery/pkarr.rs +++ b/iroh/src/discovery/pkarr.rs @@ -110,7 +110,7 @@ pub enum PkarrError { impl From for DiscoveryError { fn from(err: PkarrError) -> Self { - DiscoveryError::from_err("pkarr", err) + DiscoveryError::from_err_any("pkarr", err) } } @@ -407,7 +407,7 @@ impl PublisherService { ); let signed_packet = info .to_pkarr_signed_packet(&self.secret_key, self.ttl) - .map_err(|source| e!(PkarrError::Encoding { source }))?; + .map_err(|err| e!(PkarrError::Encoding, err))?; self.pkarr_client.publish(&signed_packet).await?; Ok(()) } @@ -517,7 +517,7 @@ impl Discovery for PkarrResolver { let fut = async move { let signed_packet = pkarr_client.resolve(endpoint_id).await?; let info = EndpointInfo::from_pkarr_signed_packet(&signed_packet) - .map_err(|err| DiscoveryError::from_err("pkarr", err))?; + .map_err(|err| DiscoveryError::from_err_any("pkarr", err))?; let item = DiscoveryItem::new(info, "pkarr", None); Ok(item) }; @@ -563,7 +563,7 @@ impl PkarrRelayClient { pub async fn resolve(&self, endpoint_id: EndpointId) -> Result { // We map the error to string, as in browsers the error is !Send let public_key = pkarr::PublicKey::try_from(endpoint_id.as_bytes()) - .map_err(|source| e!(PkarrError::PublicKey { source }))?; + .map_err(|err| e!(PkarrError::PublicKey, err))?; let mut url = self.pkarr_relay_url.clone(); url.path_segments_mut() @@ -579,7 +579,7 @@ impl PkarrRelayClient { .get(url) .send() .await - .map_err(|source| e!(PkarrError::HttpSend { source }))?; + .map_err(|err| e!(PkarrError::HttpSend, err))?; if !response.status().is_success() { return Err(e!(PkarrError::HttpRequest { @@ -594,7 +594,7 @@ impl PkarrRelayClient { .map_err(|source| e!(PkarrError::HttpPayload { source }))?; // We map the error to string, as in browsers the error is !Send let packet = SignedPacket::from_relay_payload(&public_key, &payload) - .map_err(|source| e!(PkarrError::Verify { source }))?; + .map_err(|err| e!(PkarrError::Verify, err))?; Ok(packet) } diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index feb754dceb7..3f3c111493b 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -485,6 +485,7 @@ pub struct Endpoint { #[add_meta] #[derive(Error)] #[non_exhaustive] +#[error(from_sources)] pub enum ConnectWithOptsError { #[error(transparent)] AddEndpointAddr { source: AddEndpointAddrError }, @@ -682,8 +683,7 @@ impl Endpoint { ); if !endpoint_addr.is_empty() { - self.add_endpoint_addr(endpoint_addr.clone(), Source::App) - .map_err(|err| e!(ConnectWithOptsError::AddEndpointAddr, err))?; + self.add_endpoint_addr(endpoint_addr.clone(), Source::App)?; } let endpoint_id = endpoint_addr.id; let ip_addresses: Vec<_> = endpoint_addr.ip_addrs().cloned().collect(); @@ -695,8 +695,7 @@ impl Endpoint { // still running task. let (mapped_addr, _discovery_drop_guard) = self .get_mapping_addr_and_maybe_start_discovery(endpoint_addr) - .await - .map_err(|err| e!(ConnectWithOptsError::NoAddress, err))?; + .await?; let transport_config = options .transport_config @@ -724,15 +723,11 @@ impl Endpoint { }; let server_name = &tls::name::encode(endpoint_id); - let connect = self - .msock - .endpoint() - .connect_with( - client_config, - mapped_addr.private_socket_addr(), - server_name, - ) - .map_err(|err| e!(ConnectWithOptsError::Quinn, err))?; + let connect = self.msock.endpoint().connect_with( + client_config, + mapped_addr.private_socket_addr(), + server_name, + )?; Ok(Connecting { inner: connect, @@ -1283,11 +1278,11 @@ impl Endpoint { // path to the remote endpoint. let res = DiscoveryTask::start(self.clone(), endpoint_id); let mut discovery = - res.map_err(|source| e!(GetMappingAddressError::DiscoveryStart { source }))?; + res.map_err(|err| e!(GetMappingAddressError::DiscoveryStart, err))?; discovery .first_arrived() .await - .map_err(|source| e!(GetMappingAddressError::Discover { source }))?; + .map_err(|err| e!(GetMappingAddressError::Discover, err))?; if let Some(addr) = self.msock.get_mapping_addr(endpoint_id) { Ok((addr, Some(discovery))) } else { @@ -3045,7 +3040,7 @@ mod tests { let incoming = server.accept().await.e()?; let conn = incoming.await.e()?; conn.close(0u32.into(), b"bye!"); - Ok::<_, n0_error::AnyError>(conn.alpn()) + n0_error::Ok(conn.alpn()) } }); diff --git a/iroh/src/endpoint/presets.rs b/iroh/src/endpoint/presets.rs index 6952eb4b0f8..8732c074f73 100644 --- a/iroh/src/endpoint/presets.rs +++ b/iroh/src/endpoint/presets.rs @@ -3,7 +3,7 @@ //! # Example //! //! ```no_run -//! # async fn wrapper() -> n0_error::Result<()> { +//! # async fn wrapper() -> n0_error::Result { //! use iroh::{Endpoint, RelayMode, Watcher, endpoint::presets}; //! //! let endpoint = Endpoint::empty_builder(RelayMode::Disabled) diff --git a/iroh/src/magicsock.rs b/iroh/src/magicsock.rs index 38b046891dc..873108b5f1a 100644 --- a/iroh/src/magicsock.rs +++ b/iroh/src/magicsock.rs @@ -1389,7 +1389,7 @@ impl Handle { #[cfg(not(wasm_browser))] let (ip_transports, port_mapper) = bind_ip(addr_v4, addr_v6, &metrics) - .map_err(|source| e!(CreateHandleError::BindSockets { source }))?; + .map_err(|err| e!(CreateHandleError::BindSockets, err))?; let ip_mapped_addrs = IpMappedAddresses::default(); @@ -1479,11 +1479,11 @@ impl Handle { #[cfg(wasm_browser)] Arc::new(crate::web_runtime::WebRuntime), ) - .map_err(|source| e!(CreateHandleError::CreateQuinnEndpoint { source }))?; + .map_err(|err| e!(CreateHandleError::CreateQuinnEndpoint, err))?; let network_monitor = netmon::Monitor::new() .await - .map_err(|source| e!(CreateHandleError::CreateNetmonMonitor { source }))?; + .map_err(|err| e!(CreateHandleError::CreateNetmonMonitor, err))?; let qad_endpoint = endpoint.clone(); @@ -2915,7 +2915,7 @@ mod tests { conn.closed().await; } - Ok::<_, n0_error::AnyError>(()) + n0_error::Ok(()) } })); diff --git a/iroh/src/net_report/probes.rs b/iroh/src/net_report/probes.rs index 45e5d28aa05..92884ca3eca 100644 --- a/iroh/src/net_report/probes.rs +++ b/iroh/src/net_report/probes.rs @@ -51,8 +51,6 @@ pub(super) struct ProbeSet { probes: Vec<(Duration, Arc)>, } -// Removed legacy SNAFU error (unused) during error migration. - impl ProbeSet { fn new(proto: Probe) -> Self { Self { diff --git a/iroh/src/net_report/reportgen.rs b/iroh/src/net_report/reportgen.rs index 544183c792c..0f9b6f06e90 100644 --- a/iroh/src/net_report/reportgen.rs +++ b/iroh/src/net_report/reportgen.rs @@ -30,7 +30,7 @@ use iroh_relay::{ }; #[cfg(not(wasm_browser))] use iroh_relay::{ - dns::{DnsResolver, DnsStaggeredError as StaggeredError}, + dns::{DnsError, DnsResolver, StaggeredError}, quic::QuicClient, }; use n0_error::{Error, add_meta, e}; @@ -538,7 +538,10 @@ pub(super) fn maybe_to_mapped_addr( #[non_exhaustive] enum CaptivePortalError { #[error(transparent)] - DnsLookup { source: StaggeredError }, + DnsLookup { + #[error(from)] + source: StaggeredError, + }, #[display("Creating HTTP client failed")] CreateReqwestClient { #[error(std_err)] @@ -594,15 +597,14 @@ async fn check_captive_portal( // them. But our resolver doesn't support that yet. let addrs: Vec<_> = dns_resolver .lookup_ipv4_ipv6_staggered(domain, DNS_TIMEOUT, DNS_STAGGERING_MS) - .await - .map_err(|source| e!(CaptivePortalError::DnsLookup { source }))? + .await? .map(|ipaddr| SocketAddr::new(ipaddr, 0)) .collect(); builder = builder.resolve_to_addrs(domain, &addrs); } let client = builder .build() - .map_err(|source| e!(CaptivePortalError::CreateReqwestClient { source }))?; + .map_err(|err| e!(CaptivePortalError::CreateReqwestClient, err))?; // Note: the set of valid characters in a challenge and the total // length is limited; see is_challenge_char in bin/iroh-relay for more @@ -616,7 +618,7 @@ async fn check_captive_portal( .header("X-Iroh-Challenge", &challenge) .send() .await - .map_err(|source| e!(CaptivePortalError::HttpRequest { source }))?; + .map_err(|err| e!(CaptivePortalError::HttpRequest, err))?; let expected_response = format!("response {challenge}"); let is_valid_response = res @@ -660,7 +662,7 @@ pub enum GetRelayAddrError { #[display("No suitable relay address found")] NoAddrFound, #[display("DNS lookup failed")] - DnsLookup { source: StaggeredError }, + DnsLookup { source: StaggeredError }, #[display("Relay is not suitable")] UnsupportedRelay, #[display("HTTPS probes are not implemented")] @@ -759,12 +761,15 @@ async fn relay_lookup_ipv6_staggered( pub enum MeasureHttpsLatencyError { #[error(transparent)] InvalidUrl { - #[error(std_err)] + #[error(std_err, from)] source: url::ParseError, }, #[cfg(not(wasm_browser))] #[error(transparent)] - DnsLookup { source: StaggeredError }, + DnsLookup { + #[error(from)] + source: StaggeredError, + }, #[display("Creating HTTP client failed")] CreateReqwestClient { #[error(std_err)] @@ -790,9 +795,7 @@ async fn run_https_probe( #[cfg(any(test, feature = "test-utils"))] insecure_skip_relay_cert_verify: bool, ) -> Result { trace!("HTTPS probe start"); - let url = relay - .join(RELAY_PROBE_PATH) - .map_err(|source| e!(MeasureHttpsLatencyError::InvalidUrl { source }))?; + let url = relay.join(RELAY_PROBE_PATH)?; // This should also use same connection establishment as relay client itself, which // needs to be more configurable so users can do more crazy things: @@ -815,8 +818,7 @@ async fn run_https_probe( // IPv6 though. But our resolver does not have a function for that yet. let addrs: Vec<_> = dns_resolver .lookup_ipv4_ipv6_staggered(domain, DNS_TIMEOUT, DNS_STAGGERING_MS) - .await - .map_err(|source| e!(MeasureHttpsLatencyError::DnsLookup { source }))? + .await? .map(|ipaddr| SocketAddr::new(ipaddr, 0)) .collect(); trace!(?addrs, "resolved addrs"); @@ -828,14 +830,14 @@ async fn run_https_probe( let client = builder .build() - .map_err(|source| e!(MeasureHttpsLatencyError::CreateReqwestClient { source }))?; + .map_err(|err| e!(MeasureHttpsLatencyError::CreateReqwestClient, err))?; let start = Instant::now(); let response = client .request(reqwest::Method::GET, url) .send() .await - .map_err(|source| e!(MeasureHttpsLatencyError::HttpRequest { source }))?; + .map_err(|err| e!(MeasureHttpsLatencyError::HttpRequest, err))?; let latency = start.elapsed(); if response.status().is_success() { // Drain the response body to be nice to the server, up to a limit. diff --git a/iroh/src/protocol.rs b/iroh/src/protocol.rs index b2b3f9f95e6..8e932c68967 100644 --- a/iroh/src/protocol.rs +++ b/iroh/src/protocol.rs @@ -121,6 +121,7 @@ pub enum AcceptError { impl AcceptError { /// Creates a new user error from an arbitrary error type. + #[track_caller] pub fn from_err(value: T) -> Self { e!(AcceptError::User { source: AnyError::from_std(value) diff --git a/iroh/tests/integration.rs b/iroh/tests/integration.rs index cb27febd721..04b97490042 100644 --- a/iroh/tests/integration.rs +++ b/iroh/tests/integration.rs @@ -78,7 +78,7 @@ async fn simple_endpoint_id_based_connection_transfer() -> Result { tracing::info!("Closed with code: {code:?}"); } - Ok::<_, n0_error::AnyError>(()) + n0_error::Ok(()) } .instrument(info_span!("server")) }); From 83934ea477eeb157b50b0159ee75dea5cd8fe4f0 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 27 Oct 2025 13:01:05 +0100 Subject: [PATCH 35/58] bump n0-error --- Cargo.lock | 178 +++++++++++++++++-------------------- iroh-base/Cargo.toml | 2 +- iroh-dns-server/Cargo.toml | 2 +- iroh-relay/Cargo.toml | 2 +- iroh/Cargo.toml | 2 +- iroh/bench/Cargo.toml | 2 +- 6 files changed, 88 insertions(+), 100 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f1394d8cbbe..d7d70c6e6ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -174,7 +174,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", "synstructure", ] @@ -186,7 +186,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -210,7 +210,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -318,7 +318,7 @@ checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -466,9 +466,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.41" +version = "1.2.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" +checksum = "739eb0f94557554b3ca9a86d2d37bebd49c5e6d0c1d2bda35ba5bdac830befc2" dependencies = [ "find-msvc-tools", "shlex", @@ -586,7 +586,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -862,7 +862,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -886,7 +886,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.107", + "syn", ] [[package]] @@ -897,7 +897,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -947,9 +947,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", ] @@ -980,7 +980,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", "unicode-xid", ] @@ -992,7 +992,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", "unicode-xid", ] @@ -1048,7 +1048,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -1064,9 +1064,9 @@ dependencies = [ [[package]] name = "document-features" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" dependencies = [ "litrs", ] @@ -1137,7 +1137,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -1162,7 +1162,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1323,7 +1323,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -1925,7 +1925,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.1", "tokio", "tower-service", "tracing", @@ -2101,9 +2101,9 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a646d946d06bedbbc4cac4c218acf4bbf2d87757a784857025f4d447e4e1cd" +checksum = "e2e0ddd45fe8e09ee1a607920b12271f8a5528a41ecaf6e1d1440d6493315b6b" dependencies = [ "console", "portable-atomic", @@ -2330,7 +2330,7 @@ dependencies = [ [[package]] name = "iroh-metrics" version = "0.36.2" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#693a32d5dfb4bebece701b2fbfc2e965f82ef4dc" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#4f0ce37c94d5564035e18b333424a89a2cb6bbef" dependencies = [ "http-body-util", "hyper", @@ -2349,12 +2349,12 @@ dependencies = [ [[package]] name = "iroh-metrics-derive" version = "0.3.1" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#693a32d5dfb4bebece701b2fbfc2e965f82ef4dc" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#4f0ce37c94d5564035e18b333424a89a2cb6bbef" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -2477,9 +2477,9 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -2570,9 +2570,9 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "litrs" -version = "0.4.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" [[package]] name = "lock_api" @@ -2720,7 +2720,7 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#652923bf05d9d27ec368c9d86d265ac258c5aa4a" +source = "git+https://github.com/n0-computer/n0-error?branch=main#9a672e6ea960a202f761f686b4afe1ce507aaba7" dependencies = [ "anyhow", "derive_more 2.0.1", @@ -2731,13 +2731,13 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fdev#652923bf05d9d27ec368c9d86d265ac258c5aa4a" +source = "git+https://github.com/n0-computer/n0-error?branch=main#9a672e6ea960a202f761f686b4afe1ce507aaba7" dependencies = [ "darling", "heck", "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -2774,14 +2774,14 @@ dependencies = [ [[package]] name = "nested_enum_utils" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43fa9161ed44d30e9702fe42bd78693bceac0fed02f647da749f36109023d3a3" +checksum = "b1d5475271bdd36a4a2769eac1ef88df0f99428ea43e52dfd8b0ee5cb674695f" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -2927,7 +2927,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2983,7 +2983,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -3016,9 +3016,9 @@ dependencies = [ [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "oorandom" @@ -3125,7 +3125,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -3279,7 +3279,7 @@ checksum = "e0232bd009a197ceec9cc881ba46f727fcd8060a2d8d6a9dde7a69030a6fe2bb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -3337,23 +3337,22 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb0be07becd10686a0bb407298fb425360a5c44a663774406340c59a22de4ce" +checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" dependencies = [ "bit-set", "bit-vec", "bitflags", - "lazy_static", "num-traits", "rand 0.9.2", "rand_chacha 0.9.0", @@ -3398,7 +3397,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.5.10", + "socket2 0.6.1", "thiserror 2.0.17", "tokio", "tracing", @@ -3435,9 +3434,9 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.1", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -3736,14 +3735,14 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.33" +version = "0.23.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "751e04a496ca00bb97a5e043158d23d66b5aabf2e1d5aa2a0aaebb1aafe6f82c" +checksum = "6a9586e9ee2b4f8fab52a0048ca7334d7024eef48e2cb9407e3497bb7cab7fa7" dependencies = [ "log", "once_cell", @@ -3812,9 +3811,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" dependencies = [ "web-time", "zeroize", @@ -3947,9 +3946,9 @@ dependencies = [ [[package]] name = "self_cell" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749" +checksum = "16c2f82143577edb4921b71ede051dac62ca3c16084e918bf7b40c96ae10eb33" [[package]] name = "semver" @@ -4021,7 +4020,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -4197,7 +4196,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -4228,7 +4227,7 @@ checksum = "c87e960f4dca2788eeb86bbdde8dd246be8948790b7618d656e68f9b720a86e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -4297,7 +4296,7 @@ dependencies = [ "proc-macro2", "quote", "struct_iterable_internal", - "syn 2.0.107", + "syn", ] [[package]] @@ -4324,7 +4323,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -4335,9 +4334,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "swarm-discovery" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eae338a4551897c6a50fa2c041c4b75f578962d9fca8adb828cf81f7158740f" +checksum = "790d8444f7db1e88f70aed3234cab8e42c48e05360bfc86ca7dce0d9a5d95d26" dependencies = [ "acto", "hickory-proto", @@ -4350,20 +4349,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.107" +version = "2.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a26dbd934e5451d21ef060c018dae56fc073894c5a7896f882928a76e6d081b" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" dependencies = [ "proc-macro2", "quote", @@ -4387,7 +4375,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -4427,7 +4415,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4456,7 +4444,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -4467,7 +4455,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -4573,7 +4561,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -4797,7 +4785,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -4869,7 +4857,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -5052,7 +5040,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.107", + "syn", "wasm-bindgen-shared", ] @@ -5087,7 +5075,7 @@ checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5122,7 +5110,7 @@ checksum = "b673bca3298fe582aeef8352330ecbad91849f85090805582400850f8270a2e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -5213,7 +5201,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] @@ -5321,7 +5309,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -5332,7 +5320,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -5851,7 +5839,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", "synstructure", ] @@ -5878,7 +5866,7 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -5898,7 +5886,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", "synstructure", ] @@ -5919,7 +5907,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] [[package]] @@ -5952,5 +5940,5 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.107", + "syn", ] diff --git a/iroh-base/Cargo.toml b/iroh-base/Cargo.toml index 56a614a7a35..a409c2eaf47 100644 --- a/iroh-base/Cargo.toml +++ b/iroh-base/Cargo.toml @@ -22,7 +22,7 @@ derive_more = { version = "2.0.1", features = ["display"], optional = true } url = { version = "2.5.3", features = ["serde"], optional = true } rand_core = { version = "0.9.3", optional = true } serde = { version = "1", features = ["derive", "rc"] } -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/dev" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } zeroize = { version = "1.8.2", optional = true, features = ["derive"] } zeroize_derive = { version = "1.4.2", optional = true } # needed for minimal versions diff --git a/iroh-dns-server/Cargo.toml b/iroh-dns-server/Cargo.toml index 719dd571bb4..bb5e24fe3d1 100644 --- a/iroh-dns-server/Cargo.toml +++ b/iroh-dns-server/Cargo.toml @@ -39,7 +39,7 @@ rustls = { version = "0.23.33", default-features = false, features = ["ring"] } rustls-pemfile = { version = "2.1" } serde = { version = "1", features = ["derive"] } struct_iterable = "0.1.1" -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/dev" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } strum = { version = "0.27", features = ["derive"] } tokio = { version = "1", features = ["full"] } tokio-rustls = { version = "0.26", default-features = false, features = [ diff --git a/iroh-relay/Cargo.toml b/iroh-relay/Cargo.toml index f1aecc64bca..02bdd62650f 100644 --- a/iroh-relay/Cargo.toml +++ b/iroh-relay/Cargo.toml @@ -70,7 +70,7 @@ webpki_types = { package = "rustls-pki-types", version = "1.12" } data-encoding = "2.6.0" lru = "0.16" z32 = "1.0.3" -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/dev" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } # server feature clap = { version = "4", features = ["derive"], optional = true } diff --git a/iroh/Cargo.toml b/iroh/Cargo.toml index e591d3ace79..de2fbe3007f 100644 --- a/iroh/Cargo.toml +++ b/iroh/Cargo.toml @@ -39,7 +39,7 @@ http = "1" iroh-base = { version = "0.94.1", default-features = false, features = ["key", "relay"], path = "../iroh-base" } iroh-relay = { version = "0.94", path = "../iroh-relay", default-features = false } n0-future = "0.3.0" -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/dev" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } n0-watcher = "0.4" nested_enum_utils = "0.2.1" netwatch = { version = "0.11" } diff --git a/iroh/bench/Cargo.toml b/iroh/bench/Cargo.toml index 41dce22fc6a..1c44f5e30c7 100644 --- a/iroh/bench/Cargo.toml +++ b/iroh/bench/Cargo.toml @@ -11,7 +11,7 @@ hdrhistogram = { version = "7.2", default-features = false } iroh = { path = ".." } iroh-metrics = "0.36" n0-future = "0.3.0" -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/dev" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } quinn = { package = "iroh-quinn", version = "0.14" } rand = "0.9.2" rcgen = "0.14" From b2f2975fb313ec1676b9a48068e185551e55257f Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 27 Oct 2025 13:12:32 +0100 Subject: [PATCH 36/58] adapt for changes in n0-error --- Cargo.lock | 26 +++++++++++++------------- iroh-relay/src/client/conn.rs | 4 ++-- iroh-relay/src/endpoint_info.rs | 4 ++-- iroh-relay/src/protos/handshake.rs | 4 ++-- iroh-relay/src/protos/relay.rs | 22 +++++++++++----------- iroh-relay/src/server/http_server.rs | 6 +++--- iroh-relay/src/server/streams.rs | 6 +++--- iroh/src/disco.rs | 12 ++++++------ iroh/src/discovery.rs | 8 ++++---- iroh/src/endpoint.rs | 6 +++--- iroh/src/key.rs | 2 +- 11 files changed, 50 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d7d70c6e6ea..49f61b480f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1162,7 +1162,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -1925,7 +1925,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -2330,7 +2330,7 @@ dependencies = [ [[package]] name = "iroh-metrics" version = "0.36.2" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#4f0ce37c94d5564035e18b333424a89a2cb6bbef" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#e894b7340426b909c73952e00464ec1bc315c71a" dependencies = [ "http-body-util", "hyper", @@ -2349,7 +2349,7 @@ dependencies = [ [[package]] name = "iroh-metrics-derive" version = "0.3.1" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#4f0ce37c94d5564035e18b333424a89a2cb6bbef" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#e894b7340426b909c73952e00464ec1bc315c71a" dependencies = [ "heck", "proc-macro2", @@ -2720,7 +2720,7 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=main#9a672e6ea960a202f761f686b4afe1ce507aaba7" +source = "git+https://github.com/n0-computer/n0-error?branch=main#ce4cfe034c5590bf90bbef5699939b487e487f82" dependencies = [ "anyhow", "derive_more 2.0.1", @@ -2731,7 +2731,7 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=main#9a672e6ea960a202f761f686b4afe1ce507aaba7" +source = "git+https://github.com/n0-computer/n0-error?branch=main#ce4cfe034c5590bf90bbef5699939b487e487f82" dependencies = [ "darling", "heck", @@ -2927,7 +2927,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -3397,7 +3397,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.6.1", + "socket2 0.5.10", "thiserror 2.0.17", "tokio", "tracing", @@ -3434,9 +3434,9 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.1", + "socket2 0.5.10", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -3735,7 +3735,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -4415,7 +4415,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -5201,7 +5201,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.48.0", ] [[package]] diff --git a/iroh-relay/src/client/conn.rs b/iroh-relay/src/client/conn.rs index 6e1955670d0..3604ceefcd7 100644 --- a/iroh-relay/src/client/conn.rs +++ b/iroh-relay/src/client/conn.rs @@ -139,12 +139,12 @@ impl Sink for Conn { fn start_send(mut self: Pin<&mut Self>, frame: ClientToRelayMsg) -> Result<(), Self::Error> { let size = frame.encoded_len(); - n0_error::ensure_e!( + n0_error::ensure!( size <= MAX_PACKET_SIZE, SendError::ExceedsMaxPacketSize { size } ); if let ClientToRelayMsg::Datagrams { datagrams, .. } = &frame { - n0_error::ensure_e!(!datagrams.contents.is_empty(), SendError::EmptyPacket); + n0_error::ensure!(!datagrams.contents.is_empty(), SendError::EmptyPacket); } Pin::new(&mut self.conn) diff --git a/iroh-relay/src/endpoint_info.rs b/iroh-relay/src/endpoint_info.rs index aceec005bbc..b43c5fd20a5 100644 --- a/iroh-relay/src/endpoint_info.rs +++ b/iroh-relay/src/endpoint_info.rs @@ -254,7 +254,7 @@ impl TryFrom for UserData { type Error = MaxLengthExceededError; fn try_from(value: String) -> Result { - n0_error::ensure_e!(value.len() <= Self::MAX_LENGTH, MaxLengthExceededError); + n0_error::ensure!(value.len() <= Self::MAX_LENGTH, MaxLengthExceededError); Ok(Self(value)) } } @@ -263,7 +263,7 @@ impl FromStr for UserData { type Err = MaxLengthExceededError; fn from_str(s: &str) -> std::result::Result { - n0_error::ensure_e!(s.len() <= Self::MAX_LENGTH, MaxLengthExceededError); + n0_error::ensure!(s.len() <= Self::MAX_LENGTH, MaxLengthExceededError); Ok(Self(s.to_string())) } } diff --git a/iroh-relay/src/protos/handshake.rs b/iroh-relay/src/protos/handshake.rs index 1e8dc1375c4..263fae47d1f 100644 --- a/iroh-relay/src/protos/handshake.rs +++ b/iroh-relay/src/protos/handshake.rs @@ -304,7 +304,7 @@ impl KeyMaterialClientAuth { // there must be something wrong with the client's secret key or signature. let (message, suffix) = key_material.split_at(16); let suffix: [u8; 16] = suffix.try_into().expect("hardcoded length"); - n0_error::ensure_e!( + n0_error::ensure!( suffix == self.key_material_suffix, VerificationError::MismatchedSuffix { expected: self.key_material_suffix, @@ -510,7 +510,7 @@ async fn read_frame( let frame_type = FrameType::from_bytes(&mut payload)?; trace!(?frame_type, "Reading frame"); - n0_error::ensure_e!( + n0_error::ensure!( expected_types.contains(&frame_type), Error::UnexpectedFrameType { frame_type, diff --git a/iroh-relay/src/protos/relay.rs b/iroh-relay/src/protos/relay.rs index b702165eac6..32295762947 100644 --- a/iroh-relay/src/protos/relay.rs +++ b/iroh-relay/src/protos/relay.rs @@ -222,9 +222,9 @@ impl Datagrams { fn from_bytes(mut bytes: Bytes, is_batch: bool) -> Result { if is_batch { // 1 bytes ECN, 2 bytes segment size - n0_error::ensure_e!(bytes.len() >= 3, Error::InvalidFrame); + n0_error::ensure!(bytes.len() >= 3, Error::InvalidFrame); } else { - n0_error::ensure_e!(bytes.len() >= 1, Error::InvalidFrame); + n0_error::ensure!(bytes.len() >= 1, Error::InvalidFrame); } let ecn_byte = bytes.get_u8(); @@ -331,14 +331,14 @@ impl RelayToClientMsg { pub(crate) fn from_bytes(mut content: Bytes, cache: &KeyCache) -> Result { let frame_type = FrameType::from_bytes(&mut content)?; let frame_len = content.len(); - n0_error::ensure_e!( + n0_error::ensure!( frame_len <= MAX_PACKET_SIZE, Error::FrameTooLarge { frame_len } ); let res = match frame_type { FrameType::RelayToClientDatagram | FrameType::RelayToClientDatagramBatch => { - n0_error::ensure_e!(content.len() >= EndpointId::LENGTH, Error::InvalidFrame); + n0_error::ensure!(content.len() >= EndpointId::LENGTH, Error::InvalidFrame); let remote_endpoint_id = cache.key_from_slice(&content[..EndpointId::LENGTH])?; let datagrams = Datagrams::from_bytes( @@ -351,18 +351,18 @@ impl RelayToClientMsg { } } FrameType::EndpointGone => { - n0_error::ensure_e!(content.len() == EndpointId::LENGTH, Error::InvalidFrame); + n0_error::ensure!(content.len() == EndpointId::LENGTH, Error::InvalidFrame); let endpoint_id = cache.key_from_slice(content.as_ref())?; Self::EndpointGone(endpoint_id) } FrameType::Ping => { - n0_error::ensure_e!(content.len() == 8, Error::InvalidFrame); + n0_error::ensure!(content.len() == 8, Error::InvalidFrame); let mut data = [0u8; 8]; data.copy_from_slice(&content[..8]); Self::Ping(data) } FrameType::Pong => { - n0_error::ensure_e!(content.len() == 8, Error::InvalidFrame); + n0_error::ensure!(content.len() == 8, Error::InvalidFrame); let mut data = [0u8; 8]; data.copy_from_slice(&content[..8]); Self::Pong(data) @@ -372,7 +372,7 @@ impl RelayToClientMsg { Self::Health { problem } } FrameType::Restarting => { - n0_error::ensure_e!(content.len() == 4 + 4, Error::InvalidFrame); + n0_error::ensure!(content.len() == 4 + 4, Error::InvalidFrame); let reconnect_in = u32::from_be_bytes( content[..4] .try_into() @@ -459,7 +459,7 @@ impl ClientToRelayMsg { pub(crate) fn from_bytes(mut content: Bytes, cache: &KeyCache) -> Result { let frame_type = FrameType::from_bytes(&mut content)?; let frame_len = content.len(); - n0_error::ensure_e!( + n0_error::ensure!( frame_len <= MAX_PACKET_SIZE, Error::FrameTooLarge { frame_len } ); @@ -477,13 +477,13 @@ impl ClientToRelayMsg { } } FrameType::Ping => { - n0_error::ensure_e!(content.len() == 8, Error::InvalidFrame); + n0_error::ensure!(content.len() == 8, Error::InvalidFrame); let mut data = [0u8; 8]; data.copy_from_slice(&content[..8]); Self::Ping(data) } FrameType::Pong => { - n0_error::ensure_e!(content.len() == 8, Error::InvalidFrame); + n0_error::ensure!(content.len() == 8, Error::InvalidFrame); let mut data = [0u8; 8]; data.copy_from_slice(&content[..8]); Self::Pong(data) diff --git a/iroh-relay/src/server/http_server.rs b/iroh-relay/src/server/http_server.rs index 4913ef96475..0debc67f1ac 100644 --- a/iroh-relay/src/server/http_server.rs +++ b/iroh-relay/src/server/http_server.rs @@ -460,7 +460,7 @@ impl RelayService { } let upgrade_header = expect_header(&req, UPGRADE)?; - n0_error::ensure_e!( + n0_error::ensure!( upgrade_header == HeaderValue::from_static(WEBSOCKET_UPGRADE_PROTOCOL), RelayUpgradeReqError::InvalidHeader { header: UPGRADE, @@ -471,7 +471,7 @@ impl RelayService { let key = expect_header(&req, SEC_WEBSOCKET_KEY)?.clone(); let version = expect_header(&req, SEC_WEBSOCKET_VERSION)?.clone(); - n0_error::ensure_e!( + n0_error::ensure!( version.as_bytes() == SUPPORTED_WEBSOCKET_VERSION.as_bytes(), RelayUpgradeReqError::UnsupportedWebsocketVersion ); @@ -488,7 +488,7 @@ impl RelayService { let supports_our_version = subprotocols .split_whitespace() .any(|p| p == RELAY_PROTOCOL_VERSION); - n0_error::ensure_e!( + n0_error::ensure!( supports_our_version, RelayUpgradeReqError::UnsupportedRelayVersion { we_support: RELAY_PROTOCOL_VERSION, diff --git a/iroh-relay/src/server/streams.rs b/iroh-relay/src/server/streams.rs index bd1723f245a..d29e0ab5f84 100644 --- a/iroh-relay/src/server/streams.rs +++ b/iroh-relay/src/server/streams.rs @@ -99,12 +99,12 @@ impl Sink for RelayedStream { fn start_send(mut self: Pin<&mut Self>, item: RelayToClientMsg) -> Result<(), Self::Error> { let size = item.encoded_len(); - n0_error::ensure_e!( + n0_error::ensure!( size <= MAX_PACKET_SIZE, SendError::ExceedsMaxPacketSize { size } ); if let RelayToClientMsg::Datagrams { datagrams, .. } = &item { - n0_error::ensure_e!(!datagrams.contents.is_empty(), SendError::EmptyPacket); + n0_error::ensure!(!datagrams.contents.is_empty(), SendError::EmptyPacket); } Pin::new(&mut self.inner) @@ -306,7 +306,7 @@ impl Bucket { ) -> Result { // milliseconds is the tokio timer resolution let refill = bytes_per_second.saturating_mul(refill_period.as_millis() as i64) / 1000; - n0_error::ensure_e!( + n0_error::ensure!( max > 0 && bytes_per_second > 0 && refill_period.as_millis() as u32 > 0 && refill > 0, InvalidBucketConfig { max, diff --git a/iroh/src/disco.rs b/iroh/src/disco.rs index 5d5825f5786..ad04bcf330d 100644 --- a/iroh/src/disco.rs +++ b/iroh/src/disco.rs @@ -25,7 +25,7 @@ use std::{ use data_encoding::HEXLOWER; use iroh_base::{PublicKey, RelayUrl}; -use n0_error::{Error, add_meta, e, ensure_e}; +use n0_error::{Error, add_meta, e, ensure}; use rand::Rng; use serde::{Deserialize, Serialize}; use url::Url; @@ -216,7 +216,7 @@ pub struct CallMeMaybe { impl Ping { fn from_bytes(p: &[u8]) -> Result { // Deliberately lax on longer-than-expected messages, for future compatibility. - ensure_e!(p.len() >= PING_LEN, ParseError::TooShort); + ensure!(p.len() >= PING_LEN, ParseError::TooShort); let tx_id: [u8; TX_LEN] = p[..TX_LEN].try_into().expect("length checked"); let raw_key = &p[TX_LEN..TX_LEN + iroh_base::PublicKey::LENGTH]; let endpoint_key = @@ -255,7 +255,7 @@ pub enum ParseError { } fn send_addr_from_bytes(p: &[u8]) -> Result { - ensure_e!(p.len() > 2, ParseError::TooShort); + ensure!(p.len() > 2, ParseError::TooShort); match p[0] { 0u8 => { let bytes: [u8; EP_LENGTH] = p[1..].try_into().map_err(|_| e!(ParseError::TooShort))?; @@ -339,7 +339,7 @@ impl Pong { impl CallMeMaybe { fn from_bytes(p: &[u8]) -> Result { - ensure_e!(p.len() % EP_LENGTH == 0, ParseError::InvalidEncoding); + ensure!(p.len() % EP_LENGTH == 0, ParseError::InvalidEncoding); let num_entries = p.len() / EP_LENGTH; let mut m = CallMeMaybe { @@ -378,11 +378,11 @@ impl CallMeMaybe { impl Message { /// Parses the encrypted part of the message from inside the nacl secretbox. pub fn from_bytes(p: &[u8]) -> Result { - ensure_e!(p.len() >= 2, ParseError::TooShort); + ensure!(p.len() >= 2, ParseError::TooShort); let t = MessageType::try_from(p[0]).map_err(|_| e!(ParseError::UnknownFormat))?; let version = p[1]; - ensure_e!(version == V0, ParseError::UnknownFormat); + ensure!(version == V0, ParseError::UnknownFormat); let p = &p[2..]; match t { diff --git a/iroh/src/discovery.rs b/iroh/src/discovery.rs index 15d59236b31..a9691e54713 100644 --- a/iroh/src/discovery.rs +++ b/iroh/src/discovery.rs @@ -113,7 +113,7 @@ use std::sync::{Arc, RwLock}; use iroh_base::{EndpointAddr, EndpointId}; -use n0_error::{AnyError, Error, add_meta, e, ensure_e}; +use n0_error::{AnyError, Error, add_meta, e, ensure}; use n0_future::{ boxed::BoxStream, stream::StreamExt, @@ -518,7 +518,7 @@ pub(super) struct DiscoveryTask { impl DiscoveryTask { /// Starts a discovery task. pub(super) fn start(ep: Endpoint, endpoint_id: EndpointId) -> Result { - ensure_e!( + ensure!( !ep.discovery().is_empty(), DiscoveryError::NoServiceConfigured ); @@ -552,7 +552,7 @@ impl DiscoveryTask { if !ep.needs_discovery(endpoint_id, MAX_AGE) { return Ok(None); } - ensure_e!( + ensure!( !ep.discovery().is_empty(), DiscoveryError::NoServiceConfigured ); @@ -593,7 +593,7 @@ impl DiscoveryTask { ep: &Endpoint, endpoint_id: EndpointId, ) -> Result>, DiscoveryError> { - ensure_e!( + ensure!( !ep.discovery().is_empty(), DiscoveryError::NoServiceConfigured ); diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 3f3c111493b..a36cca1ac13 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -23,7 +23,7 @@ use std::{ use ed25519_dalek::{VerifyingKey, pkcs8::DecodePublicKey}; use iroh_base::{EndpointAddr, EndpointId, RelayUrl, SecretKey, TransportAddr}; use iroh_relay::{RelayConfig, RelayMap}; -use n0_error::{Error, add_meta, e, ensure_e}; +use n0_error::{Error, add_meta, e, ensure}; use n0_future::time::Duration; use n0_watcher::Watcher; use pin_project::pin_project; @@ -677,7 +677,7 @@ impl Endpoint { ); // Connecting to ourselves is not supported. - ensure_e!( + ensure!( endpoint_addr.id != self.id(), ConnectWithOptsError::SelfConnect ); @@ -782,7 +782,7 @@ impl Endpoint { source: Source, ) -> Result<(), AddEndpointAddrError> { // Connecting to ourselves is not supported. - ensure_e!( + ensure!( endpoint_addr.id != self.id(), AddEndpointAddrError::OwnAddress ); diff --git a/iroh/src/key.rs b/iroh/src/key.rs index fa9e23f11e2..57ed242857b 100644 --- a/iroh/src/key.rs +++ b/iroh/src/key.rs @@ -65,7 +65,7 @@ impl SharedSecret { /// Opens the ciphertext, which must have been created using `Self::seal`, and places the clear text into the provided buffer. pub fn open(&self, buffer: &mut dyn Buffer) -> Result<(), DecryptionError> { - n0_error::ensure_e!(buffer.len() >= NONCE_LEN, DecryptionError::InvalidNonce); + n0_error::ensure!(buffer.len() >= NONCE_LEN, DecryptionError::InvalidNonce); let offset = buffer.len() - NONCE_LEN; let nonce: [u8; NONCE_LEN] = buffer.as_ref()[offset..] From 2aa1031d8c11a433897e6c73993157b70a182753 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 27 Oct 2025 16:31:15 +0100 Subject: [PATCH 37/58] refactor: bump n0-error, rename #display to #error --- Cargo.lock | 24 +++++------ iroh-base/src/key.rs | 4 +- iroh-base/src/relay_url.rs | 2 +- iroh-relay/src/client.rs | 30 +++++++------- iroh-relay/src/client/conn.rs | 4 +- iroh-relay/src/dns.rs | 14 +++---- iroh-relay/src/endpoint_info.rs | 20 +++++----- iroh-relay/src/protos/common.rs | 4 +- iroh-relay/src/protos/handshake.rs | 14 +++---- iroh-relay/src/protos/relay.rs | 14 +++---- iroh-relay/src/quic.rs | 4 +- iroh-relay/src/server.rs | 20 +++++----- iroh-relay/src/server/client.rs | 22 +++++----- iroh-relay/src/server/http_server.rs | 28 ++++++------- iroh-relay/src/server/streams.rs | 4 +- iroh/src/disco.rs | 6 +-- iroh/src/discovery.rs | 8 ++-- iroh/src/discovery/pkarr.rs | 14 +++---- iroh/src/endpoint.rs | 18 ++++----- iroh/src/key.rs | 4 +- iroh/src/magicsock.rs | 22 +++++----- iroh/src/magicsock/endpoint_map.rs | 2 +- .../magicsock/endpoint_map/endpoint_state.rs | 14 +++---- iroh/src/magicsock/transports/relay/actor.rs | 24 +++++------ iroh/src/net_report.rs | 10 ++--- iroh/src/net_report/ip_mapped_addrs.rs | 2 +- iroh/src/net_report/reportgen.rs | 40 +++++++++---------- iroh/src/protocol.rs | 2 +- iroh/src/tls/resolver.rs | 2 +- 29 files changed, 188 insertions(+), 188 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 49f61b480f9..765a815dea8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1162,7 +1162,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1925,7 +1925,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.1", "tokio", "tower-service", "tracing", @@ -2330,7 +2330,7 @@ dependencies = [ [[package]] name = "iroh-metrics" version = "0.36.2" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#e894b7340426b909c73952e00464ec1bc315c71a" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#46c6eb6ebea8136f6470beeddac34895ed3c08c7" dependencies = [ "http-body-util", "hyper", @@ -2349,7 +2349,7 @@ dependencies = [ [[package]] name = "iroh-metrics-derive" version = "0.3.1" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#e894b7340426b909c73952e00464ec1bc315c71a" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#46c6eb6ebea8136f6470beeddac34895ed3c08c7" dependencies = [ "heck", "proc-macro2", @@ -2720,7 +2720,7 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=main#ce4cfe034c5590bf90bbef5699939b487e487f82" +source = "git+https://github.com/n0-computer/n0-error?branch=main#00defd8204754d53ab2c3145acffc279bd4f9de0" dependencies = [ "anyhow", "derive_more 2.0.1", @@ -2731,7 +2731,7 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=main#ce4cfe034c5590bf90bbef5699939b487e487f82" +source = "git+https://github.com/n0-computer/n0-error?branch=main#00defd8204754d53ab2c3145acffc279bd4f9de0" dependencies = [ "darling", "heck", @@ -2927,7 +2927,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3397,7 +3397,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.5.10", + "socket2 0.6.1", "thiserror 2.0.17", "tokio", "tracing", @@ -3434,9 +3434,9 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.1", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -3735,7 +3735,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4415,7 +4415,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/iroh-base/src/key.rs b/iroh-base/src/key.rs index 1719581984e..aee22bb05ff 100644 --- a/iroh-base/src/key.rs +++ b/iroh-base/src/key.rs @@ -215,7 +215,7 @@ pub enum KeyParsingError { #[error(transparent)] Key(ed25519_dalek::SignatureError), /// The encoded information had the wrong length. - #[display("invalid length")] + #[error("invalid length")] DecodeInvalidLength, } @@ -415,7 +415,7 @@ impl Signature { /// Verification of a signature failed. #[add_meta] #[derive(Error)] -#[display("Invalid signature")] +#[error("Invalid signature")] pub struct SignatureError {} fn decode_base32_hex(s: &str) -> Result<[u8; 32], KeyParsingError> { diff --git a/iroh-base/src/relay_url.rs b/iroh-base/src/relay_url.rs index 374c7e15ee1..73b555b6dfd 100644 --- a/iroh-base/src/relay_url.rs +++ b/iroh-base/src/relay_url.rs @@ -41,7 +41,7 @@ impl From for RelayUrl { /// Can occur when parsing a string into a [`RelayUrl`]. #[add_meta] #[derive(Error)] -#[display("Failed to parse relay URL")] +#[error("Failed to parse relay URL")] pub struct RelayUrlParseError(#[error(std_err)] url::ParseError); /// Support for parsing strings directly. diff --git a/iroh-relay/src/client.rs b/iroh-relay/src/client.rs index 70cd3cad7c9..0c020c90f3e 100644 --- a/iroh-relay/src/client.rs +++ b/iroh-relay/src/client.rs @@ -52,9 +52,9 @@ mod util; #[allow(missing_docs)] #[non_exhaustive] pub enum ConnectError { - #[display("Invalid URL for websocket: {url}")] + #[error("Invalid URL for websocket: {url}")] InvalidWebsocketUrl { url: Url }, - #[display("Invalid relay URL: {url}")] + #[error("Invalid relay URL: {url}")] InvalidRelayUrl { url: Url }, #[error(transparent)] Websocket { @@ -72,24 +72,24 @@ pub enum ConnectError { }, #[error(transparent)] Dial { source: DialError }, - #[display("Unexpected status during upgrade: {code}")] + #[error("Unexpected status during upgrade: {code}")] UnexpectedUpgradeStatus { code: hyper::StatusCode }, - #[display("Failed to upgrade response")] + #[error("Failed to upgrade response")] Upgrade { #[error(std_err)] source: hyper::Error, }, - #[display("Invalid TLS servername")] + #[error("Invalid TLS servername")] InvalidTlsServername {}, - #[display("No local address available")] + #[error("No local address available")] NoLocalAddr {}, - #[display("tls connection failed")] + #[error("tls connection failed")] Tls { #[error(std_err)] source: std::io::Error, }, #[cfg(wasm_browser)] - #[display("The relay protocol is not available in browsers")] + #[error("The relay protocol is not available in browsers")] RelayProtoNotAvailable {}, } @@ -100,7 +100,7 @@ pub enum ConnectError { #[allow(missing_docs)] #[non_exhaustive] pub enum DialError { - #[display("Invliad target port")] + #[error("Invliad target port")] InvalidTargetPort {}, #[error(transparent)] #[cfg(not(wasm_browser))] @@ -115,20 +115,20 @@ pub enum DialError { #[error(std_err)] source: std::io::Error, }, - #[display("Invalid URL: {url}")] + #[error("Invalid URL: {url}")] InvalidUrl { url: Url }, - #[display("Failed proxy connection: {status}")] + #[error("Failed proxy connection: {status}")] ProxyConnectInvalidStatus { status: hyper::StatusCode }, - #[display("Invalid Proxy URL {proxy_url}")] + #[error("Invalid Proxy URL {proxy_url}")] ProxyInvalidUrl { proxy_url: Url }, - #[display("failed to establish proxy connection")] + #[error("failed to establish proxy connection")] ProxyConnect { #[error(std_err)] source: hyper::Error, }, - #[display("Invalid proxy TLS servername: {proxy_hostname}")] + #[error("Invalid proxy TLS servername: {proxy_hostname}")] ProxyInvalidTlsServername { proxy_hostname: String }, - #[display("Invalid proxy target port")] + #[error("Invalid proxy target port")] ProxyInvalidTargetPort {}, } diff --git a/iroh-relay/src/client/conn.rs b/iroh-relay/src/client/conn.rs index 3604ceefcd7..8d0cc7a9a58 100644 --- a/iroh-relay/src/client/conn.rs +++ b/iroh-relay/src/client/conn.rs @@ -38,9 +38,9 @@ pub enum SendError { #[cfg(wasm_browser)] source: ws_stream_wasm::WsErr, }, - #[display("Exceeds max packet size ({MAX_PACKET_SIZE}): {size}")] + #[error("Exceeds max packet size ({MAX_PACKET_SIZE}): {size}")] ExceedsMaxPacketSize { size: usize }, - #[display("Attempted to send empty packet")] + #[error("Attempted to send empty packet")] EmptyPacket {}, } diff --git a/iroh-relay/src/dns.rs b/iroh-relay/src/dns.rs index a033fc75ad9..ee9c6d56c42 100644 --- a/iroh-relay/src/dns.rs +++ b/iroh-relay/src/dns.rs @@ -69,20 +69,20 @@ pub type BoxIter = Box + Send + 'static>; pub enum DnsError { #[error(transparent)] Timeout { source: tokio::time::error::Elapsed }, - #[display("No response")] + #[error("No response")] NoResponse {}, - #[display("Resolve failed ipv4: {ipv4}, ipv6 {ipv6}")] + #[error("Resolve failed ipv4: {ipv4}, ipv6 {ipv6}")] ResolveBoth { ipv4: Box, ipv6: Box, }, - #[display("missing host")] + #[error("missing host")] MissingHost {}, #[error(transparent)] Resolve { source: hickory_resolver::ResolveError, }, - #[display("invalid DNS response: not a query for _iroh.z32encodedpubkey")] + #[error("invalid DNS response: not a query for _iroh.z32encodedpubkey")] InvalidResponse {}, } @@ -93,16 +93,16 @@ pub enum DnsError { #[non_exhaustive] #[error(from_sources)] pub enum LookupError { - #[display("Malformed txt from lookup")] + #[error("Malformed txt from lookup")] ParseError { source: ParseError }, - #[display("Failed to resolve TXT record")] + #[error("Failed to resolve TXT record")] LookupFailed { source: DnsError }, } /// Error returned when a staggered call fails. #[add_meta] #[derive(Error)] -#[display("no calls succeeded: [{}]", errors.iter().map(|e| e.to_string()).collect::>().join(""))] +#[error("no calls succeeded: [{}]", errors.iter().map(|e| e.to_string()).collect::>().join(""))] pub struct StaggeredError { errors: Vec, } diff --git a/iroh-relay/src/endpoint_info.rs b/iroh-relay/src/endpoint_info.rs index b43c5fd20a5..0414443e1b1 100644 --- a/iroh-relay/src/endpoint_info.rs +++ b/iroh-relay/src/endpoint_info.rs @@ -57,7 +57,7 @@ pub enum EncodingError { #[error(std_err)] source: pkarr::errors::SignedPacketBuildError, }, - #[display("invalid TXT entry")] + #[error("invalid TXT entry")] InvalidTxtEntry { #[error(std_err)] source: pkarr::dns::SimpleDnsError, @@ -69,14 +69,14 @@ pub enum EncodingError { #[derive(Error)] #[non_exhaustive] pub enum DecodingError { - #[display("endpoint id was not encoded in valid z32")] + #[error("endpoint id was not encoded in valid z32")] InvalidEncodingZ32 { #[error(std_err)] source: z32::Z32Error, }, - #[display("length must be 32 bytes, but got {len} byte(s)")] + #[error("length must be 32 bytes, but got {len} byte(s)")] InvalidLength { len: usize }, - #[display("endpoint id is not a valid public key")] + #[error("endpoint id is not a valid public key")] InvalidKey { source: KeyParsingError }, } @@ -247,7 +247,7 @@ impl UserData { #[allow(missing_docs)] #[add_meta] #[derive(Error)] -#[display("max length exceeded")] +#[error("max length exceeded")] pub struct MaxLengthExceededError {} impl TryFrom for UserData { @@ -431,18 +431,18 @@ impl EndpointInfo { #[error(from_sources)] #[non_exhaustive] pub enum ParseError { - #[display("Expected format `key=value`, received `{s}`")] + #[error("Expected format `key=value`, received `{s}`")] UnexpectedFormat { s: String }, - #[display("Could not convert key to Attr")] + #[error("Could not convert key to Attr")] AttrFromString { key: String }, - #[display("Expected 2 labels, received {num_labels}")] + #[error("Expected 2 labels, received {num_labels}")] NumLabels { num_labels: usize }, - #[display("Could not parse labels")] + #[error("Could not parse labels")] Utf8 { #[error(std_err)] source: Utf8Error, }, - #[display("Record is not an `iroh` record, expected `_iroh`, got `{label}`")] + #[error("Record is not an `iroh` record, expected `_iroh`, got `{label}`")] NotAnIrohRecord { label: String }, #[error(transparent)] DecodingError { source: DecodingError }, diff --git a/iroh-relay/src/protos/common.rs b/iroh-relay/src/protos/common.rs index 09c7bead6e9..d98f92ed3ce 100644 --- a/iroh-relay/src/protos/common.rs +++ b/iroh-relay/src/protos/common.rs @@ -60,12 +60,12 @@ pub enum FrameType { #[allow(missing_docs)] #[non_exhaustive] pub enum FrameTypeError { - #[display("not enough bytes to parse frame type")] + #[error("not enough bytes to parse frame type")] UnexpectedEnd { #[error(std_err)] source: UnexpectedEnd, }, - #[display("frame type unknown")] + #[error("frame type unknown")] UnknownFrameType { tag: VarInt }, } diff --git a/iroh-relay/src/protos/handshake.rs b/iroh-relay/src/protos/handshake.rs index 263fae47d1f..6bc8be7fa00 100644 --- a/iroh-relay/src/protos/handshake.rs +++ b/iroh-relay/src/protos/handshake.rs @@ -146,21 +146,21 @@ pub enum Error { #[error(from, std_err)] source: ws_stream_wasm::WsErr, }, - #[display("Handshake stream ended prematurely")] + #[error("Handshake stream ended prematurely")] UnexpectedEnd {}, #[error(transparent)] FrameTypeError { #[error(from)] source: FrameTypeError, }, - #[display("The relay denied our authentication ({reason})")] + #[error("The relay denied our authentication ({reason})")] ServerDeniedAuth { reason: String }, - #[display("Unexpected tag, got {frame_type:?}, but expected one of {expected_types:?}")] + #[error("Unexpected tag, got {frame_type:?}, but expected one of {expected_types:?}")] UnexpectedFrameType { frame_type: FrameType, expected_types: Vec, }, - #[display("Handshake failed while deserializing {frame_type:?} frame")] + #[error("Handshake failed while deserializing {frame_type:?} frame")] DeserializationError { frame_type: FrameType, #[error(std_err)] @@ -175,16 +175,16 @@ pub enum Error { #[add_meta] #[derive(Error)] pub(crate) enum VerificationError { - #[display("Couldn't export TLS keying material on our end")] + #[error("Couldn't export TLS keying material on our end")] NoKeyingMaterial, - #[display( + #[error( "Client didn't extract the same keying material, the suffix mismatched: expected {expected:X?} but got {actual:X?}" )] MismatchedSuffix { expected: [u8; 16], actual: [u8; 16], }, - #[display( + #[error( "Client signature {signature:X?} for message {message:X?} invalid for public key {public_key}" )] SignatureInvalid { diff --git a/iroh-relay/src/protos/relay.rs b/iroh-relay/src/protos/relay.rs index 32295762947..e5cc4f6578a 100644 --- a/iroh-relay/src/protos/relay.rs +++ b/iroh-relay/src/protos/relay.rs @@ -46,9 +46,9 @@ pub(crate) const PER_CLIENT_SEND_QUEUE_DEPTH: usize = 512; #[allow(missing_docs)] #[non_exhaustive] pub enum Error { - #[display("unexpected frame: got {got:?}, expected {expected:?}")] + #[error("unexpected frame: got {got:?}, expected {expected:?}")] UnexpectedFrame { got: FrameType, expected: FrameType }, - #[display("Frame is too large, has {frame_len} bytes")] + #[error("Frame is too large, has {frame_len} bytes")] FrameTooLarge { frame_len: usize }, #[error(transparent)] SerDe { @@ -57,18 +57,18 @@ pub enum Error { }, #[error(transparent)] FrameTypeError { source: FrameTypeError }, - #[display("Invalid public key")] + #[error("Invalid public key")] InvalidPublicKey { source: KeyParsingError }, - #[display("Invalid frame encoding")] + #[error("Invalid frame encoding")] InvalidFrame {}, - #[display("Invalid frame type: {frame_type:?}")] + #[error("Invalid frame type: {frame_type:?}")] InvalidFrameType { frame_type: FrameType }, - #[display("Invalid protocol message encoding")] + #[error("Invalid protocol message encoding")] InvalidProtocolMessageEncoding { #[error(std_err)] source: std::str::Utf8Error, }, - #[display("Too few bytes")] + #[error("Too few bytes")] TooSmall {}, } diff --git a/iroh-relay/src/quic.rs b/iroh-relay/src/quic.rs index 98bffe1db2a..c2080e0dab6 100644 --- a/iroh-relay/src/quic.rs +++ b/iroh-relay/src/quic.rs @@ -45,12 +45,12 @@ pub(crate) mod server { #[error(std_err, from)] source: NoInitialCipherSuite, }, - #[display("Unable to spawn a QUIC endpoint server")] + #[error("Unable to spawn a QUIC endpoint server")] EndpointServer { #[error(std_err)] source: std::io::Error, }, - #[display("Unable to get the local address from the endpoint")] + #[error("Unable to get the local address from the endpoint")] LocalAddr { #[error(std_err)] source: std::io::Error, diff --git a/iroh-relay/src/server.rs b/iroh-relay/src/server.rs index 81cd23e769e..578b6cf9eab 100644 --- a/iroh-relay/src/server.rs +++ b/iroh-relay/src/server.rs @@ -270,17 +270,17 @@ pub struct Server { #[non_exhaustive] #[error(std_sources)] pub enum SpawnError { - #[display("Unable to get local address")] + #[error("Unable to get local address")] LocalAddr { source: std::io::Error }, - #[display("Failed to bind QAD listener")] + #[error("Failed to bind QAD listener")] QuicSpawn { source: QuicSpawnError }, - #[display("Failed to parse TLS header")] + #[error("Failed to parse TLS header")] TlsHeaderParse { source: InvalidHeaderValue }, - #[display("Failed to bind TcpListener")] + #[error("Failed to bind TcpListener")] BindTlsListener { source: std::io::Error }, - #[display("No local address")] + #[error("No local address")] NoLocalAddr { source: std::io::Error }, - #[display("Failed to bind server socket to {addr}")] + #[error("Failed to bind server socket to {addr}")] BindTcpListener { source: std::io::Error, addr: SocketAddr, @@ -293,21 +293,21 @@ pub enum SpawnError { #[derive(Error)] #[non_exhaustive] pub enum SupervisorError { - #[display("Error starting metrics server")] + #[error("Error starting metrics server")] Metrics { #[error(std_err)] source: std::io::Error, }, - #[display("Acme event stream finished")] + #[error("Acme event stream finished")] AcmeEventStreamFinished {}, #[error(transparent)] JoinError { #[error(from, std_err)] source: JoinError, }, - #[display("No relay services are enabled")] + #[error("No relay services are enabled")] NoRelayServicesEnabled {}, - #[display("Task cancelled")] + #[error("Task cancelled")] TaskCancelled {}, } diff --git a/iroh-relay/src/server/client.rs b/iroh-relay/src/server/client.rs index 216edcac97e..29cb97c83be 100644 --- a/iroh-relay/src/server/client.rs +++ b/iroh-relay/src/server/client.rs @@ -178,7 +178,7 @@ impl Client { pub enum HandleFrameError { #[error(transparent)] ForwardPacket { source: ForwardPacketError }, - #[display("Stream terminated")] + #[error("Stream terminated")] StreamTerminated {}, #[error(transparent)] Recv { source: RelayRecvError }, @@ -213,28 +213,28 @@ pub enum RunError { #[error(from)] source: ForwardPacketError, }, - #[display("Flush")] + #[error("Flush")] Flush {}, #[error(transparent)] HandleFrame { #[error(from)] source: HandleFrameError, }, - #[display("Server.disco_send_queue dropped")] + #[error("Server.disco_send_queue dropped")] DiscoSendQueuePacketDrop {}, - #[display("Failed to send disco packet")] + #[error("Failed to send disco packet")] DiscoPacketSend { source: WriteFrameError }, - #[display("Server.send_queue dropped")] + #[error("Server.send_queue dropped")] SendQueuePacketDrop {}, - #[display("Failed to send packet")] + #[error("Failed to send packet")] PacketSend { source: WriteFrameError }, - #[display("Server.endpoint_gone dropped")] + #[error("Server.endpoint_gone dropped")] EndpointGoneDrop {}, - #[display("EndpointGone write frame failed")] + #[error("EndpointGone write frame failed")] EndpointGoneWriteFrame { source: WriteFrameError }, - #[display("Keep alive write frame failed")] + #[error("Keep alive write frame failed")] KeepAliveWriteFrame { source: WriteFrameError }, - #[display("Tick flush")] + #[error("Tick flush")] TickFlush {}, } @@ -499,7 +499,7 @@ pub(crate) enum SendError { #[add_meta] #[derive(Error)] -#[display("failed to forward {scope:?} packet: {reason:?}")] +#[error("failed to forward {scope:?} packet: {reason:?}")] pub struct ForwardPacketError { scope: PacketScope, reason: SendError, diff --git a/iroh-relay/src/server/http_server.rs b/iroh-relay/src/server/http_server.rs index 0debc67f1ac..5ee5ad65f71 100644 --- a/iroh-relay/src/server/http_server.rs +++ b/iroh-relay/src/server/http_server.rs @@ -155,37 +155,37 @@ pub(super) struct TlsConfig { #[derive(Error)] #[non_exhaustive] pub enum ServeConnectionError { - #[display("TLS[acme] handshake")] + #[error("TLS[acme] handshake")] TlsHandshake { #[error(std_err)] source: std::io::Error, }, - #[display("TLS[acme] serve connection")] + #[error("TLS[acme] serve connection")] ServeConnection { #[error(std_err)] source: hyper::Error, }, - #[display("TLS[manual] timeout")] + #[error("TLS[manual] timeout")] Timeout { #[error(std_err)] source: Elapsed, }, - #[display("TLS[manual] accept")] + #[error("TLS[manual] accept")] ManualAccept { #[error(std_err)] source: std::io::Error, }, - #[display("TLS[acme] accept")] + #[error("TLS[acme] accept")] LetsEncryptAccept { #[error(std_err)] source: std::io::Error, }, - #[display("HTTPS connection")] + #[error("HTTPS connection")] Https { #[error(std_err)] source: hyper::Error, }, - #[display("HTTP connection")] + #[error("HTTP connection")] Http { #[error(std_err)] source: hyper::Error, @@ -201,7 +201,7 @@ pub enum ServeConnectionError { pub enum AcceptError { #[error(transparent)] Handshake { source: handshake::Error }, - #[display("rate limiting misconfigured")] + #[error("rate limiting misconfigured")] RateLimitingMisconfigured { source: InvalidBucketConfig }, } @@ -214,9 +214,9 @@ pub enum AcceptError { pub enum ConnectionHandlerError { #[error(transparent)] Accept { source: AcceptError }, - #[display("Could not downcast the upgraded connection to MaybeTlsStream")] + #[error("Could not downcast the upgraded connection to MaybeTlsStream")] DowncastUpgrade {}, - #[display("Cannot deal with buffered data yet: {buf:?}")] + #[error("Cannot deal with buffered data yet: {buf:?}")] BufferNotEmpty { buf: Bytes }, } @@ -416,18 +416,18 @@ struct Inner { #[add_meta] #[derive(Error)] enum RelayUpgradeReqError { - #[display("missing header: {header}")] + #[error("missing header: {header}")] MissingHeader { header: http::HeaderName }, - #[display("invalid header value for {header}: {details}")] + #[error("invalid header value for {header}: {details}")] InvalidHeader { header: http::HeaderName, details: String, }, - #[display( + #[error( "invalid header value for {SEC_WEBSOCKET_VERSION}: unsupported websocket version, only supporting {SUPPORTED_WEBSOCKET_VERSION}" )] UnsupportedWebsocketVersion, - #[display( + #[error( "invalid header value for {SEC_WEBSOCKET_PROTOCOL}: unsupported relay version: we support {we_support} but you only provide {you_support}" )] UnsupportedRelayVersion { diff --git a/iroh-relay/src/server/streams.rs b/iroh-relay/src/server/streams.rs index d29e0ab5f84..b43560f3f1e 100644 --- a/iroh-relay/src/server/streams.rs +++ b/iroh-relay/src/server/streams.rs @@ -84,9 +84,9 @@ pub enum SendError { #[error(from, std_err)] source: StreamError, }, - #[display("Packet exceeds max packet size")] + #[error("Packet exceeds max packet size")] ExceedsMaxPacketSize { size: usize }, - #[display("Attempted to send empty packet")] + #[error("Attempted to send empty packet")] EmptyPacket {}, } diff --git a/iroh/src/disco.rs b/iroh/src/disco.rs index ad04bcf330d..235b1162532 100644 --- a/iroh/src/disco.rs +++ b/iroh/src/disco.rs @@ -246,11 +246,11 @@ impl Ping { #[derive(Error)] #[non_exhaustive] pub enum ParseError { - #[display("message is too short")] + #[error("message is too short")] TooShort, - #[display("invalid encoding")] + #[error("invalid encoding")] InvalidEncoding, - #[display("unknown format")] + #[error("unknown format")] UnknownFormat, } diff --git a/iroh/src/discovery.rs b/iroh/src/discovery.rs index a9691e54713..71aa66a04d2 100644 --- a/iroh/src/discovery.rs +++ b/iroh/src/discovery.rs @@ -185,7 +185,7 @@ impl DynIntoDiscovery for T { #[derive(Error)] #[non_exhaustive] pub enum IntoDiscoveryError { - #[display("Service '{provenance}' error")] + #[error("Service '{provenance}' error")] User { provenance: &'static str, source: AnyError, @@ -222,11 +222,11 @@ impl IntoDiscoveryError { #[derive(Error)] #[non_exhaustive] pub enum DiscoveryError { - #[display("No discovery service configured")] + #[error("No discovery service configured")] NoServiceConfigured, - #[display("Discovery produced no results for {}", endpoint_id.fmt_short())] + #[error("Discovery produced no results for {}", endpoint_id.fmt_short())] NoResults { endpoint_id: EndpointId }, - #[display("Service '{provenance}' error")] + #[error("Service '{provenance}' error")] User { provenance: &'static str, source: AnyError, diff --git a/iroh/src/discovery/pkarr.rs b/iroh/src/discovery/pkarr.rs index 5821ba8ce59..8be75ab75c6 100644 --- a/iroh/src/discovery/pkarr.rs +++ b/iroh/src/discovery/pkarr.rs @@ -80,31 +80,31 @@ pub mod dht; #[derive(Error)] #[non_exhaustive] pub enum PkarrError { - #[display("Invalid public key")] + #[error("Invalid public key")] PublicKey { #[error(std_err)] source: PublicKeyError, }, - #[display("Packet failed to verify")] + #[error("Packet failed to verify")] Verify { #[error(std_err)] source: SignedPacketVerifyError, }, - #[display("Invalid relay URL")] + #[error("Invalid relay URL")] InvalidRelayUrl { url: RelayUrl }, - #[display("Error sending http request")] + #[error("Error sending http request")] HttpSend { #[error(std_err)] source: reqwest::Error, }, - #[display("Error resolving http request")] + #[error("Error resolving http request")] HttpRequest { status: reqwest::StatusCode }, - #[display("Http payload error")] + #[error("Http payload error")] HttpPayload { #[error(std_err)] source: reqwest::Error, }, - #[display("EncodingError")] + #[error("EncodingError")] Encoding { source: EncodingError }, } diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index a36cca1ac13..f0898f1504c 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -489,11 +489,11 @@ pub struct Endpoint { pub enum ConnectWithOptsError { #[error(transparent)] AddEndpointAddr { source: AddEndpointAddrError }, - #[display("Connecting to ourself is not supported")] + #[error("Connecting to ourself is not supported")] SelfConnect, - #[display("No addressing information available")] + #[error("No addressing information available")] NoAddress { source: GetMappingAddressError }, - #[display("Unable to connect to remote")] + #[error("Unable to connect to remote")] Quinn { #[error(std_err)] source: quinn_proto::ConnectError, @@ -536,11 +536,11 @@ pub enum BindError { #[derive(Error)] #[non_exhaustive] pub enum GetMappingAddressError { - #[display("Discovery service required due to missing addressing information")] + #[error("Discovery service required due to missing addressing information")] DiscoveryStart { source: DiscoveryError }, - #[display("Discovery service failed")] + #[error("Discovery service failed")] Discover { source: DiscoveryError }, - #[display("No addressing information found")] + #[error("No addressing information found")] NoAddress, } @@ -1524,9 +1524,9 @@ pub enum AlpnError { #[error(std_err)] source: ConnectionError, }, - #[display("No ALPN available")] + #[error("No ALPN available")] Unavailable, - #[display("Unknown handshake type")] + #[error("Unknown handshake type")] UnknownHandshake, } @@ -1684,7 +1684,7 @@ pub struct Connection { #[allow(missing_docs)] #[add_meta] #[derive(Error)] -#[display("Protocol error: no remote id available")] +#[error("Protocol error: no remote id available")] pub struct RemoteEndpointIdError; impl Connection { diff --git a/iroh/src/key.rs b/iroh/src/key.rs index 57ed242857b..2e5fe9cc973 100644 --- a/iroh/src/key.rs +++ b/iroh/src/key.rs @@ -30,10 +30,10 @@ pub struct SharedSecret(crypto_box::ChaChaBox); #[non_exhaustive] pub enum DecryptionError { /// The nonce had the wrong size. - #[display("Invalid nonce")] + #[error("Invalid nonce")] InvalidNonce, /// AEAD decryption failed. - #[display("Aead error")] + #[error("Aead error")] Aead { #[error(std_err)] source: aead::Error, diff --git a/iroh/src/magicsock.rs b/iroh/src/magicsock.rs index 873108b5f1a..a770e7b940f 100644 --- a/iroh/src/magicsock.rs +++ b/iroh/src/magicsock.rs @@ -217,11 +217,11 @@ pub(crate) struct MagicSock { #[derive(Error)] #[non_exhaustive] pub enum AddEndpointAddrError { - #[display("Empty addressing info")] + #[error("Empty addressing info")] Empty, - #[display("Empty addressing info, {pruned} direct address have been pruned")] + #[error("Empty addressing info, {pruned} direct address have been pruned")] EmptyPruned { pruned: usize }, - #[display("Adding our own address is not supported")] + #[error("Adding our own address is not supported")] OwnAddress, } @@ -1336,27 +1336,27 @@ impl DirectAddrUpdateState { #[derive(Error)] #[non_exhaustive] pub enum CreateHandleError { - #[display("Failed to create bind sockets")] + #[error("Failed to create bind sockets")] BindSockets { #[error(std_err)] source: io::Error, }, - #[display("Failed to create internal quinn endpoint")] + #[error("Failed to create internal quinn endpoint")] CreateQuinnEndpoint { #[error(std_err)] source: io::Error, }, - #[display("Failed to create socket state")] + #[error("Failed to create socket state")] CreateSocketState { #[error(std_err)] source: io::Error, }, - #[display("Failed to create netmon monitor")] + #[error("Failed to create netmon monitor")] CreateNetmonMonitor { #[error(std_err)] source: netmon::Error, }, - #[display("Failed to subscribe netmon monitor")] + #[error("Failed to subscribe netmon monitor")] SubscribeNetmonMonitor { #[error(std_err)] source: netmon::Error, @@ -1715,9 +1715,9 @@ impl DiscoState { #[derive(Error)] #[non_exhaustive] enum DiscoBoxError { - #[display("Failed to open crypto box")] + #[error("Failed to open crypto box")] Open { source: DecryptionError }, - #[display("Failed to parse disco message")] + #[error("Failed to parse disco message")] Parse { source: disco::ParseError }, } @@ -2401,7 +2401,7 @@ pub(crate) struct EndpointIdMappedAddr(Ipv6Addr); /// Can occur when converting a [`SocketAddr`] to an [`EndpointIdMappedAddr`] #[add_meta] #[derive(Error)] -#[display("Failed to convert")] +#[error("Failed to convert")] pub struct EndpointIdMappedAddrError; /// Counter to always generate unique addresses for [`EndpointIdMappedAddr`]. diff --git a/iroh/src/magicsock/endpoint_map.rs b/iroh/src/magicsock/endpoint_map.rs index e23da332321..b5502b03e97 100644 --- a/iroh/src/magicsock/endpoint_map.rs +++ b/iroh/src/magicsock/endpoint_map.rs @@ -721,7 +721,7 @@ impl EndpointMapInner { /// NOTE: storing an [`IpPort`] is safer than storing a [`SocketAddr`] because for IPv6 socket /// addresses include fields that can't be assumed consistent even within a single connection. #[derive(Debug, derive_more::Display, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] -#[display("{}", SocketAddr::from(*self))] +#[error("{}", SocketAddr::from(*self))] pub struct IpPort { ip: IpAddr, port: u16, diff --git a/iroh/src/magicsock/endpoint_map/endpoint_state.rs b/iroh/src/magicsock/endpoint_map/endpoint_state.rs index e4b1c2a2209..39702e083ac 100644 --- a/iroh/src/magicsock/endpoint_map/endpoint_state.rs +++ b/iroh/src/magicsock/endpoint_map/endpoint_state.rs @@ -1287,13 +1287,13 @@ pub enum DiscoPingPurpose { #[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, derive_more::Display)] pub enum ControlMsg { /// We received a Ping from the endpoint. - #[display("ping←")] + #[error("ping←")] Ping, /// We received a Pong from the endpoint. - #[display("pong←")] + #[error("pong←")] Pong, /// We received a CallMeMaybe. - #[display("call me")] + #[error("call me")] CallMeMaybe, } @@ -1427,20 +1427,20 @@ impl RemoteInfo { #[derive(derive_more::Display, Default, Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] pub enum ConnectionType { /// Direct UDP connection - #[display("direct({_0})")] + #[error("direct({_0})")] Direct(SocketAddr), /// Relay connection over relay - #[display("relay({_0})")] + #[error("relay({_0})")] Relay(RelayUrl), /// Both a UDP and a relay connection are used. /// /// This is the case if we do have a UDP address, but are missing a recent confirmation that /// the address works. - #[display("mixed(udp: {_0}, relay: {_1})")] + #[error("mixed(udp: {_0}, relay: {_1})")] Mixed(SocketAddr, RelayUrl), /// We have no verified connection to this PublicKey #[default] - #[display("none")] + #[error("none")] None, } diff --git a/iroh/src/magicsock/transports/relay/actor.rs b/iroh/src/magicsock/transports/relay/actor.rs index a34fc6ae459..7eabe1119c1 100644 --- a/iroh/src/magicsock/transports/relay/actor.rs +++ b/iroh/src/magicsock/transports/relay/actor.rs @@ -213,11 +213,11 @@ struct RelayConnectionOptions { #[add_meta] #[derive(Error)] enum RelayConnectionError { - #[display("Failed to connect to relay server")] + #[error("Failed to connect to relay server")] Dial { source: DialError }, - #[display("Failed to handshake with relay server")] + #[error("Failed to handshake with relay server")] Handshake { source: RunError }, - #[display("Lost connection to relay server")] + #[error("Lost connection to relay server")] Established { source: RunError }, } @@ -225,22 +225,22 @@ enum RelayConnectionError { #[add_meta] #[derive(Error)] enum RunError { - #[display("Send timeout")] + #[error("Send timeout")] SendTimeout, - #[display("Ping timeout")] + #[error("Ping timeout")] PingTimeout, - #[display("Local IP no longer valid")] + #[error("Local IP no longer valid")] LocalIpInvalid, - #[display("No local address")] + #[error("No local address")] LocalAddrMissing, - #[display("Stream closed by server.")] + #[error("Stream closed by server.")] StreamClosedServer, - #[display("Client stream read failed")] + #[error("Client stream read failed")] ClientStreamRead { #[error(std_err)] source: RecvError, }, - #[display("Client stream write failed")] + #[error("Client stream write failed")] ClientStreamWrite { #[error(std_err)] source: SendError, @@ -251,9 +251,9 @@ enum RunError { #[add_meta] #[derive(Error)] enum DialError { - #[display("timeout (>{timeout:?}) trying to establish a connection")] + #[error("timeout (>{timeout:?}) trying to establish a connection")] Timeout { timeout: Duration }, - #[display("unable to connect")] + #[error("unable to connect")] Connect { source: ConnectError }, } diff --git a/iroh/src/net_report.rs b/iroh/src/net_report.rs index 7f2da1db9a3..cd7a5fcaf64 100644 --- a/iroh/src/net_report.rs +++ b/iroh/src/net_report.rs @@ -65,7 +65,7 @@ mod options; pub(crate) mod portmapper { /// Output of a port mapping probe. #[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)] - #[display("portmap={{ UPnP: {upnp}, PMP: {nat_pmp}, PCP: {pcp} }}")] + #[error("portmap={{ UPnP: {upnp}, PMP: {nat_pmp}, PCP: {pcp} }}")] pub struct ProbeOutput { /// If UPnP can be considered available. pub upnp: bool, @@ -85,15 +85,15 @@ pub(crate) use self::reportgen::IfStateDetails; #[derive(n0_error::Error)] #[non_exhaustive] enum QadProbeError { - #[display("Failed to resolve relay address")] + #[error("Failed to resolve relay address")] GetRelayAddr { source: self::reportgen::GetRelayAddrError, }, - #[display("Missing host in relay URL")] + #[error("Missing host in relay URL")] MissingHost, - #[display("QUIC connection failed")] + #[error("QUIC connection failed")] Quic { source: iroh_relay::quic::Error }, - #[display("Receiver dropped")] + #[error("Receiver dropped")] ReceiverDropped, } diff --git a/iroh/src/net_report/ip_mapped_addrs.rs b/iroh/src/net_report/ip_mapped_addrs.rs index dea24243f02..98d38066cde 100644 --- a/iroh/src/net_report/ip_mapped_addrs.rs +++ b/iroh/src/net_report/ip_mapped_addrs.rs @@ -12,7 +12,7 @@ use n0_error::{Error, add_meta, e}; /// Can occur when converting a [`SocketAddr`] to an [`IpMappedAddr`] #[add_meta] #[derive(Error)] -#[display("Failed to convert")] +#[error("Failed to convert")] pub struct IpMappedAddrError; /// A map fake Ipv6 address with an actual IP address. diff --git a/iroh/src/net_report/reportgen.rs b/iroh/src/net_report/reportgen.rs index 0f9b6f06e90..55f854ab76d 100644 --- a/iroh/src/net_report/reportgen.rs +++ b/iroh/src/net_report/reportgen.rs @@ -180,13 +180,13 @@ struct Actor { #[derive(Error)] #[non_exhaustive] pub(super) enum ProbesError { - #[display("Probe failed")] + #[error("Probe failed")] ProbeFailure { source: ProbeError }, - #[display("All probes failed")] + #[error("All probes failed")] AllProbesFailed, - #[display("Probe cancelled")] + #[error("Probe cancelled")] Cancelled, - #[display("Probe timed out")] + #[error("Probe timed out")] Timeout, } @@ -452,11 +452,11 @@ pub(super) struct HttpsProbeReport { #[derive(Error)] #[non_exhaustive] pub(super) enum ProbeError { - #[display("Client is gone")] + #[error("Client is gone")] ClientGone, - #[display("Probe is no longer useful")] + #[error("Probe is no longer useful")] NotUseful, - #[display("Failed to run HTTPS probe")] + #[error("Failed to run HTTPS probe")] Https { source: MeasureHttpsLatencyError }, } @@ -465,9 +465,9 @@ pub(super) enum ProbeError { #[derive(Error)] #[non_exhaustive] pub(super) enum QuicError { - #[display("No relay available")] + #[error("No relay available")] NoRelay, - #[display("URL must have 'host' to use QUIC address discovery probes")] + #[error("URL must have 'host' to use QUIC address discovery probes")] InvalidUrl, } @@ -542,12 +542,12 @@ enum CaptivePortalError { #[error(from)] source: StaggeredError, }, - #[display("Creating HTTP client failed")] + #[error("Creating HTTP client failed")] CreateReqwestClient { #[error(std_err)] source: reqwest::Error, }, - #[display("HTTP request failed")] + #[error("HTTP request failed")] HttpRequest { #[error(std_err)] source: reqwest::Error, @@ -657,17 +657,17 @@ fn get_quic_port(relay: &RelayConfig) -> Option { #[derive(Error)] #[non_exhaustive] pub enum GetRelayAddrError { - #[display("No valid hostname in the relay URL")] + #[error("No valid hostname in the relay URL")] InvalidHostname, - #[display("No suitable relay address found")] + #[error("No suitable relay address found")] NoAddrFound, - #[display("DNS lookup failed")] + #[error("DNS lookup failed")] DnsLookup { source: StaggeredError }, - #[display("Relay is not suitable")] + #[error("Relay is not suitable")] UnsupportedRelay, - #[display("HTTPS probes are not implemented")] + #[error("HTTPS probes are not implemented")] UnsupportedHttps, - #[display("No port available for this protocol")] + #[error("No port available for this protocol")] MissingPort, } @@ -770,17 +770,17 @@ pub enum MeasureHttpsLatencyError { #[error(from)] source: StaggeredError, }, - #[display("Creating HTTP client failed")] + #[error("Creating HTTP client failed")] CreateReqwestClient { #[error(std_err)] source: reqwest::Error, }, - #[display("HTTP request failed")] + #[error("HTTP request failed")] HttpRequest { #[error(std_err)] source: reqwest::Error, }, - #[display("Error response from server {status}: {:?}", status.canonical_reason())] + #[error("Error response from server {status}: {:?}", status.canonical_reason())] InvalidResponse { status: StatusCode }, } diff --git a/iroh/src/protocol.rs b/iroh/src/protocol.rs index 8e932c68967..befd0311abb 100644 --- a/iroh/src/protocol.rs +++ b/iroh/src/protocol.rs @@ -113,7 +113,7 @@ pub enum AcceptError { }, #[error(transparent)] MissingRemoteEndpointId { source: RemoteEndpointIdError }, - #[display("Not allowed.")] + #[error("Not allowed.")] NotAllowed {}, #[error(transparent)] User { source: AnyError }, diff --git a/iroh/src/tls/resolver.rs b/iroh/src/tls/resolver.rs index 84657d84219..ef277823287 100644 --- a/iroh/src/tls/resolver.rs +++ b/iroh/src/tls/resolver.rs @@ -17,7 +17,7 @@ pub(super) struct AlwaysResolvesCert { #[non_exhaustive] pub(super) enum CreateConfigError { /// Rustls configuration error - #[display("rustls error")] + #[error("rustls error")] Rustls { source: rustls::Error }, } From b249b7b4ca3a32f153683ab1b1536788c0fabacc Mon Sep 17 00:00:00 2001 From: Frando Date: Tue, 28 Oct 2025 11:41:47 +0100 Subject: [PATCH 38/58] wip: bail -> bail_any --- Cargo.lock | 57 ++++++++++++++++------- iroh-dns-server/src/dns/node_authority.rs | 8 ++-- iroh-dns-server/src/http.rs | 4 +- iroh-dns-server/src/http/tls.rs | 6 +-- iroh-relay/src/main.rs | 18 +++---- iroh-relay/src/quic.rs | 2 +- iroh-relay/src/server/client.rs | 4 +- iroh-relay/src/server/clients.rs | 4 +- iroh-relay/src/server/http_server.rs | 18 +++---- iroh/examples/0rtt.rs | 4 +- iroh/examples/transfer.rs | 6 +-- iroh/src/discovery/mdns.rs | 4 +- iroh/src/endpoint.rs | 6 +-- 13 files changed, 82 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 765a815dea8..037d57fcb56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1162,7 +1162,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -1925,7 +1925,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -2193,7 +2193,7 @@ dependencies = [ "iroh-quinn-proto", "iroh-quinn-udp", "iroh-relay", - "n0-error", + "n0-error 0.1.0 (git+https://github.com/n0-computer/n0-error?branch=main)", "n0-future", "n0-watcher", "nested_enum_utils", @@ -2241,7 +2241,7 @@ dependencies = [ "data-encoding", "derive_more 2.0.1", "ed25519-dalek", - "n0-error", + "n0-error 0.1.0 (git+https://github.com/n0-computer/n0-error?branch=main)", "postcard", "proptest", "rand 0.9.2", @@ -2265,7 +2265,7 @@ dependencies = [ "iroh", "iroh-metrics", "iroh-quinn", - "n0-error", + "n0-error 0.1.0 (git+https://github.com/n0-computer/n0-error?branch=main)", "n0-future", "rand 0.9.2", "rcgen", @@ -2298,7 +2298,7 @@ dependencies = [ "iroh", "iroh-metrics", "lru 0.16.2", - "n0-error", + "n0-error 0.1.0 (git+https://github.com/n0-computer/n0-error?branch=main)", "n0-future", "pkarr", "rand 0.9.2", @@ -2330,14 +2330,14 @@ dependencies = [ [[package]] name = "iroh-metrics" version = "0.36.2" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#46c6eb6ebea8136f6470beeddac34895ed3c08c7" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#3268f15ee3d97dbaafcbbc9886268c9164c55cca" dependencies = [ "http-body-util", "hyper", "hyper-util", "iroh-metrics-derive", "itoa", - "n0-error", + "n0-error 0.1.0 (git+https://github.com/n0-computer/n0-error?branch=Frando%2Fstackerr-macro)", "postcard", "reqwest", "ryu", @@ -2349,7 +2349,7 @@ dependencies = [ [[package]] name = "iroh-metrics-derive" version = "0.3.1" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#46c6eb6ebea8136f6470beeddac34895ed3c08c7" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#3268f15ee3d97dbaafcbbc9886268c9164c55cca" dependencies = [ "heck", "proc-macro2", @@ -2436,7 +2436,7 @@ dependencies = [ "iroh-quinn", "iroh-quinn-proto", "lru 0.16.2", - "n0-error", + "n0-error 0.1.0 (git+https://github.com/n0-computer/n0-error?branch=main)", "n0-future", "num_enum", "pin-project", @@ -2717,6 +2717,17 @@ dependencies = [ "uuid", ] +[[package]] +name = "n0-error" +version = "0.1.0" +source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fstackerr-macro#1198276e78a319ff73dbd8335de6674473f20105" +dependencies = [ + "anyhow", + "derive_more 2.0.1", + "n0-error-macros 0.1.0 (git+https://github.com/n0-computer/n0-error?branch=Frando%2Fstackerr-macro)", + "spez", +] + [[package]] name = "n0-error" version = "0.1.0" @@ -2724,10 +2735,22 @@ source = "git+https://github.com/n0-computer/n0-error?branch=main#00defd8204754d dependencies = [ "anyhow", "derive_more 2.0.1", - "n0-error-macros", + "n0-error-macros 0.1.0 (git+https://github.com/n0-computer/n0-error?branch=main)", "spez", ] +[[package]] +name = "n0-error-macros" +version = "0.1.0" +source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fstackerr-macro#1198276e78a319ff73dbd8335de6674473f20105" +dependencies = [ + "darling", + "heck", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "n0-error-macros" version = "0.1.0" @@ -2927,7 +2950,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -3397,7 +3420,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.6.1", + "socket2 0.5.10", "thiserror 2.0.17", "tokio", "tracing", @@ -3434,9 +3457,9 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.1", + "socket2 0.5.10", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -3735,7 +3758,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -4415,7 +4438,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] diff --git a/iroh-dns-server/src/dns/node_authority.rs b/iroh-dns-server/src/dns/node_authority.rs index 1beecda9527..ce8c07d3fc8 100644 --- a/iroh-dns-server/src/dns/node_authority.rs +++ b/iroh-dns-server/src/dns/node_authority.rs @@ -13,7 +13,7 @@ use hickory_server::{ server::RequestInfo, store::in_memory::InMemoryAuthority, }; -use n0_error::{Result, StackResultExt, StdResultExt, bail}; +use n0_error::{Result, StackResultExt, StdResultExt, bail_any}; use tracing::{debug, trace}; use crate::{ @@ -41,7 +41,7 @@ impl NodeAuthority { serial: u32, ) -> Result { if origins.is_empty() { - bail!("at least one origin is required"); + bail_any!("at least one origin is required"); } let first_origin = LowerName::from(&origins[0]); Ok(Self { @@ -183,7 +183,7 @@ fn parse_name_as_pkarr_with_origin( continue; } if name.num_labels() < origin.num_labels() + 1 { - bail!("not a valid pkarr name: missing pubkey"); + bail_any!("not a valid pkarr name: missing pubkey"); } trace!("parse {origin}"); let labels = name.iter().rev(); @@ -195,7 +195,7 @@ fn parse_name_as_pkarr_with_origin( let remaining_name = Name::from_labels(labels_without_origin.rev()).e()?; return Ok((remaining_name, pkey, origin.clone())); } - bail!("name does not match any allowed origin"); + bail_any!("name does not match any allowed origin"); } fn err_refused(e: impl fmt::Debug) -> LookupError { diff --git a/iroh-dns-server/src/http.rs b/iroh-dns-server/src/http.rs index 73671e04765..cac8b423fb2 100644 --- a/iroh-dns-server/src/http.rs +++ b/iroh-dns-server/src/http.rs @@ -14,7 +14,7 @@ use axum::{ response::IntoResponse, routing::get, }; -use n0_error::{Result, StdResultExt, anyerr, bail}; +use n0_error::{Result, StdResultExt, anyerr, bail_any}; use serde::{Deserialize, Serialize}; use tokio::{net::TcpListener, task::JoinSet}; use tower_http::{ @@ -74,7 +74,7 @@ impl HttpServer { state: AppState, ) -> Result { if http_config.is_none() && https_config.is_none() { - bail!("Either http or https config is required"); + bail_any!("Either http or https config is required"); } let app = create_app(state, &rate_limit_config); diff --git a/iroh-dns-server/src/http/tls.rs b/iroh-dns-server/src/http/tls.rs index ca2f4f246d4..5db0e7ec0d7 100644 --- a/iroh-dns-server/src/http/tls.rs +++ b/iroh-dns-server/src/http/tls.rs @@ -9,7 +9,7 @@ use axum_server::{ accept::Accept, tls_rustls::{RustlsAcceptor, RustlsConfig}, }; -use n0_error::{Result, StackResultExt, StdResultExt, bail}; +use n0_error::{Result, StackResultExt, StdResultExt, bail_any}; use n0_future::{FutureExt, future::Boxed as BoxFuture}; use serde::{Deserialize, Serialize}; use tokio::io::{AsyncRead, AsyncWrite}; @@ -86,7 +86,7 @@ impl TlsAcceptor { async fn manual(domains: Vec, dir: PathBuf) -> Result { let config = rustls::ServerConfig::builder().with_no_client_auth(); if domains.len() != 1 { - bail!("Multiple domains in manual mode are not supported"); + bail_any!("Multiple domains in manual mode are not supported"); } let keyname = escape_hostname(&domains[0]); @@ -174,7 +174,7 @@ async fn load_secret_key( } } - bail!( + bail_any!( "no keys found in {} (encrypted keys not supported)", filename.as_ref().display() ); diff --git a/iroh-relay/src/main.rs b/iroh-relay/src/main.rs index cefbba46432..5f558dbaa15 100644 --- a/iroh-relay/src/main.rs +++ b/iroh-relay/src/main.rs @@ -19,7 +19,7 @@ use iroh_relay::{ }, server::{self as relay, ClientRateLimit, QuicConfig}, }; -use n0_error::{AnyError as Error, Result, StdResultExt, bail}; +use n0_error::{AnyError as Error, Result, StdResultExt, bail_any}; use n0_future::FutureExt; use serde::{Deserialize, Serialize}; use tokio_rustls_acme::{AcmeConfig, caches::DirCache}; @@ -96,7 +96,7 @@ fn load_secret_key( } } - bail!( + bail_any!( "no keys found in {} (encrypted keys not supported)", filename.display() ); @@ -297,10 +297,10 @@ async fn http_access_check_inner( } Ok(res) if res.status() == StatusCode::OK => match res.text().await { Ok(text) if text == "true" => Ok(()), - Ok(_) => bail!("Invalid response text (must be 'true')"), + Ok(_) => bail_any!("Invalid response text (must be 'true')"), Err(err) => Err(err).std_context("Failed to read response"), }, - Ok(res) => bail!("Received invalid status code ({})", res.status()), + Ok(res) => bail_any!("Received invalid status code ({})", res.status()), } } @@ -505,7 +505,7 @@ impl Config { async fn read_from_file(path: impl AsRef) -> Result { if !path.as_ref().is_file() { - bail!("config-path must be a file"); + bail_any!("config-path must be a file"); } let config_ser = tokio::fs::read_to_string(&path) .await @@ -524,7 +524,7 @@ async fn main() -> Result<()> { let cli = Cli::parse(); let mut cfg = Config::load(&cli).await?; if cfg.enable_quic_addr_discovery && cfg.tls.is_none() { - bail!("TLS must be configured in order to spawn a QUIC endpoint"); + bail_any!("TLS must be configured in order to spawn a QUIC endpoint"); } if cli.dev { // When in `--dev` mode, do not use https, even when tls is configured. @@ -536,7 +536,7 @@ async fn main() -> Result<()> { } } if cfg.tls.is_none() && cfg.enable_quic_addr_discovery { - bail!("If QUIC address discovery is enabled, TLS must also be configured"); + bail_any!("If QUIC address discovery is enabled, TLS must also be configured"); }; let relay_config = build_relay_config(cfg).await?; debug!("{relay_config:#?}"); @@ -662,7 +662,7 @@ async fn build_relay_config(cfg: Config) -> Result Result { if rx.bytes_per_second.is_none() && rx.max_burst_bytes.is_some() { - bail!("bytes_per_seconds must be specified to enable the rate-limiter"); + bail_any!("bytes_per_seconds must be specified to enable the rate-limiter"); } match rx.bytes_per_second { Some(bps) => Some(ClientRateLimit { diff --git a/iroh-relay/src/quic.rs b/iroh-relay/src/quic.rs index c2080e0dab6..35156f7a809 100644 --- a/iroh-relay/src/quic.rs +++ b/iroh-relay/src/quic.rs @@ -315,7 +315,7 @@ impl QuicClient { // tokio::select! { // _ = cancel.cancelled() => { // conn.close(QUIC_ADDR_DISC_CLOSE_CODE, QUIC_ADDR_DISC_CLOSE_REASON); - // bail!("QUIC address discovery canceled early"); + // bail_any!("QUIC address discovery canceled early"); // }, // res = external_addresses.wait_for(|addr| addr.is_some()) => { // let addr = res?.expect("checked"); diff --git a/iroh-relay/src/server/client.rs b/iroh-relay/src/server/client.rs index 29cb97c83be..9497c7f4e77 100644 --- a/iroh-relay/src/server/client.rs +++ b/iroh-relay/src/server/client.rs @@ -559,7 +559,7 @@ mod tests { match stream.next().await { Some(Ok(frame)) => { if frame_type != frame.typ() { - n0_error::bail!( + n0_error::bail_any!( "Unexpected frame, got {:?}, but expected {:?}", frame.typ(), frame_type @@ -568,7 +568,7 @@ mod tests { Ok(frame) } Some(Err(err)) => Err(err).e(), - None => n0_error::bail!("Unexpected EOF, expected frame {frame_type:?}"), + None => n0_error::bail_any!("Unexpected EOF, expected frame {frame_type:?}"), } } diff --git a/iroh-relay/src/server/clients.rs b/iroh-relay/src/server/clients.rs index 8dd1e041345..ab4166bcfe5 100644 --- a/iroh-relay/src/server/clients.rs +++ b/iroh-relay/src/server/clients.rs @@ -215,7 +215,7 @@ mod tests { match stream.next().await { Some(Ok(frame)) => { if frame_type != frame.typ() { - n0_error::bail!( + n0_error::bail_any!( "Unexpected frame, got {:?}, but expected {:?}", frame.typ(), frame_type @@ -224,7 +224,7 @@ mod tests { Ok(frame) } Some(Err(err)) => Err(err).e(), - None => n0_error::bail!("Unexpected EOF, expected frame {frame_type:?}"), + None => n0_error::bail_any!("Unexpected EOF, expected frame {frame_type:?}"), } } diff --git a/iroh-relay/src/server/http_server.rs b/iroh-relay/src/server/http_server.rs index 5ee5ad65f71..c6b37b6c2a0 100644 --- a/iroh-relay/src/server/http_server.rs +++ b/iroh-relay/src/server/http_server.rs @@ -854,7 +854,7 @@ mod tests { use std::sync::Arc; use iroh_base::{PublicKey, SecretKey}; - use n0_error::{Result, StdResultExt, bail}; + use n0_error::{Result, StdResultExt, bail_any}; use n0_future::{SinkExt, StreamExt}; use rand::SeedableRng; use reqwest::Url; @@ -913,7 +913,7 @@ mod tests { let addr = if let std::net::IpAddr::V4(ipv4_addr) = addr.ip() { ipv4_addr } else { - bail!("cannot get ipv4 addr from socket addr {addr:?}"); + bail_any!("cannot get ipv4 addr from socket addr {addr:?}"); }; info!("addr: {addr}:{port}"); @@ -1034,7 +1034,7 @@ mod tests { let addr = if let std::net::IpAddr::V4(ipv4_addr) = addr.ip() { ipv4_addr } else { - bail!("cannot get ipv4 addr from socket addr {addr:?}"); + bail_any!("cannot get ipv4 addr from socket addr {addr:?}"); }; info!("Relay listening on: {addr}:{port}"); @@ -1154,7 +1154,7 @@ mod tests { assert_eq!(msg, datagrams); } msg => { - bail!("expected ReceivedDatagrams msg, got {msg:?}"); + bail_any!("expected ReceivedDatagrams msg, got {msg:?}"); } } @@ -1175,7 +1175,7 @@ mod tests { assert_eq!(msg, datagrams); } msg => { - bail!("expected ReceivedDatagrams msg, got {msg:?}"); + bail_any!("expected ReceivedDatagrams msg, got {msg:?}"); } } @@ -1254,7 +1254,7 @@ mod tests { assert_eq!(msg, datagrams); } msg => { - bail!("expected ReceivedDatagrams msg, got {msg:?}"); + bail_any!("expected ReceivedDatagrams msg, got {msg:?}"); } } @@ -1275,7 +1275,7 @@ mod tests { assert_eq!(msg, datagrams); } msg => { - bail!("expected ReceivedDatagrams msg, got {msg:?}"); + bail_any!("expected ReceivedDatagrams msg, got {msg:?}"); } } @@ -1306,7 +1306,7 @@ mod tests { assert_eq!(msg, datagrams); } msg => { - bail!("expected ReceivedDatagrams msg, got {msg:?}"); + bail_any!("expected ReceivedDatagrams msg, got {msg:?}"); } } @@ -1327,7 +1327,7 @@ mod tests { assert_eq!(msg, datagrams); } msg => { - bail!("expected ReceivedDatagrams msg, got {msg:?}"); + bail_any!("expected ReceivedDatagrams msg, got {msg:?}"); } } diff --git a/iroh/examples/0rtt.rs b/iroh/examples/0rtt.rs index df324519a75..78fa317e60b 100644 --- a/iroh/examples/0rtt.rs +++ b/iroh/examples/0rtt.rs @@ -6,7 +6,7 @@ use iroh::{ EndpointId, SecretKey, endpoint::{Connecting, Connection}, }; -use n0_error::{Result, StackResultExt, StdResultExt, bail}; +use n0_error::{Result, StackResultExt, StdResultExt, bail_any}; use n0_future::{StreamExt, future}; use n0_watcher::Watcher; use tracing::{info, trace}; @@ -141,7 +141,7 @@ async fn accept(_args: Args) -> Result<()> { let mut addrs = endpoint.watch_addr().stream(); let addr = loop { let Some(addr) = addrs.next().await else { - bail!("Address stream closed"); + bail_any!("Address stream closed"); }; if !addr.ip_addrs().count() == 0 { break addr; diff --git a/iroh/examples/transfer.rs b/iroh/examples/transfer.rs index 2a33c1cef1c..35e34ad093c 100644 --- a/iroh/examples/transfer.rs +++ b/iroh/examples/transfer.rs @@ -212,7 +212,7 @@ impl EndpointArgs { } #[cfg(not(feature = "test-utils"))] { - n0_error::bail!( + n0_error::bail_any!( "Must have the `test-utils` feature enabled when using the `--env=dev` flag" ) } @@ -248,7 +248,7 @@ impl EndpointArgs { } #[cfg(not(feature = "test-utils"))] { - n0_error::bail!( + n0_error::bail_any!( "Must have the `discovery-local-network` enabled when using the `--mdns` flag" ); } @@ -279,7 +279,7 @@ impl EndpointArgs { } #[cfg(not(feature = "discovery-local-network"))] { - n0_error::bail!( + n0_error::bail_any!( "Must have the `test-utils` feature enabled when using the `--relay-only` flag" ); } diff --git a/iroh/src/discovery/mdns.rs b/iroh/src/discovery/mdns.rs index 0455f490598..e5ea36575ca 100644 --- a/iroh/src/discovery/mdns.rs +++ b/iroh/src/discovery/mdns.rs @@ -546,7 +546,7 @@ mod tests { /// tests) mod run_in_isolation { use iroh_base::{SecretKey, TransportAddr}; - use n0_error::{AnyError as Error, Result, StdResultExt, bail}; + use n0_error::{AnyError as Error, Result, StdResultExt, bail_any}; use n0_future::StreamExt; use rand::{CryptoRng, SeedableRng}; use tracing_test::traced_test; @@ -707,7 +707,7 @@ mod tests { got_ids.insert((endpoint_info.endpoint_id, data)); } } else { - bail!( + bail_any!( "no more events, only got {} ids, expected {num_endpoints}\n", got_ids.len() ); diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index f0898f1504c..d19d0175b90 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -2369,7 +2369,7 @@ mod tests { let server = server.clone(); async move { let Some(conn) = server.accept().await else { - n0_error::bail!("Expected an incoming connection"); + n0_error::bail_any!("Expected an incoming connection"); }; let conn = conn.await.e()?; let (mut send, mut recv) = conn.accept_bi().await.e()?; @@ -2420,7 +2420,7 @@ mod tests { for i in 0..2 { println!("accept: round {i}"); let Some(conn) = server.accept().await else { - n0_error::bail!("Expected an incoming connection"); + n0_error::bail_any!("Expected an incoming connection"); }; let conn = conn.await.e()?; let (mut send, mut recv) = conn.accept_bi().await.e()?; @@ -2641,7 +2641,7 @@ mod tests { return Ok(()); } } - n0_error::bail!("conn_type stream ended before `ConnectionType::Direct`"); + n0_error::bail_any!("conn_type stream ended before `ConnectionType::Direct`"); } async fn accept(ep: &Endpoint) -> Result { From 649482b50e4a010eaee8f30f6b9c7188f20ff646 Mon Sep 17 00:00:00 2001 From: Frando Date: Tue, 28 Oct 2025 12:06:48 +0100 Subject: [PATCH 39/58] bump n0-error and adapt for changes --- Cargo.lock | 53 ++++++------------- iroh-base/Cargo.toml | 2 +- iroh-base/src/key.rs | 9 ++-- iroh-base/src/relay_url.rs | 5 +- iroh-dns-server/Cargo.toml | 2 +- iroh-dns-server/src/dns.rs | 6 +-- iroh-dns-server/src/store/signed_packets.rs | 4 +- iroh-relay/Cargo.toml | 2 +- iroh-relay/src/client.rs | 10 ++-- iroh-relay/src/client/conn.rs | 10 ++-- iroh-relay/src/dns.rs | 13 ++--- iroh-relay/src/endpoint_info.rs | 15 ++---- iroh-relay/src/protos/common.rs | 5 +- iroh-relay/src/protos/handshake.rs | 8 ++- iroh-relay/src/protos/relay.rs | 6 +-- iroh-relay/src/quic.rs | 9 ++-- iroh-relay/src/server.rs | 9 ++-- iroh-relay/src/server/client.rs | 16 ++---- iroh-relay/src/server/http_server.rs | 16 ++---- iroh-relay/src/server/streams.rs | 12 ++--- iroh/Cargo.toml | 2 +- iroh/bench/Cargo.toml | 2 +- iroh/src/disco.rs | 5 +- iroh/src/discovery.rs | 8 ++- iroh/src/discovery/pkarr.rs | 5 +- iroh/src/endpoint.rs | 24 +++------ iroh/src/key.rs | 6 +-- iroh/src/magicsock.rs | 14 ++--- iroh/src/magicsock/endpoint_map.rs | 2 +- .../magicsock/endpoint_map/endpoint_state.rs | 14 ++--- iroh/src/magicsock/transports/relay/actor.rs | 11 ++-- iroh/src/net_report.rs | 5 +- iroh/src/net_report/ip_mapped_addrs.rs | 5 +- iroh/src/net_report/reportgen.rs | 20 +++---- iroh/src/protocol.rs | 6 +-- iroh/src/tls/resolver.rs | 6 +-- 36 files changed, 121 insertions(+), 226 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 037d57fcb56..59f670a4101 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1162,7 +1162,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1925,7 +1925,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.1", "tokio", "tower-service", "tracing", @@ -2193,7 +2193,7 @@ dependencies = [ "iroh-quinn-proto", "iroh-quinn-udp", "iroh-relay", - "n0-error 0.1.0 (git+https://github.com/n0-computer/n0-error?branch=main)", + "n0-error", "n0-future", "n0-watcher", "nested_enum_utils", @@ -2241,7 +2241,7 @@ dependencies = [ "data-encoding", "derive_more 2.0.1", "ed25519-dalek", - "n0-error 0.1.0 (git+https://github.com/n0-computer/n0-error?branch=main)", + "n0-error", "postcard", "proptest", "rand 0.9.2", @@ -2265,7 +2265,7 @@ dependencies = [ "iroh", "iroh-metrics", "iroh-quinn", - "n0-error 0.1.0 (git+https://github.com/n0-computer/n0-error?branch=main)", + "n0-error", "n0-future", "rand 0.9.2", "rcgen", @@ -2298,7 +2298,7 @@ dependencies = [ "iroh", "iroh-metrics", "lru 0.16.2", - "n0-error 0.1.0 (git+https://github.com/n0-computer/n0-error?branch=main)", + "n0-error", "n0-future", "pkarr", "rand 0.9.2", @@ -2337,7 +2337,7 @@ dependencies = [ "hyper-util", "iroh-metrics-derive", "itoa", - "n0-error 0.1.0 (git+https://github.com/n0-computer/n0-error?branch=Frando%2Fstackerr-macro)", + "n0-error", "postcard", "reqwest", "ryu", @@ -2436,7 +2436,7 @@ dependencies = [ "iroh-quinn", "iroh-quinn-proto", "lru 0.16.2", - "n0-error 0.1.0 (git+https://github.com/n0-computer/n0-error?branch=main)", + "n0-error", "n0-future", "num_enum", "pin-project", @@ -2724,18 +2724,7 @@ source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fstackerr-m dependencies = [ "anyhow", "derive_more 2.0.1", - "n0-error-macros 0.1.0 (git+https://github.com/n0-computer/n0-error?branch=Frando%2Fstackerr-macro)", - "spez", -] - -[[package]] -name = "n0-error" -version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=main#00defd8204754d53ab2c3145acffc279bd4f9de0" -dependencies = [ - "anyhow", - "derive_more 2.0.1", - "n0-error-macros 0.1.0 (git+https://github.com/n0-computer/n0-error?branch=main)", + "n0-error-macros", "spez", ] @@ -2751,18 +2740,6 @@ dependencies = [ "syn", ] -[[package]] -name = "n0-error-macros" -version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=main#00defd8204754d53ab2c3145acffc279bd4f9de0" -dependencies = [ - "darling", - "heck", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "n0-future" version = "0.3.0" @@ -2950,7 +2927,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3420,7 +3397,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.5.10", + "socket2 0.6.1", "thiserror 2.0.17", "tokio", "tracing", @@ -3457,9 +3434,9 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.1", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -3758,7 +3735,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4438,7 +4415,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/iroh-base/Cargo.toml b/iroh-base/Cargo.toml index a409c2eaf47..468ac33999b 100644 --- a/iroh-base/Cargo.toml +++ b/iroh-base/Cargo.toml @@ -22,7 +22,7 @@ derive_more = { version = "2.0.1", features = ["display"], optional = true } url = { version = "2.5.3", features = ["serde"], optional = true } rand_core = { version = "0.9.3", optional = true } serde = { version = "1", features = ["derive", "rc"] } -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/stackerr-macro" } zeroize = { version = "1.8.2", optional = true, features = ["derive"] } zeroize_derive = { version = "1.4.2", optional = true } # needed for minimal versions diff --git a/iroh-base/src/key.rs b/iroh-base/src/key.rs index aee22bb05ff..69e61f3e9a5 100644 --- a/iroh-base/src/key.rs +++ b/iroh-base/src/key.rs @@ -11,7 +11,7 @@ use std::{ use curve25519_dalek::edwards::CompressedEdwardsY; use ed25519_dalek::{SigningKey, VerifyingKey}; -use n0_error::{Error, add_meta, e}; +use n0_error::{e, stack_error}; use rand_core::CryptoRng; use serde::{Deserialize, Serialize, de, ser}; @@ -203,9 +203,7 @@ impl Display for PublicKey { } /// Error when deserialising a [`PublicKey`] or a [`SecretKey`]. -#[add_meta] -#[derive(Error)] -#[error(from_sources, std_sources)] +#[stack_error(derive, add_meta, from_sources, std_sources)] #[allow(missing_docs)] pub enum KeyParsingError { /// Error when decoding. @@ -413,8 +411,7 @@ impl Signature { } /// Verification of a signature failed. -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[error("Invalid signature")] pub struct SignatureError {} diff --git a/iroh-base/src/relay_url.rs b/iroh-base/src/relay_url.rs index 73b555b6dfd..c49389e329b 100644 --- a/iroh-base/src/relay_url.rs +++ b/iroh-base/src/relay_url.rs @@ -1,6 +1,6 @@ use std::{fmt, ops::Deref, str::FromStr, sync::Arc}; -use n0_error::{Error, add_meta}; +use n0_error::stack_error; use serde::{Deserialize, Serialize}; use url::Url; @@ -39,8 +39,7 @@ impl From for RelayUrl { } /// Can occur when parsing a string into a [`RelayUrl`]. -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[error("Failed to parse relay URL")] pub struct RelayUrlParseError(#[error(std_err)] url::ParseError); diff --git a/iroh-dns-server/Cargo.toml b/iroh-dns-server/Cargo.toml index bb5e24fe3d1..3579d2b905f 100644 --- a/iroh-dns-server/Cargo.toml +++ b/iroh-dns-server/Cargo.toml @@ -39,7 +39,7 @@ rustls = { version = "0.23.33", default-features = false, features = ["ring"] } rustls-pemfile = { version = "2.1" } serde = { version = "1", features = ["derive"] } struct_iterable = "0.1.1" -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/stackerr-macro" } strum = { version = "0.27", features = ["derive"] } tokio = { version = "1", features = ["full"] } tokio-rustls = { version = "0.26", default-features = false, features = [ diff --git a/iroh-dns-server/src/dns.rs b/iroh-dns-server/src/dns.rs index 03a5dd7d365..72b9111df8d 100644 --- a/iroh-dns-server/src/dns.rs +++ b/iroh-dns-server/src/dns.rs @@ -25,7 +25,7 @@ use hickory_server::{ server::{Request, RequestHandler, ResponseHandler, ResponseInfo}, store::in_memory::InMemoryAuthority, }; -use n0_error::{Result, StdResultExt, format_err}; +use n0_error::{Result, StdResultExt, anyerr}; use serde::{Deserialize, Serialize}; use tokio::{ net::{TcpListener, UdpSocket}, @@ -236,7 +236,7 @@ fn create_static_authority( ) .e()? .into_soa() - .map_err(|_| format_err!("Couldn't parse SOA: {}", config.default_soa))?; + .map_err(|_| anyerr!("Couldn't parse SOA: {}", config.default_soa))?; let serial = soa.serial(); let mut records = BTreeMap::new(); for name in origins { @@ -270,7 +270,7 @@ fn create_static_authority( } let static_authority = InMemoryAuthority::new(Name::root(), records, ZoneType::Primary, false) - .map_err(|e| format_err!("new authority: {e}"))?; + .map_err(|e| anyerr!("new authority: {e}"))?; Ok((static_authority, serial)) } diff --git a/iroh-dns-server/src/store/signed_packets.rs b/iroh-dns-server/src/store/signed_packets.rs index 20c9590ad9e..4c5b1b2ca7d 100644 --- a/iroh-dns-server/src/store/signed_packets.rs +++ b/iroh-dns-server/src/store/signed_packets.rs @@ -6,7 +6,7 @@ use std::{ time::{Duration, SystemTime}, }; -use n0_error::{Result, StdResultExt, format_err}; +use n0_error::{Result, StdResultExt, anyerr}; use pkarr::{SignedPacket, Timestamp}; use redb::{ Database, MultimapTableDefinition, ReadableTable, TableDefinition, backends::InMemoryBackend, @@ -375,7 +375,7 @@ fn get_packet( buf.extend(data); match SignedPacket::deserialize(&buf) { Ok(packet) => Ok(Some(packet)), - Err(err2) => Err(format_err!( + Err(err2) => Err(anyerr!( "Failed to decode as pkarr v3: {err:#}. Also failed to decode as pkarr v2: {err2:#}" )), } diff --git a/iroh-relay/Cargo.toml b/iroh-relay/Cargo.toml index 02bdd62650f..9fd04856a18 100644 --- a/iroh-relay/Cargo.toml +++ b/iroh-relay/Cargo.toml @@ -70,7 +70,7 @@ webpki_types = { package = "rustls-pki-types", version = "1.12" } data-encoding = "2.6.0" lru = "0.16" z32 = "1.0.3" -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/stackerr-macro" } # server feature clap = { version = "4", features = ["derive"], optional = true } diff --git a/iroh-relay/src/client.rs b/iroh-relay/src/client.rs index 0c020c90f3e..d67458cdcf6 100644 --- a/iroh-relay/src/client.rs +++ b/iroh-relay/src/client.rs @@ -11,7 +11,7 @@ use std::{ use conn::Conn; use iroh_base::{RelayUrl, SecretKey}; -use n0_error::{Error, add_meta, e}; +use n0_error::{e, stack_error}; use n0_future::{ Sink, Stream, split::{SplitSink, SplitStream, split}, @@ -46,9 +46,7 @@ mod util; /// /// `ConnectError` contains `DialError`, errors that can occur while dialing the /// relay, as well as errors that occur while creating or maintaining a connection. -#[add_meta] -#[derive(Error)] -#[error(from_sources)] +#[stack_error(derive, add_meta, from_sources)] #[allow(missing_docs)] #[non_exhaustive] pub enum ConnectError { @@ -94,9 +92,7 @@ pub enum ConnectError { } /// Errors that can occur while dialing the relay server. -#[add_meta] -#[derive(Error)] -#[error(from_sources)] +#[stack_error(derive, add_meta, from_sources)] #[allow(missing_docs)] #[non_exhaustive] pub enum DialError { diff --git a/iroh-relay/src/client/conn.rs b/iroh-relay/src/client/conn.rs index 8d0cc7a9a58..c02aea8a0c5 100644 --- a/iroh-relay/src/client/conn.rs +++ b/iroh-relay/src/client/conn.rs @@ -8,7 +8,7 @@ use std::{ }; use iroh_base::SecretKey; -use n0_error::{Error, add_meta}; +use n0_error::stack_error; use n0_future::{Sink, Stream}; use tracing::debug; @@ -25,9 +25,7 @@ use crate::{ }; /// Error for sending messages to the relay server. -#[add_meta] -#[derive(Error)] -#[error(from_sources, std_sources)] +#[stack_error(derive, add_meta, from_sources, std_sources)] #[allow(missing_docs)] #[non_exhaustive] pub enum SendError { @@ -45,9 +43,7 @@ pub enum SendError { } /// Errors when receiving messages from the relay server. -#[add_meta] -#[derive(Error)] -#[error(from_sources, std_sources)] +#[stack_error(derive, add_meta, from_sources, std_sources)] #[allow(missing_docs)] #[non_exhaustive] pub enum RecvError { diff --git a/iroh-relay/src/dns.rs b/iroh-relay/src/dns.rs index ee9c6d56c42..b9d1a1bc3fd 100644 --- a/iroh-relay/src/dns.rs +++ b/iroh-relay/src/dns.rs @@ -13,7 +13,7 @@ use hickory_resolver::{ name_server::TokioConnectionProvider, }; use iroh_base::EndpointId; -use n0_error::{Error, StackError, add_meta, e}; +use n0_error::{StackError, e, stack_error}; use n0_future::{ StreamExt, boxed::BoxFuture, @@ -62,9 +62,7 @@ pub type BoxIter = Box + Send + 'static>; /// Potential errors related to dns. #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] -#[error(from_sources, std_sources)] +#[stack_error(derive, add_meta, from_sources, std_sources)] #[non_exhaustive] pub enum DnsError { #[error(transparent)] @@ -88,10 +86,8 @@ pub enum DnsError { #[cfg(not(wasm_browser))] #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta, from_sources)] #[non_exhaustive] -#[error(from_sources)] pub enum LookupError { #[error("Malformed txt from lookup")] ParseError { source: ParseError }, @@ -100,8 +96,7 @@ pub enum LookupError { } /// Error returned when a staggered call fails. -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[error("no calls succeeded: [{}]", errors.iter().map(|e| e.to_string()).collect::>().join(""))] pub struct StaggeredError { errors: Vec, diff --git a/iroh-relay/src/endpoint_info.rs b/iroh-relay/src/endpoint_info.rs index 0414443e1b1..aaf7b4c5e83 100644 --- a/iroh-relay/src/endpoint_info.rs +++ b/iroh-relay/src/endpoint_info.rs @@ -41,15 +41,14 @@ use std::{ }; use iroh_base::{EndpointAddr, EndpointId, KeyParsingError, RelayUrl, SecretKey, TransportAddr}; -use n0_error::{Error, add_meta, e}; +use n0_error::{e, stack_error}; use url::Url; /// The DNS name for the iroh TXT record. pub const IROH_TXT_NAME: &str = "_iroh"; #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] pub enum EncodingError { #[error(transparent)] @@ -65,8 +64,7 @@ pub enum EncodingError { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] pub enum DecodingError { #[error("endpoint id was not encoded in valid z32")] @@ -245,8 +243,7 @@ impl UserData { /// Error returned when an input value is too long for [`UserData`]. #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[error("max length exceeded")] pub struct MaxLengthExceededError {} @@ -426,9 +423,7 @@ impl EndpointInfo { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] -#[error(from_sources)] +#[stack_error(derive, add_meta, from_sources)] #[non_exhaustive] pub enum ParseError { #[error("Expected format `key=value`, received `{s}`")] diff --git a/iroh-relay/src/protos/common.rs b/iroh-relay/src/protos/common.rs index d98f92ed3ce..45750178d01 100644 --- a/iroh-relay/src/protos/common.rs +++ b/iroh-relay/src/protos/common.rs @@ -4,7 +4,7 @@ //! integers for different frames. use bytes::{Buf, BufMut}; -use n0_error::{Error, add_meta, e}; +use n0_error::{e, stack_error}; use quinn_proto::{ VarInt, coding::{Codec, UnexpectedEnd}, @@ -55,8 +55,7 @@ pub enum FrameType { Restarting = 12, } -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[allow(missing_docs)] #[non_exhaustive] pub enum FrameTypeError { diff --git a/iroh-relay/src/protos/handshake.rs b/iroh-relay/src/protos/handshake.rs index 6bc8be7fa00..58daa233658 100644 --- a/iroh-relay/src/protos/handshake.rs +++ b/iroh-relay/src/protos/handshake.rs @@ -31,7 +31,7 @@ use http::HeaderValue; #[cfg(feature = "server")] use iroh_base::Signature; use iroh_base::{PublicKey, SecretKey}; -use n0_error::{Error, add_meta, e}; +use n0_error::{e, stack_error}; use n0_future::{SinkExt, TryStreamExt}; #[cfg(feature = "server")] use rand::CryptoRng; @@ -132,8 +132,7 @@ impl Frame for ServerDeniesAuth { const TAG: FrameType = FrameType::ServerDeniesAuth; } -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[allow(missing_docs)] #[non_exhaustive] pub enum Error { @@ -172,8 +171,7 @@ pub enum Error { } #[cfg(feature = "server")] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] pub(crate) enum VerificationError { #[error("Couldn't export TLS keying material on our end")] NoKeyingMaterial, diff --git a/iroh-relay/src/protos/relay.rs b/iroh-relay/src/protos/relay.rs index e5cc4f6578a..cf7c5837e94 100644 --- a/iroh-relay/src/protos/relay.rs +++ b/iroh-relay/src/protos/relay.rs @@ -11,7 +11,7 @@ use std::num::NonZeroU16; use bytes::{Buf, BufMut, Bytes, BytesMut}; use iroh_base::{EndpointId, KeyParsingError}; -use n0_error::{Error, add_meta, e}; +use n0_error::{e, stack_error}; use n0_future::time::Duration; use super::common::{FrameType, FrameTypeError}; @@ -40,9 +40,7 @@ pub(crate) const PING_INTERVAL: Duration = Duration::from_secs(15); pub(crate) const PER_CLIENT_SEND_QUEUE_DEPTH: usize = 512; /// Protocol send errors. -#[add_meta] -#[derive(Error)] -#[error(from_sources)] +#[stack_error(derive, add_meta, from_sources)] #[allow(missing_docs)] #[non_exhaustive] pub enum Error { diff --git a/iroh-relay/src/quic.rs b/iroh-relay/src/quic.rs index 35156f7a809..9b6b7bc3b00 100644 --- a/iroh-relay/src/quic.rs +++ b/iroh-relay/src/quic.rs @@ -2,7 +2,7 @@ //! for QUIC address discovery. use std::{net::SocketAddr, sync::Arc}; -use n0_error::{Error, add_meta}; +use n0_error::stack_error; use n0_future::time::Duration; use quinn::{VarInt, crypto::rustls::QuicClientConfig}; use tokio::sync::watch; @@ -36,8 +36,7 @@ pub(crate) mod server { /// Server spawn errors #[allow(missing_docs)] - #[add_meta] - #[derive(Error)] + #[stack_error(derive, add_meta)] #[non_exhaustive] pub enum QuicSpawnError { #[error(transparent)] @@ -225,9 +224,7 @@ pub(crate) mod server { /// Quic client related errors. #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] -#[error(from_sources, std_sources)] +#[stack_error(derive, add_meta, from_sources, std_sources)] #[non_exhaustive] pub enum Error { #[error(transparent)] diff --git a/iroh-relay/src/server.rs b/iroh-relay/src/server.rs index 578b6cf9eab..f3b470b8a3c 100644 --- a/iroh-relay/src/server.rs +++ b/iroh-relay/src/server.rs @@ -26,7 +26,7 @@ use hyper::body::Incoming; use iroh_base::EndpointId; #[cfg(feature = "test-utils")] use iroh_base::RelayUrl; -use n0_error::{Error, add_meta, e}; +use n0_error::{e, stack_error}; use n0_future::{StreamExt, future::Boxed}; use tokio::{ net::TcpListener, @@ -265,10 +265,8 @@ pub struct Server { /// Server spawn errors #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta, std_sources)] #[non_exhaustive] -#[error(std_sources)] pub enum SpawnError { #[error("Unable to get local address")] LocalAddr { source: std::io::Error }, @@ -289,8 +287,7 @@ pub enum SpawnError { /// Server task errors #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] pub enum SupervisorError { #[error("Error starting metrics server")] diff --git a/iroh-relay/src/server/client.rs b/iroh-relay/src/server/client.rs index 9497c7f4e77..191b70f2ad7 100644 --- a/iroh-relay/src/server/client.rs +++ b/iroh-relay/src/server/client.rs @@ -3,7 +3,7 @@ use std::{collections::HashSet, sync::Arc, time::Duration}; use iroh_base::EndpointId; -use n0_error::{Error, add_meta, e}; +use n0_error::{e, stack_error}; use n0_future::{SinkExt, StreamExt}; use rand::Rng; use time::{Date, OffsetDateTime}; @@ -170,9 +170,7 @@ impl Client { } /// Error for [`Actor::handle_frame`] -#[add_meta] -#[derive(Error)] -#[error(from_sources)] +#[stack_error(derive, add_meta, from_sources)] #[allow(missing_docs)] #[non_exhaustive] pub enum HandleFrameError { @@ -187,9 +185,7 @@ pub enum HandleFrameError { } /// Error for [`Actor::write_frame`] -#[add_meta] -#[derive(Error)] -#[error(from_sources)] +#[stack_error(derive, add_meta, from_sources)] #[allow(missing_docs)] #[non_exhaustive] pub enum WriteFrameError { @@ -203,8 +199,7 @@ pub enum WriteFrameError { } /// Run error -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[allow(missing_docs)] #[non_exhaustive] pub enum RunError { @@ -497,8 +492,7 @@ pub(crate) enum SendError { Closed, } -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[error("failed to forward {scope:?} packet: {reason:?}")] pub struct ForwardPacketError { scope: PacketScope, diff --git a/iroh-relay/src/server/http_server.rs b/iroh-relay/src/server/http_server.rs index c6b37b6c2a0..31244a4b84e 100644 --- a/iroh-relay/src/server/http_server.rs +++ b/iroh-relay/src/server/http_server.rs @@ -15,7 +15,7 @@ use hyper::{ service::Service, upgrade::Upgraded, }; -use n0_error::{Error, add_meta, e}; +use n0_error::{e, stack_error}; use n0_future::time::Elapsed; use tokio::net::{TcpListener, TcpStream}; use tokio_rustls_acme::AcmeAcceptor; @@ -151,8 +151,7 @@ pub(super) struct TlsConfig { /// Errors when attempting to upgrade and #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] pub enum ServeConnectionError { #[error("TLS[acme] handshake")] @@ -194,10 +193,8 @@ pub enum ServeConnectionError { /// Server accept errors. #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta, from_sources)] #[non_exhaustive] -#[error(from_sources)] pub enum AcceptError { #[error(transparent)] Handshake { source: handshake::Error }, @@ -207,10 +204,8 @@ pub enum AcceptError { /// Server connection errors, includes errors that can happen on `accept`. #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta, from_sources)] #[non_exhaustive] -#[error(from_sources)] pub enum ConnectionHandlerError { #[error(transparent)] Accept { source: AcceptError }, @@ -413,8 +408,7 @@ struct Inner { metrics: Arc, } -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] enum RelayUpgradeReqError { #[error("missing header: {header}")] MissingHeader { header: http::HeaderName }, diff --git a/iroh-relay/src/server/streams.rs b/iroh-relay/src/server/streams.rs index b43560f3f1e..8b3cca3459c 100644 --- a/iroh-relay/src/server/streams.rs +++ b/iroh-relay/src/server/streams.rs @@ -6,7 +6,7 @@ use std::{ task::{Context, Poll}, }; -use n0_error::{Error, add_meta}; +use n0_error::stack_error; use n0_future::{FutureExt, Sink, Stream, ready, time}; use tokio::io::{AsyncRead, AsyncWrite}; use tracing::instrument; @@ -75,8 +75,7 @@ impl RelayedStream { } /// Relay send errors -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] pub enum SendError { #[error(transparent)] @@ -122,9 +121,7 @@ impl Sink for RelayedStream { } /// Relay receive errors -#[add_meta] -#[derive(Error)] -#[error(from_sources)] +#[stack_error(derive, add_meta, from_sources)] #[non_exhaustive] pub enum RecvError { #[error(transparent)] @@ -290,8 +287,7 @@ struct Bucket { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] pub struct InvalidBucketConfig { max: i64, bytes_per_second: i64, diff --git a/iroh/Cargo.toml b/iroh/Cargo.toml index de2fbe3007f..10ba8d815a7 100644 --- a/iroh/Cargo.toml +++ b/iroh/Cargo.toml @@ -39,7 +39,7 @@ http = "1" iroh-base = { version = "0.94.1", default-features = false, features = ["key", "relay"], path = "../iroh-base" } iroh-relay = { version = "0.94", path = "../iroh-relay", default-features = false } n0-future = "0.3.0" -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/stackerr-macro" } n0-watcher = "0.4" nested_enum_utils = "0.2.1" netwatch = { version = "0.11" } diff --git a/iroh/bench/Cargo.toml b/iroh/bench/Cargo.toml index 1c44f5e30c7..acda382050d 100644 --- a/iroh/bench/Cargo.toml +++ b/iroh/bench/Cargo.toml @@ -11,7 +11,7 @@ hdrhistogram = { version = "7.2", default-features = false } iroh = { path = ".." } iroh-metrics = "0.36" n0-future = "0.3.0" -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/stackerr-macro" } quinn = { package = "iroh-quinn", version = "0.14" } rand = "0.9.2" rcgen = "0.14" diff --git a/iroh/src/disco.rs b/iroh/src/disco.rs index 235b1162532..0e648b28db5 100644 --- a/iroh/src/disco.rs +++ b/iroh/src/disco.rs @@ -25,7 +25,7 @@ use std::{ use data_encoding::HEXLOWER; use iroh_base::{PublicKey, RelayUrl}; -use n0_error::{Error, add_meta, e, ensure}; +use n0_error::{e, ensure, stack_error}; use rand::Rng; use serde::{Deserialize, Serialize}; use url::Url; @@ -242,8 +242,7 @@ impl Ping { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] pub enum ParseError { #[error("message is too short")] diff --git a/iroh/src/discovery.rs b/iroh/src/discovery.rs index 71aa66a04d2..9c19d958170 100644 --- a/iroh/src/discovery.rs +++ b/iroh/src/discovery.rs @@ -113,7 +113,7 @@ use std::sync::{Arc, RwLock}; use iroh_base::{EndpointAddr, EndpointId}; -use n0_error::{AnyError, Error, add_meta, e, ensure}; +use n0_error::{AnyError, e, ensure, stack_error}; use n0_future::{ boxed::BoxStream, stream::StreamExt, @@ -181,8 +181,7 @@ impl DynIntoDiscovery for T { /// IntoDiscovery errors #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] pub enum IntoDiscoveryError { #[error("Service '{provenance}' error")] @@ -218,8 +217,7 @@ impl IntoDiscoveryError { /// Discovery errors #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] pub enum DiscoveryError { #[error("No discovery service configured")] diff --git a/iroh/src/discovery/pkarr.rs b/iroh/src/discovery/pkarr.rs index 8be75ab75c6..67cecd0e4c3 100644 --- a/iroh/src/discovery/pkarr.rs +++ b/iroh/src/discovery/pkarr.rs @@ -48,7 +48,7 @@ use std::sync::Arc; use iroh_base::{EndpointId, RelayUrl, SecretKey}; use iroh_relay::endpoint_info::{EncodingError, EndpointInfo}; -use n0_error::{Error, add_meta, e}; +use n0_error::{e, stack_error}; use n0_future::{ boxed::BoxStream, task::{self, AbortOnDropHandle}, @@ -76,8 +76,7 @@ use crate::{ pub mod dht; #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] pub enum PkarrError { #[error("Invalid public key")] diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index d19d0175b90..6313a0e62ea 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -23,7 +23,7 @@ use std::{ use ed25519_dalek::{VerifyingKey, pkcs8::DecodePublicKey}; use iroh_base::{EndpointAddr, EndpointId, RelayUrl, SecretKey, TransportAddr}; use iroh_relay::{RelayConfig, RelayMap}; -use n0_error::{Error, add_meta, e, ensure}; +use n0_error::{e, ensure, stack_error}; use n0_future::time::Duration; use n0_watcher::Watcher; use pin_project::pin_project; @@ -482,10 +482,8 @@ pub struct Endpoint { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta, from_sources)] #[non_exhaustive] -#[error(from_sources)] pub enum ConnectWithOptsError { #[error(transparent)] AddEndpointAddr { source: AddEndpointAddrError }, @@ -501,9 +499,7 @@ pub enum ConnectWithOptsError { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] -#[error(from_sources)] +#[stack_error(derive, add_meta, from_sources)] #[non_exhaustive] pub enum ConnectError { #[error(transparent)] @@ -516,9 +512,7 @@ pub enum ConnectError { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] -#[error(from_sources)] +#[stack_error(derive, add_meta, from_sources)] #[non_exhaustive] pub enum BindError { #[error(transparent)] @@ -532,8 +526,7 @@ pub enum BindError { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] pub enum GetMappingAddressError { #[error("Discovery service required due to missing addressing information")] @@ -1514,9 +1507,7 @@ pub struct Connecting { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] -#[error(from_sources, std_sources)] +#[stack_error(derive, add_meta, from_sources, std_sources)] #[non_exhaustive] pub enum AlpnError { #[error(transparent)] @@ -1682,8 +1673,7 @@ pub struct Connection { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[error("Protocol error: no remote id available")] pub struct RemoteEndpointIdError; diff --git a/iroh/src/key.rs b/iroh/src/key.rs index 2e5fe9cc973..43f58396909 100644 --- a/iroh/src/key.rs +++ b/iroh/src/key.rs @@ -4,7 +4,7 @@ use std::fmt::Debug; use aead::{AeadCore, AeadInOut, Buffer}; use iroh_base::{PublicKey, SecretKey}; -use n0_error::{Error, add_meta, e}; +use n0_error::{e, stack_error}; pub(crate) const NONCE_LEN: usize = 24; @@ -24,9 +24,7 @@ pub(super) fn secret_ed_box(key: &SecretKey) -> crypto_box::SecretKey { pub struct SharedSecret(crypto_box::ChaChaBox); /// Errors that can occur during [`SharedSecret::open`]. -#[add_meta] -#[derive(Error)] -#[error(from_sources, std_sources)] +#[stack_error(derive, add_meta, from_sources, std_sources)] #[non_exhaustive] pub enum DecryptionError { /// The nonce had the wrong size. diff --git a/iroh/src/magicsock.rs b/iroh/src/magicsock.rs index a770e7b940f..157efbe6766 100644 --- a/iroh/src/magicsock.rs +++ b/iroh/src/magicsock.rs @@ -32,7 +32,7 @@ use bytes::Bytes; use data_encoding::HEXLOWER; use iroh_base::{EndpointAddr, EndpointId, PublicKey, RelayUrl, SecretKey, TransportAddr}; use iroh_relay::{RelayConfig, RelayMap}; -use n0_error::{Error, add_meta, e}; +use n0_error::{e, stack_error}; use n0_future::{ task::{self, AbortOnDropHandle}, time::{self, Duration, Instant}, @@ -213,8 +213,7 @@ pub(crate) struct MagicSock { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] pub enum AddEndpointAddrError { #[error("Empty addressing info")] @@ -1332,8 +1331,7 @@ impl DirectAddrUpdateState { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] pub enum CreateHandleError { #[error("Failed to create bind sockets")] @@ -1711,8 +1709,7 @@ impl DiscoState { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] enum DiscoBoxError { #[error("Failed to open crypto box")] @@ -2399,8 +2396,7 @@ impl DiscoveredDirectAddrs { pub(crate) struct EndpointIdMappedAddr(Ipv6Addr); /// Can occur when converting a [`SocketAddr`] to an [`EndpointIdMappedAddr`] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[error("Failed to convert")] pub struct EndpointIdMappedAddrError; diff --git a/iroh/src/magicsock/endpoint_map.rs b/iroh/src/magicsock/endpoint_map.rs index b5502b03e97..e23da332321 100644 --- a/iroh/src/magicsock/endpoint_map.rs +++ b/iroh/src/magicsock/endpoint_map.rs @@ -721,7 +721,7 @@ impl EndpointMapInner { /// NOTE: storing an [`IpPort`] is safer than storing a [`SocketAddr`] because for IPv6 socket /// addresses include fields that can't be assumed consistent even within a single connection. #[derive(Debug, derive_more::Display, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] -#[error("{}", SocketAddr::from(*self))] +#[display("{}", SocketAddr::from(*self))] pub struct IpPort { ip: IpAddr, port: u16, diff --git a/iroh/src/magicsock/endpoint_map/endpoint_state.rs b/iroh/src/magicsock/endpoint_map/endpoint_state.rs index 39702e083ac..e4b1c2a2209 100644 --- a/iroh/src/magicsock/endpoint_map/endpoint_state.rs +++ b/iroh/src/magicsock/endpoint_map/endpoint_state.rs @@ -1287,13 +1287,13 @@ pub enum DiscoPingPurpose { #[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, derive_more::Display)] pub enum ControlMsg { /// We received a Ping from the endpoint. - #[error("ping←")] + #[display("ping←")] Ping, /// We received a Pong from the endpoint. - #[error("pong←")] + #[display("pong←")] Pong, /// We received a CallMeMaybe. - #[error("call me")] + #[display("call me")] CallMeMaybe, } @@ -1427,20 +1427,20 @@ impl RemoteInfo { #[derive(derive_more::Display, Default, Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] pub enum ConnectionType { /// Direct UDP connection - #[error("direct({_0})")] + #[display("direct({_0})")] Direct(SocketAddr), /// Relay connection over relay - #[error("relay({_0})")] + #[display("relay({_0})")] Relay(RelayUrl), /// Both a UDP and a relay connection are used. /// /// This is the case if we do have a UDP address, but are missing a recent confirmation that /// the address works. - #[error("mixed(udp: {_0}, relay: {_1})")] + #[display("mixed(udp: {_0}, relay: {_1})")] Mixed(SocketAddr, RelayUrl), /// We have no verified connection to this PublicKey #[default] - #[error("none")] + #[display("none")] None, } diff --git a/iroh/src/magicsock/transports/relay/actor.rs b/iroh/src/magicsock/transports/relay/actor.rs index 7eabe1119c1..5b9d8b226bf 100644 --- a/iroh/src/magicsock/transports/relay/actor.rs +++ b/iroh/src/magicsock/transports/relay/actor.rs @@ -44,7 +44,7 @@ use iroh_relay::{ client::{Client, ConnectError, RecvError, SendError}, protos::relay::{ClientToRelayMsg, Datagrams, RelayToClientMsg}, }; -use n0_error::{Error, add_meta, e}; +use n0_error::{e, stack_error}; use n0_future::{ FuturesUnorderedBounded, SinkExt, StreamExt, task::JoinSet, @@ -210,8 +210,7 @@ struct RelayConnectionOptions { /// Possible reasons for a failed relay connection. #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] enum RelayConnectionError { #[error("Failed to connect to relay server")] Dial { source: DialError }, @@ -222,8 +221,7 @@ enum RelayConnectionError { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] enum RunError { #[error("Send timeout")] SendTimeout, @@ -248,8 +246,7 @@ enum RunError { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] enum DialError { #[error("timeout (>{timeout:?}) trying to establish a connection")] Timeout { timeout: Duration }, diff --git a/iroh/src/net_report.rs b/iroh/src/net_report.rs index cd7a5fcaf64..4a462b02395 100644 --- a/iroh/src/net_report.rs +++ b/iroh/src/net_report.rs @@ -33,6 +33,8 @@ use iroh_relay::{ }; use n0_error::e; #[cfg(not(wasm_browser))] +use n0_error::stack_error; +#[cfg(not(wasm_browser))] use n0_future::task; use n0_future::{ StreamExt, @@ -81,8 +83,7 @@ pub(crate) use ip_mapped_addrs::{IpMappedAddr, IpMappedAddresses}; pub(crate) use self::reportgen::IfStateDetails; #[cfg(not(wasm_browser))] #[allow(missing_docs)] -#[n0_error::add_meta] -#[derive(n0_error::Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] enum QadProbeError { #[error("Failed to resolve relay address")] diff --git a/iroh/src/net_report/ip_mapped_addrs.rs b/iroh/src/net_report/ip_mapped_addrs.rs index 98d38066cde..90f1efbc964 100644 --- a/iroh/src/net_report/ip_mapped_addrs.rs +++ b/iroh/src/net_report/ip_mapped_addrs.rs @@ -7,11 +7,10 @@ use std::{ }, }; -use n0_error::{Error, add_meta, e}; +use n0_error::{e, stack_error}; /// Can occur when converting a [`SocketAddr`] to an [`IpMappedAddr`] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[error("Failed to convert")] pub struct IpMappedAddrError; diff --git a/iroh/src/net_report/reportgen.rs b/iroh/src/net_report/reportgen.rs index 55f854ab76d..fad42a2f65b 100644 --- a/iroh/src/net_report/reportgen.rs +++ b/iroh/src/net_report/reportgen.rs @@ -33,7 +33,7 @@ use iroh_relay::{ dns::{DnsError, DnsResolver, StaggeredError}, quic::QuicClient, }; -use n0_error::{Error, add_meta, e}; +use n0_error::{e, stack_error}; #[cfg(wasm_browser)] use n0_future::future::Pending; use n0_future::{ @@ -176,8 +176,7 @@ struct Actor { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] pub(super) enum ProbesError { #[error("Probe failed")] @@ -448,8 +447,7 @@ pub(super) struct HttpsProbeReport { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] pub(super) enum ProbeError { #[error("Client is gone")] @@ -461,8 +459,7 @@ pub(super) enum ProbeError { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] pub(super) enum QuicError { #[error("No relay available")] @@ -533,8 +530,7 @@ pub(super) fn maybe_to_mapped_addr( } #[cfg(not(wasm_browser))] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] enum CaptivePortalError { #[error(transparent)] @@ -653,8 +649,7 @@ fn get_quic_port(relay: &RelayConfig) -> Option { } #[cfg(not(wasm_browser))] -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] pub enum GetRelayAddrError { #[error("No valid hostname in the relay URL")] @@ -755,8 +750,7 @@ async fn relay_lookup_ipv6_staggered( } } -#[add_meta] -#[derive(Error)] +#[stack_error(derive, add_meta)] #[non_exhaustive] pub enum MeasureHttpsLatencyError { #[error(transparent)] diff --git a/iroh/src/protocol.rs b/iroh/src/protocol.rs index befd0311abb..9c2f7be526f 100644 --- a/iroh/src/protocol.rs +++ b/iroh/src/protocol.rs @@ -43,7 +43,7 @@ use std::{ }; use iroh_base::EndpointId; -use n0_error::{AnyError, Error, add_meta, e}; +use n0_error::{AnyError, e, stack_error}; use n0_future::{ join_all, task::{self, AbortOnDropHandle, JoinSet}, @@ -102,9 +102,7 @@ pub struct RouterBuilder { } #[allow(missing_docs)] -#[add_meta] -#[derive(Error)] -#[error(from_sources, std_sources)] +#[stack_error(derive, add_meta, from_sources, std_sources)] #[non_exhaustive] pub enum AcceptError { #[error(transparent)] diff --git a/iroh/src/tls/resolver.rs b/iroh/src/tls/resolver.rs index ef277823287..5f70937e8d5 100644 --- a/iroh/src/tls/resolver.rs +++ b/iroh/src/tls/resolver.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use ed25519_dalek::pkcs8::{EncodePrivateKey, spki::der::pem::LineEnding}; use iroh_base::SecretKey; -use n0_error::{Error, add_meta}; +use n0_error::stack_error; use webpki_types::{CertificateDer, PrivatePkcs8KeyDer, pem::PemObject}; #[derive(Debug)] @@ -11,9 +11,7 @@ pub(super) struct AlwaysResolvesCert { } /// Error for generating TLS configs. -#[add_meta] -#[derive(Error)] -#[error(from_sources, std_sources)] +#[stack_error(derive, add_meta, from_sources, std_sources)] #[non_exhaustive] pub(super) enum CreateConfigError { /// Rustls configuration error From 315afaf70da04c03cf41056b42c9b47b4c2730fc Mon Sep 17 00:00:00 2001 From: Frando Date: Tue, 28 Oct 2025 12:09:48 +0100 Subject: [PATCH 40/58] bump n0-error --- Cargo.lock | 24 ++++++++++++------------ iroh-base/Cargo.toml | 2 +- iroh-dns-server/Cargo.toml | 2 +- iroh-relay/Cargo.toml | 2 +- iroh/Cargo.toml | 2 +- iroh/bench/Cargo.toml | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 59f670a4101..26041cde76e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1162,7 +1162,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -1925,7 +1925,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -2330,7 +2330,7 @@ dependencies = [ [[package]] name = "iroh-metrics" version = "0.36.2" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#3268f15ee3d97dbaafcbbc9886268c9164c55cca" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#1b3d0c981c38ef62676f9bb6955893c1230b76f8" dependencies = [ "http-body-util", "hyper", @@ -2349,7 +2349,7 @@ dependencies = [ [[package]] name = "iroh-metrics-derive" version = "0.3.1" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#3268f15ee3d97dbaafcbbc9886268c9164c55cca" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#1b3d0c981c38ef62676f9bb6955893c1230b76f8" dependencies = [ "heck", "proc-macro2", @@ -2720,7 +2720,7 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fstackerr-macro#1198276e78a319ff73dbd8335de6674473f20105" +source = "git+https://github.com/n0-computer/n0-error?branch=main#c00949c842d9907ca6446a7c2fcbee9915a2773a" dependencies = [ "anyhow", "derive_more 2.0.1", @@ -2731,7 +2731,7 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=Frando%2Fstackerr-macro#1198276e78a319ff73dbd8335de6674473f20105" +source = "git+https://github.com/n0-computer/n0-error?branch=main#c00949c842d9907ca6446a7c2fcbee9915a2773a" dependencies = [ "darling", "heck", @@ -2927,7 +2927,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -3397,7 +3397,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.6.1", + "socket2 0.5.10", "thiserror 2.0.17", "tokio", "tracing", @@ -3434,9 +3434,9 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.1", + "socket2 0.5.10", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -3735,7 +3735,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -4415,7 +4415,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] diff --git a/iroh-base/Cargo.toml b/iroh-base/Cargo.toml index 468ac33999b..a409c2eaf47 100644 --- a/iroh-base/Cargo.toml +++ b/iroh-base/Cargo.toml @@ -22,7 +22,7 @@ derive_more = { version = "2.0.1", features = ["display"], optional = true } url = { version = "2.5.3", features = ["serde"], optional = true } rand_core = { version = "0.9.3", optional = true } serde = { version = "1", features = ["derive", "rc"] } -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/stackerr-macro" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } zeroize = { version = "1.8.2", optional = true, features = ["derive"] } zeroize_derive = { version = "1.4.2", optional = true } # needed for minimal versions diff --git a/iroh-dns-server/Cargo.toml b/iroh-dns-server/Cargo.toml index 3579d2b905f..bb5e24fe3d1 100644 --- a/iroh-dns-server/Cargo.toml +++ b/iroh-dns-server/Cargo.toml @@ -39,7 +39,7 @@ rustls = { version = "0.23.33", default-features = false, features = ["ring"] } rustls-pemfile = { version = "2.1" } serde = { version = "1", features = ["derive"] } struct_iterable = "0.1.1" -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/stackerr-macro" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } strum = { version = "0.27", features = ["derive"] } tokio = { version = "1", features = ["full"] } tokio-rustls = { version = "0.26", default-features = false, features = [ diff --git a/iroh-relay/Cargo.toml b/iroh-relay/Cargo.toml index 9fd04856a18..02bdd62650f 100644 --- a/iroh-relay/Cargo.toml +++ b/iroh-relay/Cargo.toml @@ -70,7 +70,7 @@ webpki_types = { package = "rustls-pki-types", version = "1.12" } data-encoding = "2.6.0" lru = "0.16" z32 = "1.0.3" -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/stackerr-macro" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } # server feature clap = { version = "4", features = ["derive"], optional = true } diff --git a/iroh/Cargo.toml b/iroh/Cargo.toml index 10ba8d815a7..de2fbe3007f 100644 --- a/iroh/Cargo.toml +++ b/iroh/Cargo.toml @@ -39,7 +39,7 @@ http = "1" iroh-base = { version = "0.94.1", default-features = false, features = ["key", "relay"], path = "../iroh-base" } iroh-relay = { version = "0.94", path = "../iroh-relay", default-features = false } n0-future = "0.3.0" -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/stackerr-macro" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } n0-watcher = "0.4" nested_enum_utils = "0.2.1" netwatch = { version = "0.11" } diff --git a/iroh/bench/Cargo.toml b/iroh/bench/Cargo.toml index acda382050d..1c44f5e30c7 100644 --- a/iroh/bench/Cargo.toml +++ b/iroh/bench/Cargo.toml @@ -11,7 +11,7 @@ hdrhistogram = { version = "7.2", default-features = false } iroh = { path = ".." } iroh-metrics = "0.36" n0-future = "0.3.0" -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "Frando/stackerr-macro" } +n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } quinn = { package = "iroh-quinn", version = "0.14" } rand = "0.9.2" rcgen = "0.14" From ad42cf160b23f4b435794e02ab4d1b10510639f1 Mon Sep 17 00:00:00 2001 From: Frando Date: Tue, 28 Oct 2025 12:55:26 +0100 Subject: [PATCH 41/58] bump n0-error, rename e() to anyerr() --- Cargo.lock | 24 +-- iroh-dns-server/examples/convert.rs | 4 +- iroh-dns-server/examples/resolve.rs | 2 +- iroh-dns-server/src/config.rs | 2 +- iroh-dns-server/src/dns.rs | 18 +- iroh-dns-server/src/dns/node_authority.rs | 4 +- iroh-dns-server/src/http.rs | 16 +- iroh-dns-server/src/http/doh.rs | 4 +- iroh-dns-server/src/http/tls.rs | 8 +- iroh-dns-server/src/lib.rs | 40 ++-- iroh-dns-server/src/server.rs | 8 +- iroh-dns-server/src/store/signed_packets.rs | 60 +++--- iroh-dns-server/src/util.rs | 14 +- iroh-relay/src/protos/handshake.rs | 12 +- iroh-relay/src/server/client.rs | 10 +- iroh-relay/src/server/clients.rs | 2 +- iroh-relay/src/server/streams.rs | 2 +- iroh/bench/src/iroh.rs | 4 +- iroh/bench/src/quinn.rs | 8 +- iroh/examples/0rtt.rs | 28 +-- iroh/examples/connect-unreliable.rs | 7 +- iroh/examples/connect.rs | 10 +- iroh/examples/dht_discovery.rs | 12 +- iroh/examples/echo-no-router.rs | 16 +- iroh/examples/echo.rs | 10 +- iroh/examples/listen-unreliable.rs | 7 +- iroh/examples/listen.rs | 12 +- iroh/examples/screening-connection.rs | 10 +- iroh/examples/search.rs | 12 +- iroh/examples/transfer.rs | 20 +- iroh/src/discovery/pkarr/dht.rs | 6 +- iroh/src/endpoint.rs | 225 ++++++++++---------- iroh/src/magicsock.rs | 4 +- iroh/src/net_report.rs | 3 +- iroh/src/net_report/reportgen.rs | 5 +- iroh/src/protocol.rs | 8 +- iroh/tests/integration.rs | 20 +- 37 files changed, 341 insertions(+), 316 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 26041cde76e..63f6c54e5d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1162,7 +1162,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1925,7 +1925,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.1", "tokio", "tower-service", "tracing", @@ -2330,7 +2330,7 @@ dependencies = [ [[package]] name = "iroh-metrics" version = "0.36.2" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#1b3d0c981c38ef62676f9bb6955893c1230b76f8" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#4f7afa784b5efe8ee013145dfd7907abab2dc59d" dependencies = [ "http-body-util", "hyper", @@ -2349,7 +2349,7 @@ dependencies = [ [[package]] name = "iroh-metrics-derive" version = "0.3.1" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#1b3d0c981c38ef62676f9bb6955893c1230b76f8" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#4f7afa784b5efe8ee013145dfd7907abab2dc59d" dependencies = [ "heck", "proc-macro2", @@ -2720,7 +2720,7 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=main#c00949c842d9907ca6446a7c2fcbee9915a2773a" +source = "git+https://github.com/n0-computer/n0-error?branch=main#e3d7f3c44399c4c4dafb43331ae0ee98ee9ebb95" dependencies = [ "anyhow", "derive_more 2.0.1", @@ -2731,7 +2731,7 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=main#c00949c842d9907ca6446a7c2fcbee9915a2773a" +source = "git+https://github.com/n0-computer/n0-error?branch=main#e3d7f3c44399c4c4dafb43331ae0ee98ee9ebb95" dependencies = [ "darling", "heck", @@ -2927,7 +2927,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3397,7 +3397,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.5.10", + "socket2 0.6.1", "thiserror 2.0.17", "tokio", "tracing", @@ -3434,9 +3434,9 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.1", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -3735,7 +3735,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4415,7 +4415,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/iroh-dns-server/examples/convert.rs b/iroh-dns-server/examples/convert.rs index ca5a9cb1cd7..1f6a2eb88ed 100644 --- a/iroh-dns-server/examples/convert.rs +++ b/iroh-dns-server/examples/convert.rs @@ -21,11 +21,11 @@ fn main() -> Result<()> { match args.command { Command::EndpointToPkarr { endpoint_id } => { let endpoint_id = EndpointId::from_str(&endpoint_id)?; - let public_key = pkarr::PublicKey::try_from(endpoint_id.as_bytes()).e()?; + let public_key = pkarr::PublicKey::try_from(endpoint_id.as_bytes()).anyerr()?; println!("{}", public_key.to_z32()) } Command::PkarrToEndpoint { z32_pubkey } => { - let public_key = pkarr::PublicKey::try_from(z32_pubkey.as_str()).e()?; + let public_key = pkarr::PublicKey::try_from(z32_pubkey.as_str()).anyerr()?; let endpoint_id = EndpointId::from_bytes(public_key.as_bytes())?; println!("{endpoint_id}") } diff --git a/iroh-dns-server/examples/resolve.rs b/iroh-dns-server/examples/resolve.rs index c91784c49de..e9c536bbcf2 100644 --- a/iroh-dns-server/examples/resolve.rs +++ b/iroh-dns-server/examples/resolve.rs @@ -49,7 +49,7 @@ async fn main() -> Result<()> { let resolver = if let Some(host) = args.dns_server { let addr = tokio::net::lookup_host(host) .await - .e()? + .anyerr()? .next() .context("failed to resolve DNS server address")?; DnsResolver::with_nameserver(addr) diff --git a/iroh-dns-server/src/config.rs b/iroh-dns-server/src/config.rs index d1770f6e4a4..9f602990099 100644 --- a/iroh-dns-server/src/config.rs +++ b/iroh-dns-server/src/config.rs @@ -163,7 +163,7 @@ impl Config { let s = tokio::fs::read_to_string(path.as_ref()) .await .with_std_context(|_| format!("failed to read {}", path.as_ref().to_string_lossy()))?; - let config: Config = toml::from_str(&s).e()?; + let config: Config = toml::from_str(&s).anyerr()?; Ok(config) } diff --git a/iroh-dns-server/src/dns.rs b/iroh-dns-server/src/dns.rs index 72b9111df8d..f12273df4a6 100644 --- a/iroh-dns-server/src/dns.rs +++ b/iroh-dns-server/src/dns.rs @@ -82,12 +82,12 @@ impl DnsServer { config.port, ); - let socket = UdpSocket::bind(bind_addr).await.e()?; + let socket = UdpSocket::bind(bind_addr).await.anyerr()?; - let socket_addr = socket.local_addr().e()?; + let socket_addr = socket.local_addr().anyerr()?; server.register_socket(socket); - server.register_listener(TcpListener::bind(bind_addr).await.e()?, TCP_TIMEOUT); + server.register_listener(TcpListener::bind(bind_addr).await.anyerr()?, TCP_TIMEOUT); info!("DNS server listening on {}", bind_addr); Ok(Self { @@ -103,7 +103,7 @@ impl DnsServer { /// Shutdown the server an wait for all tasks to complete. pub async fn shutdown(mut self) -> Result<()> { - self.server.shutdown_gracefully().await.e()?; + self.server.shutdown_gracefully().await.anyerr()?; Ok(()) } @@ -111,7 +111,7 @@ impl DnsServer { /// /// Runs forever unless tasks fail. pub async fn run_until_done(mut self) -> Result<()> { - self.server.block_until_done().await.e()?; + self.server.block_until_done().await.anyerr()?; Ok(()) } } @@ -133,7 +133,7 @@ impl DnsHandler { .iter() .map(Name::from_utf8) .collect::, _>>() - .e()?; + .anyerr()?; let (static_authority, serial) = create_static_authority(&origins, config)?; let authority = Arc::new(NodeAuthority::new( @@ -159,7 +159,7 @@ impl DnsHandler { let (tx, mut rx) = broadcast::channel(1); let response_handle = Handle(tx); self.handle_request(&request, response_handle).await; - rx.recv().await.e() + rx.recv().await.anyerr() } } @@ -234,7 +234,7 @@ fn create_static_authority( config.default_soa.split_ascii_whitespace(), None, ) - .e()? + .anyerr()? .into_soa() .map_err(|_| anyerr!("Couldn't parse SOA: {}", config.default_soa))?; let serial = soa.serial(); @@ -260,7 +260,7 @@ fn create_static_authority( ); } if let Some(ns) = &config.rr_ns { - let ns = Name::parse(ns, Some(&Name::root())).e()?; + let ns = Name::parse(ns, Some(&Name::root())).anyerr()?; push_record( &mut records, serial, diff --git a/iroh-dns-server/src/dns/node_authority.rs b/iroh-dns-server/src/dns/node_authority.rs index ce8c07d3fc8..db047b2be5f 100644 --- a/iroh-dns-server/src/dns/node_authority.rs +++ b/iroh-dns-server/src/dns/node_authority.rs @@ -189,10 +189,10 @@ fn parse_name_as_pkarr_with_origin( let labels = name.iter().rev(); let mut labels_without_origin = labels.skip(origin.num_labels() as usize); let pkey_label = labels_without_origin.next().expect("length checked above"); - let pkey_str = std::str::from_utf8(pkey_label).e()?; + let pkey_str = std::str::from_utf8(pkey_label).anyerr()?; let pkey = PublicKeyBytes::from_z32(pkey_str).context("not a valid pkarr name: invalid pubkey")?; - let remaining_name = Name::from_labels(labels_without_origin.rev()).e()?; + let remaining_name = Name::from_labels(labels_without_origin.rev()).anyerr()?; return Ok((remaining_name, pkey, origin.clone())); } bail_any!("name does not match any allowed origin"); diff --git a/iroh-dns-server/src/http.rs b/iroh-dns-server/src/http.rs index cac8b423fb2..cc993ffcb24 100644 --- a/iroh-dns-server/src/http.rs +++ b/iroh-dns-server/src/http.rs @@ -88,8 +88,12 @@ impl HttpServer { config.port, ); let app = app.clone(); - let listener = TcpListener::bind(bind_addr).await.e()?.into_std().e()?; - let bound_addr = listener.local_addr().e()?; + let listener = TcpListener::bind(bind_addr) + .await + .anyerr()? + .into_std() + .anyerr()?; + let bound_addr = listener.local_addr().anyerr()?; let fut = axum_server::from_tcp(listener) .serve(app.into_make_service_with_connect_info::()); info!("HTTP server listening on {bind_addr}"); @@ -124,8 +128,12 @@ impl HttpServer { ) .await? }; - let listener = TcpListener::bind(bind_addr).await.e()?.into_std().e()?; - let bound_addr = listener.local_addr().e()?; + let listener = TcpListener::bind(bind_addr) + .await + .anyerr()? + .into_std() + .anyerr()?; + let bound_addr = listener.local_addr().anyerr()?; let fut = axum_server::from_tcp(listener) .acceptor(acceptor) .serve(app.into_make_service_with_connect_info::()); diff --git a/iroh-dns-server/src/http/doh.rs b/iroh-dns-server/src/http/doh.rs index 30e013648bf..984d372853e 100644 --- a/iroh-dns-server/src/http/doh.rs +++ b/iroh-dns-server/src/http/doh.rs @@ -32,7 +32,7 @@ pub async fn get( DnsRequestQuery(request, accept_type): DnsRequestQuery, ) -> AppResult { let message_bytes = state.dns_handler.answer_request(request).await?; - let message = proto::op::Message::from_bytes(&message_bytes).e()?; + let message = proto::op::Message::from_bytes(&message_bytes).anyerr()?; let min_ttl = message.answers().iter().map(|rec| rec.ttl()).min(); @@ -49,7 +49,7 @@ pub async fn get( .insert(CONTENT_TYPE, accept_type.to_header_value()); if let Some(min_ttl) = min_ttl { - let maxage = HeaderValue::from_str(&format!("s-maxage={min_ttl}")).e()?; + let maxage = HeaderValue::from_str(&format!("s-maxage={min_ttl}")).anyerr()?; response.headers_mut().insert(CACHE_CONTROL, maxage); } diff --git a/iroh-dns-server/src/http/tls.rs b/iroh-dns-server/src/http/tls.rs index 5db0e7ec0d7..624bf0e44e1 100644 --- a/iroh-dns-server/src/http/tls.rs +++ b/iroh-dns-server/src/http/tls.rs @@ -75,10 +75,10 @@ impl Acce impl TlsAcceptor { async fn self_signed(domains: Vec) -> Result { let rcgen::CertifiedKey { cert, signing_key } = - rcgen::generate_simple_self_signed(domains).e()?; + rcgen::generate_simple_self_signed(domains).anyerr()?; let config = RustlsConfig::from_der(vec![cert.der().to_vec()], signing_key.serialize_der()) .await - .e()?; + .anyerr()?; let acceptor = RustlsAcceptor::new(config); Ok(Self::Manual(acceptor)) } @@ -96,7 +96,7 @@ impl TlsAcceptor { let certs = load_certs(cert_path).await?; let secret_key = load_secret_key(key_path).await?; - let config = config.with_single_cert(certs, secret_key).e()?; + let config = config.with_single_cert(certs, secret_key).anyerr()?; let config = RustlsConfig::from_config(Arc::new(config)); let acceptor = RustlsAcceptor::new(config); Ok(Self::Manual(acceptor)) @@ -143,7 +143,7 @@ async fn load_certs( .std_context("cannot open certificate file")?; let mut reader = std::io::Cursor::new(certfile); let certs: Result, std::io::Error> = rustls_pemfile::certs(&mut reader).collect(); - let certs = certs.e()?; + let certs = certs.anyerr()?; Ok(certs) } diff --git a/iroh-dns-server/src/lib.rs b/iroh-dns-server/src/lib.rs index 5383e80ad9d..a20573603fc 100644 --- a/iroh-dns-server/src/lib.rs +++ b/iroh-dns-server/src/lib.rs @@ -55,98 +55,98 @@ mod tests { let mut packet = dns::Packet::new_reply(0); // record at root packet.answers.push(dns::ResourceRecord::new( - dns::Name::new("").e()?, + dns::Name::new("").anyerr()?, dns::CLASS::IN, 30, dns::rdata::RData::TXT("hi0".try_into().unwrap()), )); // record at level one packet.answers.push(dns::ResourceRecord::new( - dns::Name::new("_hello").e()?, + dns::Name::new("_hello").anyerr()?, dns::CLASS::IN, 30, dns::rdata::RData::TXT("hi1".try_into().unwrap()), )); // record at level two packet.answers.push(dns::ResourceRecord::new( - dns::Name::new("_hello.world").e()?, + dns::Name::new("_hello.world").anyerr()?, dns::CLASS::IN, 30, dns::rdata::RData::TXT("hi2".try_into().unwrap()), )); // multiple records for same name packet.answers.push(dns::ResourceRecord::new( - dns::Name::new("multiple").e()?, + dns::Name::new("multiple").anyerr()?, dns::CLASS::IN, 30, dns::rdata::RData::TXT("hi3".try_into().unwrap()), )); packet.answers.push(dns::ResourceRecord::new( - dns::Name::new("multiple").e()?, + dns::Name::new("multiple").anyerr()?, dns::CLASS::IN, 30, dns::rdata::RData::TXT("hi4".try_into().unwrap()), )); // record of type A packet.answers.push(dns::ResourceRecord::new( - dns::Name::new("").e()?, + dns::Name::new("").anyerr()?, dns::CLASS::IN, 30, dns::rdata::RData::A(Ipv4Addr::LOCALHOST.into()), )); // record of type AAAA packet.answers.push(dns::ResourceRecord::new( - dns::Name::new("foo.bar.baz").e()?, + dns::Name::new("foo.bar.baz").anyerr()?, dns::CLASS::IN, 30, dns::rdata::RData::AAAA(Ipv6Addr::LOCALHOST.into()), )); - SignedPacket::new(&keypair, &packet.answers, Timestamp::now()).e()? + SignedPacket::new(&keypair, &packet.answers, Timestamp::now()).anyerr()? }; let pkarr_client = pkarr::Client::builder() .no_default_network() .relays(&[pkarr_relay_url]) - .e()? + .anyerr()? .build() - .e()?; - pkarr_client.publish(&signed_packet, None).await.e()?; + .anyerr()?; + pkarr_client.publish(&signed_packet, None).await.anyerr()?; use hickory_server::proto::rr::Name; let pubkey = signed_packet.public_key().to_z32(); let resolver = test_resolver(nameserver); // resolve root record - let name = Name::from_utf8(format!("{pubkey}.")).e()?; + let name = Name::from_utf8(format!("{pubkey}.")).anyerr()?; let res = resolver.lookup_txt(name, DNS_TIMEOUT).await?; let records = res.into_iter().map(|t| t.to_string()).collect::>(); assert_eq!(records, vec!["hi0".to_string()]); // resolve level one record - let name = Name::from_utf8(format!("_hello.{pubkey}.")).e()?; + let name = Name::from_utf8(format!("_hello.{pubkey}.")).anyerr()?; let res = resolver.lookup_txt(name, DNS_TIMEOUT).await?; let records = res.into_iter().map(|t| t.to_string()).collect::>(); assert_eq!(records, vec!["hi1".to_string()]); // resolve level two record - let name = Name::from_utf8(format!("_hello.world.{pubkey}.")).e()?; + let name = Name::from_utf8(format!("_hello.world.{pubkey}.")).anyerr()?; let res = resolver.lookup_txt(name, DNS_TIMEOUT).await?; let records = res.into_iter().map(|t| t.to_string()).collect::>(); assert_eq!(records, vec!["hi2".to_string()]); // resolve multiple records for same name - let name = Name::from_utf8(format!("multiple.{pubkey}.")).e()?; + let name = Name::from_utf8(format!("multiple.{pubkey}.")).anyerr()?; let res = resolver.lookup_txt(name, DNS_TIMEOUT).await?; let records = res.into_iter().map(|t| t.to_string()).collect::>(); assert_eq!(records, vec!["hi3".to_string(), "hi4".to_string()]); // resolve A record - let name = Name::from_utf8(format!("{pubkey}.")).e()?; + let name = Name::from_utf8(format!("{pubkey}.")).anyerr()?; let res = resolver.lookup_ipv4(name, DNS_TIMEOUT).await?; let records = res.collect::>(); assert_eq!(records, vec![Ipv4Addr::LOCALHOST]); // resolve AAAA record - let name = Name::from_utf8(format!("foo.bar.baz.{pubkey}.")).e()?; + let name = Name::from_utf8(format!("foo.bar.baz.{pubkey}.")).anyerr()?; let res = resolver.lookup_ipv6(name, DNS_TIMEOUT).await?; let records = res.collect::>(); assert_eq!(records, vec![Ipv6Addr::LOCALHOST]); @@ -227,7 +227,7 @@ mod tests { let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(0u64); // run a mainline testnet - let testnet = pkarr::mainline::Testnet::new_async(5).await.e()?; + let testnet = pkarr::mainline::Testnet::new_async(5).await.anyerr()?; let bootstrap = testnet.bootstrap.clone(); // spawn our server with mainline support @@ -249,8 +249,8 @@ mod tests { .no_default_network() .dht(|builder| builder.bootstrap(&testnet.bootstrap)) .build() - .e()?; - pkarr.publish(&signed_packet, None).await.e()?; + .anyerr()?; + pkarr.publish(&signed_packet, None).await.anyerr()?; // resolve via DNS from our server, which will lookup from our DHT let resolver = test_resolver(nameserver); diff --git a/iroh-dns-server/src/server.rs b/iroh-dns-server/src/server.rs index 8eb0b515782..361e1899b8f 100644 --- a/iroh-dns-server/src/server.rs +++ b/iroh-dns-server/src/server.rs @@ -28,7 +28,7 @@ pub async fn run_with_config_until_ctrl_c(config: Config) -> Result<()> { store = store.with_mainline_fallback(bootstrap); }; let server = Server::spawn(config, store, metrics).await?; - tokio::signal::ctrl_c().await.e()?; + tokio::signal::ctrl_c().await.anyerr()?; info!("shutdown"); server.shutdown().await?; Ok(()) @@ -62,7 +62,9 @@ impl Server { if let Some(addr) = metrics_addr { let mut registry = iroh_metrics::Registry::default(); registry.register(metrics); - start_metrics_server(addr, Arc::new(registry)).await.e()?; + start_metrics_server(addr, Arc::new(registry)) + .await + .anyerr()?; } Ok(()) }); @@ -140,7 +142,7 @@ impl Server { let server = Self::spawn(config, store, Default::default()).await?; let dns_addr = server.dns_server.local_addr(); let http_addr = server.http_server.http_addr().expect("http is set"); - let http_url = format!("http://{http_addr}").parse::().e()?; + let http_url = format!("http://{http_addr}").parse::().anyerr()?; Ok((server, dns_addr, http_url)) } } diff --git a/iroh-dns-server/src/store/signed_packets.rs b/iroh-dns-server/src/store/signed_packets.rs index 4c5b1b2ca7d..8329d4e259a 100644 --- a/iroh-dns-server/src/store/signed_packets.rs +++ b/iroh-dns-server/src/store/signed_packets.rs @@ -122,15 +122,15 @@ impl Actor { }; trace!("batch"); self.recv.push_back(msg).unwrap(); - let transaction = self.db.begin_write().e()?; - let mut tables = Tables::new(&transaction).e()?; + let transaction = self.db.begin_write().anyerr()?; + let mut tables = Tables::new(&transaction).anyerr()?; let timeout = tokio::time::sleep(self.options.max_batch_time); tokio::pin!(timeout); for _ in 0..self.options.max_batch_size { tokio::select! { _ = self.cancel.cancelled() => { drop(tables); - transaction.commit().e()?; + transaction.commit().anyerr()?; return Ok(()); } _ = &mut timeout => break, @@ -158,7 +158,7 @@ impl Actor { continue; } else { // remove the old packet from the update time index - tables.update_time.remove(&existing.timestamp().to_bytes(), key.as_bytes()).e()?; + tables.update_time.remove(&existing.timestamp().to_bytes(), key.as_bytes()).anyerr()?; true } } _ => { @@ -167,9 +167,9 @@ impl Actor { }; let value = packet.serialize(); tables.signed_packets - .insert(key.as_bytes(), &value[..]).e()?; + .insert(key.as_bytes(), &value[..]).anyerr()?; tables.update_time - .insert(&packet.timestamp().to_bytes(), key.as_bytes()).e()?; + .insert(&packet.timestamp().to_bytes(), key.as_bytes()).anyerr()?; if replaced { self.metrics.store_packets_updated.inc(); } else { @@ -179,9 +179,9 @@ impl Actor { } Message::Remove { key, res } => { trace!("remove {}", key); - let updated = match tables.signed_packets.remove(key.as_bytes()).e()? { Some(row) => { - let packet = SignedPacket::deserialize(row.value()).e()?; - tables.update_time.remove(&packet.timestamp().to_bytes(), key.as_bytes()).e()?; + let updated = match tables.signed_packets.remove(key.as_bytes()).anyerr()? { Some(row) => { + let packet = SignedPacket::deserialize(row.value()).anyerr()?; + tables.update_time.remove(&packet.timestamp().to_bytes(), key.as_bytes()).anyerr()?; self.metrics.store_packets_removed.inc(); true } _ => { @@ -198,17 +198,17 @@ impl Actor { match get_packet(&tables.signed_packets, &key)? { Some(packet) => { let expired = Timestamp::now() - expiry_us; if packet.timestamp() < expired { - tables.update_time.remove(&time.to_bytes(), key.as_bytes()).e()?; - let _ = tables.signed_packets.remove(key.as_bytes()).e()?; + tables.update_time.remove(&time.to_bytes(), key.as_bytes()).anyerr()?; + let _ = tables.signed_packets.remove(key.as_bytes()).anyerr()?; self.metrics.store_packets_expired.inc(); debug!("removed expired packet {key}"); } else { debug!("packet {key} is no longer expired, removing obsolete expiry entry"); - tables.update_time.remove(&time.to_bytes(), key.as_bytes()).e()?; + tables.update_time.remove(&time.to_bytes(), key.as_bytes()).anyerr()?; } } _ => { debug!("expired packet {key} not found, remove from expiry table"); - tables.update_time.remove(&time.to_bytes(), key.as_bytes()).e()?; + tables.update_time.remove(&time.to_bytes(), key.as_bytes()).anyerr()?; }} } } @@ -216,7 +216,7 @@ impl Actor { } } drop(tables); - transaction.commit().e()?; + transaction.commit().anyerr()?; } Ok(()) } @@ -250,10 +250,10 @@ pub(super) struct Snapshot { impl Snapshot { pub fn new(db: &Database) -> Result { - let tx = db.begin_read().e()?; + let tx = db.begin_read().anyerr()?; Ok(Self { - signed_packets: tx.open_table(SIGNED_PACKETS_TABLE).e()?, - update_time: tx.open_multimap_table(UPDATE_TIME_TABLE).e()?, + signed_packets: tx.open_table(SIGNED_PACKETS_TABLE).anyerr()?, + update_time: tx.open_multimap_table(UPDATE_TIME_TABLE).anyerr()?, }) } } @@ -289,15 +289,15 @@ impl SignedPacketStore { info!("using in-memory packet database"); let db = Database::builder() .create_with_backend(InMemoryBackend::new()) - .e()?; + .anyerr()?; Self::open(db, options, metrics) } pub fn open(db: Database, options: Options, metrics: Arc) -> Result { // create tables - let write_tx = db.begin_write().e()?; - let _ = Tables::new(&write_tx).e()?; - write_tx.commit().e()?; + let write_tx = db.begin_write().anyerr()?; + let _ = Tables::new(&write_tx).anyerr()?; + write_tx.commit().anyerr()?; let (send, recv) = mpsc::channel(1024); let send2 = send.clone(); let cancel = CancellationToken::new(); @@ -329,8 +329,8 @@ impl SignedPacketStore { self.send .send(Message::Upsert { packet, res: tx }) .await - .e()?; - rx.await.e() + .anyerr()?; + rx.await.anyerr() } pub async fn get(&self, key: &PublicKeyBytes) -> Result> { @@ -338,8 +338,8 @@ impl SignedPacketStore { self.send .send(Message::Get { key: *key, res: tx }) .await - .e()?; - rx.await.e() + .anyerr()?; + rx.await.anyerr() } pub async fn remove(&self, key: &PublicKeyBytes) -> Result { @@ -347,8 +347,8 @@ impl SignedPacketStore { self.send .send(Message::Remove { key: *key, res: tx }) .await - .e()?; - rx.await.e() + .anyerr()?; + rx.await.anyerr() } } @@ -410,7 +410,7 @@ async fn evict_task_inner(send: mpsc::Sender, options: Options) -> Resu trace!("evicting packets older than {}", fmt_time(expired)); // if getting the range fails we exit the loop and shut down // if individual reads fail we log the error and limp on - for item in snapshot.update_time.range(..expired.to_bytes()).e()? { + for item in snapshot.update_time.range(..expired.to_bytes()).anyerr()? { let (time, keys) = match item { Ok(v) => v, Err(e) => { @@ -435,7 +435,9 @@ async fn evict_task_inner(send: mpsc::Sender, options: Options) -> Resu let key = PublicKeyBytes::new(key.value()); debug!("evicting expired packet {} {}", fmt_time(time), key); - send.send(Message::CheckExpired { time, key }).await.e()?; + send.send(Message::CheckExpired { time, key }) + .await + .anyerr()?; } } // sleep for the eviction interval so we don't constantly check diff --git a/iroh-dns-server/src/util.rs b/iroh-dns-server/src/util.rs index 119171bea2b..060498527c2 100644 --- a/iroh-dns-server/src/util.rs +++ b/iroh-dns-server/src/util.rs @@ -27,7 +27,7 @@ impl PublicKeyBytes { } pub fn from_z32(s: &str) -> Result { - let bytes = z32::decode(s.as_bytes()).e()?; + let bytes = z32::decode(s.as_bytes()).anyerr()?; let bytes = TryInto::<[u8; 32]>::try_into(&bytes[..]).std_context("invalid length")?; Ok(Self(bytes)) } @@ -70,7 +70,7 @@ impl From for PublicKeyBytes { impl TryFrom for pkarr::PublicKey { type Error = AnyError; fn try_from(value: PublicKeyBytes) -> Result { - pkarr::PublicKey::try_from(&value.0).e() + pkarr::PublicKey::try_from(&value.0).anyerr() } } @@ -89,7 +89,7 @@ impl AsRef<[u8; 32]> for PublicKeyBytes { pub fn signed_packet_to_hickory_message(signed_packet: &SignedPacket) -> Result { let encoded = signed_packet.encoded_packet(); - let message = Message::from_bytes(&encoded).e()?; + let message = Message::from_bytes(&encoded).anyerr()?; Ok(message) } @@ -97,7 +97,7 @@ pub fn signed_packet_to_hickory_records_without_origin( signed_packet: &SignedPacket, filter: impl Fn(&Record) -> bool, ) -> Result<(Label, BTreeMap>)> { - let common_zone = Label::from_utf8(&signed_packet.public_key().to_z32()).e()?; + let common_zone = Label::from_utf8(&signed_packet.public_key().to_z32()).anyerr()?; let mut message = signed_packet_to_hickory_message(signed_packet)?; let answers = message.take_answers(); let mut output: BTreeMap> = BTreeMap::new(); @@ -111,7 +111,7 @@ pub fn signed_packet_to_hickory_records_without_origin( if name.num_labels() < 1 { continue; } - let zone = name.iter().next_back().unwrap().into_label().e()?; + let zone = name.iter().next_back().unwrap().into_label().anyerr()?; if zone != common_zone { continue; } @@ -120,7 +120,7 @@ pub fn signed_packet_to_hickory_records_without_origin( } let name_without_zone = - Name::from_labels(name.iter().take(name.num_labels() as usize - 1)).e()?; + Name::from_labels(name.iter().take(name.num_labels() as usize - 1)).anyerr()?; record.set_name(name_without_zone); let rrkey = RrKey::new(record.name().into(), record.record_type()); @@ -145,7 +145,7 @@ pub fn record_set_append_origin( origin: &Name, serial: u32, ) -> Result { - let new_name = input.name().clone().append_name(origin).e()?; + let new_name = input.name().clone().append_name(origin).anyerr()?; let mut output = RecordSet::new(new_name.clone(), input.record_type(), serial); // TODO: less clones for record in input.records_without_rrsigs() { diff --git a/iroh-relay/src/protos/handshake.rs b/iroh-relay/src/protos/handshake.rs index 58daa233658..2f1123550df 100644 --- a/iroh-relay/src/protos/handshake.rs +++ b/iroh-relay/src/protos/handshake.rs @@ -769,8 +769,8 @@ mod tests { let challenge = ServerChallenge::new(&mut rng); let client_auth = ClientAuth::new(&secret_key, &challenge); - let bytes = postcard::to_allocvec(&client_auth).e()?; - let decoded: ClientAuth = postcard::from_bytes(&bytes).e()?; + let bytes = postcard::to_allocvec(&client_auth).anyerr()?; + let decoded: ClientAuth = postcard::from_bytes(&bytes).anyerr()?; assert_eq!(client_auth.public_key, decoded.public_key); assert_eq!(client_auth.signature, decoded.signature); @@ -789,10 +789,10 @@ mod tests { shared_secret: Some(42), }, ) - .e()?; + .anyerr()?; - let bytes = postcard::to_allocvec(&client_auth).e()?; - let decoded: KeyMaterialClientAuth = postcard::from_bytes(&bytes).e()?; + let bytes = postcard::to_allocvec(&client_auth).anyerr()?; + let decoded: KeyMaterialClientAuth = postcard::from_bytes(&bytes).anyerr()?; assert_eq!(client_auth.public_key, decoded.public_key); assert_eq!(client_auth.signature, decoded.signature); @@ -819,7 +819,7 @@ mod tests { inner: (), shared_secret: Some(42), }; - let client_auth = KeyMaterialClientAuth::new(&secret_key, &io).e()?; + let client_auth = KeyMaterialClientAuth::new(&secret_key, &io).anyerr()?; assert!(client_auth.verify(&io).is_ok()); Ok(()) diff --git a/iroh-relay/src/server/client.rs b/iroh-relay/src/server/client.rs index 191b70f2ad7..81cf58c9a16 100644 --- a/iroh-relay/src/server/client.rs +++ b/iroh-relay/src/server/client.rs @@ -561,7 +561,7 @@ mod tests { } Ok(frame) } - Some(Err(err)) => Err(err).e(), + Some(Err(err)) => Err(err).anyerr(), None => n0_error::bail_any!("Unexpected EOF, expected frame {frame_type:?}"), } } @@ -616,7 +616,7 @@ mod tests { .std_context("send")?; let frame = recv_frame(FrameType::RelayToClientDatagram, &mut io_rw) .await - .e()?; + .anyerr()?; assert_eq!( frame, RelayToClientMsg::Datagrams { @@ -633,7 +633,7 @@ mod tests { .std_context("send")?; let frame = recv_frame(FrameType::RelayToClientDatagram, &mut io_rw) .await - .e()?; + .anyerr()?; assert_eq!( frame, RelayToClientMsg::Datagrams { @@ -645,7 +645,9 @@ mod tests { // send peer_gone println!("send peer gone"); peer_gone_s.send(endpoint_id).await.std_context("send")?; - let frame = recv_frame(FrameType::EndpointGone, &mut io_rw).await.e()?; + let frame = recv_frame(FrameType::EndpointGone, &mut io_rw) + .await + .anyerr()?; assert_eq!(frame, RelayToClientMsg::EndpointGone(endpoint_id)); // Read tests diff --git a/iroh-relay/src/server/clients.rs b/iroh-relay/src/server/clients.rs index ab4166bcfe5..7fe77784e00 100644 --- a/iroh-relay/src/server/clients.rs +++ b/iroh-relay/src/server/clients.rs @@ -223,7 +223,7 @@ mod tests { } Ok(frame) } - Some(Err(err)) => Err(err).e(), + Some(Err(err)) => Err(err).anyerr(), None => n0_error::bail_any!("Unexpected EOF, expected frame {frame_type:?}"), } } diff --git a/iroh-relay/src/server/streams.rs b/iroh-relay/src/server/streams.rs index 8b3cca3459c..9745e7c2f64 100644 --- a/iroh-relay/src/server/streams.rs +++ b/iroh-relay/src/server/streams.rs @@ -527,7 +527,7 @@ mod tests { }, ) .await - .e()?; + .anyerr()?; let duration = time::Instant::now().duration_since(before); assert_ne!(duration.as_millis(), 0); diff --git a/iroh/bench/src/iroh.rs b/iroh/bench/src/iroh.rs index ae22a7d25e2..f8dd6bd1878 100644 --- a/iroh/bench/src/iroh.rs +++ b/iroh/bench/src/iroh.rs @@ -154,7 +154,7 @@ async fn drain_stream( let mut num_chunks: u64 = 0; if read_unordered { - while let Some(chunk) = stream.read_chunk(usize::MAX, false).await.e()? { + while let Some(chunk) = stream.read_chunk(usize::MAX, false).await.anyerr()? { if first_byte { ttfb = download_start.elapsed(); first_byte = false; @@ -176,7 +176,7 @@ async fn drain_stream( Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), ]; - while let Some(n) = stream.read_chunks(&mut bufs[..]).await.e()? { + while let Some(n) = stream.read_chunks(&mut bufs[..]).await.anyerr()? { if first_byte { ttfb = download_start.elapsed(); first_byte = false; diff --git a/iroh/bench/src/quinn.rs b/iroh/bench/src/quinn.rs index b36880b0059..fcb340ce702 100644 --- a/iroh/bench/src/quinn.rs +++ b/iroh/bench/src/quinn.rs @@ -73,7 +73,7 @@ pub async fn connect_client( quinn::Endpoint::client(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0)).unwrap(); let mut roots = RootCertStore::empty(); - roots.add(server_cert).e()?; + roots.add(server_cert).anyerr()?; let provider = rustls::crypto::ring::default_provider(); @@ -84,7 +84,7 @@ pub async fn connect_client( .with_no_client_auth(); let mut client_config = - quinn::ClientConfig::new(Arc::new(QuicClientConfig::try_from(crypto).e()?)); + quinn::ClientConfig::new(Arc::new(QuicClientConfig::try_from(crypto).anyerr()?)); client_config.transport_config(Arc::new(transport_config(opt.max_streams, opt.initial_mtu))); let connection = endpoint @@ -125,7 +125,7 @@ async fn drain_stream( let mut num_chunks: u64 = 0; if read_unordered { - while let Some(chunk) = stream.read_chunk(usize::MAX, false).await.e()? { + while let Some(chunk) = stream.read_chunk(usize::MAX, false).await.anyerr()? { if first_byte { ttfb = download_start.elapsed(); first_byte = false; @@ -147,7 +147,7 @@ async fn drain_stream( Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), ]; - while let Some(n) = stream.read_chunks(&mut bufs[..]).await.e()? { + while let Some(n) = stream.read_chunks(&mut bufs[..]).await.anyerr()? { if first_byte { ttfb = download_start.elapsed(); first_byte = false; diff --git a/iroh/examples/0rtt.rs b/iroh/examples/0rtt.rs index 78fa317e60b..907d18b5d0a 100644 --- a/iroh/examples/0rtt.rs +++ b/iroh/examples/0rtt.rs @@ -53,22 +53,22 @@ async fn pingpong( proceed: impl Future, x: u64, ) -> Result<()> { - let (mut send, recv) = connection.open_bi().await.e()?; + let (mut send, recv) = connection.open_bi().await.anyerr()?; let data = x.to_be_bytes(); - send.write_all(&data).await.e()?; - send.finish().e()?; + send.write_all(&data).await.anyerr()?; + send.finish().anyerr()?; let mut recv = if proceed.await { // use recv directly if we can proceed recv } else { // proceed returned false, so we have learned that the 0-RTT send was rejected. // at this point we have a fully handshaked connection, so we try again. - let (mut send, recv) = connection.open_bi().await.e()?; - send.write_all(&data).await.e()?; - send.finish().e()?; + let (mut send, recv) = connection.open_bi().await.anyerr()?; + send.write_all(&data).await.anyerr()?; + send.finish().anyerr()?; recv }; - let echo = recv.read_to_end(8).await.e()?; + let echo = recv.read_to_end(8).await.anyerr()?; assert!(echo == data); Ok(()) } @@ -82,7 +82,7 @@ async fn pingpong_0rtt(connecting: Connecting, i: u64) -> Result { } Err(connecting) => { trace!("0-RTT not possible from our side"); - let connection = connecting.await.e()?; + let connection = connecting.await.anyerr()?; pingpong(&connection, future::ready(true), i).await?; connection } @@ -104,7 +104,7 @@ async fn connect(args: Args) -> Result<()> { .connect_with_opts(remote_id, PINGPONG_ALPN, Default::default()) .await?; let connection = if args.disable_0rtt { - let connection = connecting.await.e()?; + let connection = connecting.await.anyerr()?; trace!("connecting without 0-RTT"); pingpong(&connection, future::ready(true), i).await?; connection @@ -152,16 +152,16 @@ async fn accept(_args: Args) -> Result<()> { let accept = async move { while let Some(incoming) = endpoint.accept().await { tokio::spawn(async move { - let connecting = incoming.accept().e()?; + let connecting = incoming.accept().anyerr()?; let (connection, _zero_rtt_accepted) = connecting .into_0rtt() .expect("accept into 0.5 RTT always succeeds"); - let (mut send, mut recv) = connection.accept_bi().await.e()?; + let (mut send, mut recv) = connection.accept_bi().await.anyerr()?; trace!("recv.is_0rtt: {}", recv.is_0rtt()); - let data = recv.read_to_end(8).await.e()?; + let data = recv.read_to_end(8).await.anyerr()?; trace!("recv: {}", data.len()); - send.write_all(&data).await.e()?; - send.finish().e()?; + send.write_all(&data).await.anyerr()?; + send.finish().anyerr()?; connection.closed().await; n0_error::Ok(()) }); diff --git a/iroh/examples/connect-unreliable.rs b/iroh/examples/connect-unreliable.rs index 68d9c3153b4..46a19bd8dc4 100644 --- a/iroh/examples/connect-unreliable.rs +++ b/iroh/examples/connect-unreliable.rs @@ -83,11 +83,12 @@ async fn main() -> Result<()> { // Send a datagram over the connection. let message = format!("{me} is saying 'hello!'"); - conn.send_datagram(message.as_bytes().to_vec().into()).e()?; + conn.send_datagram(message.as_bytes().to_vec().into()) + .anyerr()?; // Read a datagram over the connection. - let message = conn.read_datagram().await.e()?; - let message = String::from_utf8(message.into()).e()?; + let message = conn.read_datagram().await.anyerr()?; + let message = String::from_utf8(message.into()).anyerr()?; println!("received: {message}"); Ok(()) diff --git a/iroh/examples/connect.rs b/iroh/examples/connect.rs index 26239a1584e..6ac6482519f 100644 --- a/iroh/examples/connect.rs +++ b/iroh/examples/connect.rs @@ -81,15 +81,15 @@ async fn main() -> Result<()> { info!("connected"); // Use the Quinn API to send and recv content. - let (mut send, mut recv) = conn.open_bi().await.e()?; + let (mut send, mut recv) = conn.open_bi().await.anyerr()?; let message = format!("{me} is saying 'hello!'"); - send.write_all(message.as_bytes()).await.e()?; + send.write_all(message.as_bytes()).await.anyerr()?; // Call `finish` to close the send side of the connection gracefully. - send.finish().e()?; - let message = recv.read_to_end(100).await.e()?; - let message = String::from_utf8(message).e()?; + send.finish().anyerr()?; + let message = recv.read_to_end(100).await.anyerr()?; + let message = String::from_utf8(message).anyerr()?; println!("received: {message}"); // We received the last message: close all connections and allow for the close diff --git a/iroh/examples/dht_discovery.rs b/iroh/examples/dht_discovery.rs index 213c863f9a9..5fc0ec8af45 100644 --- a/iroh/examples/dht_discovery.rs +++ b/iroh/examples/dht_discovery.rs @@ -72,7 +72,7 @@ async fn chat_server(args: Args) -> Result<()> { .bind() .await?; let zid = pkarr::PublicKey::try_from(endpoint_id.as_bytes()) - .e()? + .anyerr()? .to_z32(); println!("Listening on {endpoint_id}"); println!("pkarr z32: {zid}"); @@ -88,11 +88,11 @@ async fn chat_server(args: Args) -> Result<()> { } }; tokio::spawn(async move { - let connection = connecting.await.e()?; + let connection = connecting.await.anyerr()?; let remote_endpoint_id = connection.remote_id()?; println!("got connection from {remote_endpoint_id}"); // just leave the tasks hanging. this is just an example. - let (mut writer, mut reader) = connection.accept_bi().await.e()?; + let (mut writer, mut reader) = connection.accept_bi().await.anyerr()?; let _copy_to_stdout = tokio::spawn(async move { tokio::io::copy(&mut reader, &mut tokio::io::stdout()).await }); @@ -121,13 +121,13 @@ async fn chat_client(args: Args) -> Result<()> { println!("We are {endpoint_id} and connecting to {remote_endpoint_id}"); let connection = endpoint.connect(remote_endpoint_id, CHAT_ALPN).await?; println!("connected to {remote_endpoint_id}"); - let (mut writer, mut reader) = connection.open_bi().await.e()?; + let (mut writer, mut reader) = connection.open_bi().await.anyerr()?; let _copy_to_stdout = tokio::spawn(async move { tokio::io::copy(&mut reader, &mut tokio::io::stdout()).await }); let _copy_from_stdin = tokio::spawn(async move { tokio::io::copy(&mut tokio::io::stdin(), &mut writer).await }); - _copy_to_stdout.await.e()?.e()?; - _copy_from_stdin.await.e()?.e()?; + _copy_to_stdout.await.anyerr()?.anyerr()?; + _copy_from_stdin.await.anyerr()?.anyerr()?; Ok(()) } diff --git a/iroh/examples/echo-no-router.rs b/iroh/examples/echo-no-router.rs index 6784383e2bb..4427320d36b 100644 --- a/iroh/examples/echo-no-router.rs +++ b/iroh/examples/echo-no-router.rs @@ -39,16 +39,16 @@ async fn connect_side(addr: EndpointAddr) -> Result<()> { let conn = endpoint.connect(addr, ALPN).await?; // Open a bidirectional QUIC stream - let (mut send, mut recv) = conn.open_bi().await.e()?; + let (mut send, mut recv) = conn.open_bi().await.anyerr()?; // Send some data to be echoed - send.write_all(b"Hello, world!").await.e()?; + send.write_all(b"Hello, world!").await.anyerr()?; // Signal the end of data for this particular stream - send.finish().e()?; + send.finish().anyerr()?; // Receive the echo, but limit reading up to maximum 1000 bytes - let response = recv.read_to_end(1000).await.e()?; + let response = recv.read_to_end(1000).await.anyerr()?; assert_eq!(&response, b"Hello, world!"); // Explicitly close the whole connection. @@ -86,7 +86,7 @@ async fn start_accept_side() -> Result { while let Some(incoming) = endpoint.accept().await { // spawn a task for each incoming connection, so we can serve multiple connections asynchronously tokio::spawn(async move { - let connection = incoming.await.e()?; + let connection = incoming.await.anyerr()?; // We can get the remote's endpoint id from the connection. let endpoint_id = connection.remote_id()?; @@ -94,16 +94,16 @@ async fn start_accept_side() -> Result { // Our protocol is a simple request-response protocol, so we expect the // connecting peer to open a single bi-directional stream. - let (mut send, mut recv) = connection.accept_bi().await.e()?; + let (mut send, mut recv) = connection.accept_bi().await.anyerr()?; // Echo any bytes received back directly. // This will keep copying until the sender signals the end of data on the stream. - let bytes_sent = tokio::io::copy(&mut recv, &mut send).await.e()?; + let bytes_sent = tokio::io::copy(&mut recv, &mut send).await.anyerr()?; println!("Copied over {bytes_sent} byte(s)"); // By calling `finish` on the send stream we signal that we will not send anything // further, which makes the receive stream on the other end terminate. - send.finish().e()?; + send.finish().anyerr()?; // Wait until the remote closes the connection, which it does once it // received the response. diff --git a/iroh/examples/echo.rs b/iroh/examples/echo.rs index d8914ee15c4..2430abb14de 100644 --- a/iroh/examples/echo.rs +++ b/iroh/examples/echo.rs @@ -29,7 +29,7 @@ async fn main() -> Result<()> { connect_side(router.endpoint().addr()).await?; // This makes sure the endpoint in the router is closed properly and connections close gracefully - router.shutdown().await.e()?; + router.shutdown().await.anyerr()?; Ok(()) } @@ -41,16 +41,16 @@ async fn connect_side(addr: EndpointAddr) -> Result<()> { let conn = endpoint.connect(addr, ALPN).await?; // Open a bidirectional QUIC stream - let (mut send, mut recv) = conn.open_bi().await.e()?; + let (mut send, mut recv) = conn.open_bi().await.anyerr()?; // Send some data to be echoed - send.write_all(b"Hello, world!").await.e()?; + send.write_all(b"Hello, world!").await.anyerr()?; // Signal the end of data for this particular stream - send.finish().e()?; + send.finish().anyerr()?; // Receive the echo, but limit reading up to maximum 1000 bytes - let response = recv.read_to_end(1000).await.e()?; + let response = recv.read_to_end(1000).await.anyerr()?; assert_eq!(&response, b"Hello, world!"); // Explicitly close the whole connection. diff --git a/iroh/examples/listen-unreliable.rs b/iroh/examples/listen-unreliable.rs index 46346b15ce8..75c39ec96c7 100644 --- a/iroh/examples/listen-unreliable.rs +++ b/iroh/examples/listen-unreliable.rs @@ -72,7 +72,7 @@ async fn main() -> Result<()> { } }; let alpn = connecting.alpn().await?; - let conn = connecting.await.e()?; + let conn = connecting.await.anyerr()?; let endpoint_id = conn.remote_id()?; info!( "new (unreliable) connection from {endpoint_id} with ALPN {}", @@ -82,11 +82,12 @@ async fn main() -> Result<()> { tokio::spawn(async move { // use the `quinn` API to read a datagram off the connection, and send a datagra, in return while let Ok(message) = conn.read_datagram().await { - let message = String::from_utf8(message.into()).e()?; + let message = String::from_utf8(message.into()).anyerr()?; println!("received: {message}"); let message = format!("hi! you connected to {me}. bye bye"); - conn.send_datagram(message.as_bytes().to_vec().into()).e()?; + conn.send_datagram(message.as_bytes().to_vec().into()) + .anyerr()?; } Ok::<_, Error>(()) diff --git a/iroh/examples/listen.rs b/iroh/examples/listen.rs index 5e28f4a9648..f1e9df9e617 100644 --- a/iroh/examples/listen.rs +++ b/iroh/examples/listen.rs @@ -70,7 +70,7 @@ async fn main() -> Result<()> { } }; let alpn = connecting.alpn().await?; - let conn = connecting.await.e()?; + let conn = connecting.await.anyerr()?; let endpoint_id = conn.remote_id()?; info!( "new connection from {endpoint_id} with ALPN {}", @@ -81,16 +81,16 @@ async fn main() -> Result<()> { tokio::spawn(async move { // accept a bi-directional QUIC connection // use the `quinn` APIs to send and recv content - let (mut send, mut recv) = conn.accept_bi().await.e()?; + let (mut send, mut recv) = conn.accept_bi().await.anyerr()?; debug!("accepted bi stream, waiting for data..."); - let message = recv.read_to_end(100).await.e()?; - let message = String::from_utf8(message).e()?; + let message = recv.read_to_end(100).await.anyerr()?; + let message = String::from_utf8(message).anyerr()?; println!("received: {message}"); let message = format!("hi! you connected to {me}. bye bye"); - send.write_all(message.as_bytes()).await.e()?; + send.write_all(message.as_bytes()).await.anyerr()?; // call `finish` to close the connection gracefully - send.finish().e()?; + send.finish().anyerr()?; // We sent the last message, so wait for the client to close the connection once // it received this message. diff --git a/iroh/examples/screening-connection.rs b/iroh/examples/screening-connection.rs index 734f74af24c..a821467db02 100644 --- a/iroh/examples/screening-connection.rs +++ b/iroh/examples/screening-connection.rs @@ -40,7 +40,7 @@ async fn main() -> Result<()> { connect_side(&endpoint_addr).await?; // This makes sure the endpoint in the router is closed properly and connections close gracefully - router.shutdown().await.e()?; + router.shutdown().await.anyerr()?; Ok(()) } @@ -52,16 +52,16 @@ async fn connect_side(addr: &EndpointAddr) -> Result<()> { let conn = endpoint.connect(addr.clone(), ALPN).await?; // Open a bidirectional QUIC stream - let (mut send, mut recv) = conn.open_bi().await.e()?; + let (mut send, mut recv) = conn.open_bi().await.anyerr()?; // Send some data to be echoed - send.write_all(b"Hello, world!").await.e()?; + send.write_all(b"Hello, world!").await.anyerr()?; // Signal the end of data for this particular stream - send.finish().e()?; + send.finish().anyerr()?; // Receive the echo, but limit reading up to maximum 1000 bytes - let response = recv.read_to_end(1000).await.e()?; + let response = recv.read_to_end(1000).await.anyerr()?; assert_eq!(&response, b"Hello, world!"); // Explicitly close the whole connection. diff --git a/iroh/examples/search.rs b/iroh/examples/search.rs index 7e3edc75514..8c9a6ea9431 100644 --- a/iroh/examples/search.rs +++ b/iroh/examples/search.rs @@ -97,7 +97,7 @@ async fn main() -> Result<()> { } // Wait for Ctrl-C to be pressed. - tokio::signal::ctrl_c().await.e()?; + tokio::signal::ctrl_c().await.anyerr()?; } Command::Query { endpoint_id, query } => { // Query the remote endpoint. @@ -110,7 +110,7 @@ async fn main() -> Result<()> { } } - router.shutdown().await.e()?; + router.shutdown().await.anyerr()?; Ok(()) } @@ -178,21 +178,21 @@ impl BlobSearch { let conn = self.endpoint.connect(endpoint_id, ALPN).await?; // Open a bi-directional in our connection. - let (mut send, mut recv) = conn.open_bi().await.e()?; + let (mut send, mut recv) = conn.open_bi().await.anyerr()?; // Send our query. - send.write_all(query.as_bytes()).await.e()?; + send.write_all(query.as_bytes()).await.anyerr()?; // Finish the send stream, signalling that no further data will be sent. // This makes the `read_to_end` call on the accepting side terminate. - send.finish().e()?; + send.finish().anyerr()?; // The response is a 64 bit integer // We simply read it into a byte buffer. let mut num_matches = [0u8; 8]; // Read 8 bytes from the stream. - recv.read_exact(&mut num_matches).await.e()?; + recv.read_exact(&mut num_matches).await.anyerr()?; let num_matches = u64::from_le_bytes(num_matches); diff --git a/iroh/examples/transfer.rs b/iroh/examples/transfer.rs index 35e34ad093c..ea0c42f9554 100644 --- a/iroh/examples/transfer.rs +++ b/iroh/examples/transfer.rs @@ -339,7 +339,7 @@ async fn provide(endpoint: Endpoint, size: u64) -> Result<()> { // spawn a task to handle reading and writing off of the connection let endpoint_clone = endpoint.clone(); tokio::spawn(async move { - let conn = connecting.await.e()?; + let conn = connecting.await.anyerr()?; let endpoint_id = conn.remote_id()?; info!( "new connection from {endpoint_id} with ALPN {}", @@ -354,10 +354,10 @@ async fn provide(endpoint: Endpoint, size: u64) -> Result<()> { // accept a bi-directional QUIC connection // use the `quinn` APIs to send and recv content - let (mut send, mut recv) = conn.accept_bi().await.e()?; + let (mut send, mut recv) = conn.accept_bi().await.anyerr()?; tracing::debug!("accepted bi stream, waiting for data..."); - let message = recv.read_to_end(100).await.e()?; - let message = String::from_utf8(message).e()?; + let message = recv.read_to_end(100).await.anyerr()?; + let message = String::from_utf8(message).anyerr()?; println!("[{remote}] Received: \"{message}\""); let start = Instant::now(); @@ -407,12 +407,12 @@ async fn fetch(endpoint: Endpoint, remote_addr: EndpointAddr) -> Result<()> { let _guard = watch_conn_type(&endpoint, remote_id); // Use the Quinn API to send and recv content. - let (mut send, mut recv) = conn.open_bi().await.e()?; + let (mut send, mut recv) = conn.open_bi().await.anyerr()?; let message = format!("{me} is saying hello!"); - send.write_all(message.as_bytes()).await.e()?; + send.write_all(message.as_bytes()).await.anyerr()?; // Call `finish` to signal no more data will be sent on this stream. - send.finish().e()?; + send.finish().anyerr()?; println!("Sent: \"{message}\""); let (len, time_to_first_byte, chnk) = drain_stream(&mut recv, false).await?; @@ -421,7 +421,7 @@ async fn fetch(endpoint: Endpoint, remote_addr: EndpointAddr) -> Result<()> { // message to be sent. tokio::time::timeout(Duration::from_secs(3), endpoint.close()) .await - .e()?; + .anyerr()?; let duration = start.elapsed(); println!( @@ -448,7 +448,7 @@ async fn drain_stream( let mut num_chunks: u64 = 0; if read_unordered { - while let Some(chunk) = stream.read_chunk(usize::MAX, false).await.e()? { + while let Some(chunk) = stream.read_chunk(usize::MAX, false).await.anyerr()? { if first_byte { time_to_first_byte = download_start.elapsed(); first_byte = false; @@ -470,7 +470,7 @@ async fn drain_stream( Bytes::new(), Bytes::new(), Bytes::new(), Bytes::new(), ]; - while let Some(n) = stream.read_chunks(&mut bufs[..]).await.e()? { + while let Some(n) = stream.read_chunks(&mut bufs[..]).await.anyerr()? { if first_byte { time_to_first_byte = download_start.elapsed(); first_byte = false; diff --git a/iroh/src/discovery/pkarr/dht.rs b/iroh/src/discovery/pkarr/dht.rs index 385664213ee..720e66e5bf5 100644 --- a/iroh/src/discovery/pkarr/dht.rs +++ b/iroh/src/discovery/pkarr/dht.rs @@ -343,17 +343,17 @@ mod tests { #[traced_test] async fn dht_discovery_smoke() -> Result { let secret = SecretKey::generate(&mut rand::rng()); - let testnet = pkarr::mainline::Testnet::new_async(3).await.e()?; + let testnet = pkarr::mainline::Testnet::new_async(3).await.anyerr()?; let client = pkarr::Client::builder() .dht(|builder| builder.bootstrap(&testnet.bootstrap)) .build() - .e()?; + .anyerr()?; let discovery = DhtDiscovery::builder() .secret_key(secret.clone()) .client(client) .build()?; - let relay_url: RelayUrl = Url::parse("https://example.com").e()?.into(); + let relay_url: RelayUrl = Url::parse("https://example.com").anyerr()?.into(); let data = EndpointData::default().with_relay_url(Some(relay_url.clone())); discovery.publish(&data); diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 6313a0e62ea..52e359e5db6 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -2161,11 +2161,11 @@ mod tests { let server = tokio::spawn( async move { info!("accepting connection"); - let incoming = ep.accept().await.e()?; - let conn = incoming.await.e()?; - let mut stream = conn.accept_uni().await.e()?; + let incoming = ep.accept().await.anyerr()?; + let conn = incoming.await.anyerr()?; + let mut stream = conn.accept_uni().await.anyerr()?; let mut buf = [0u8; 5]; - stream.read_exact(&mut buf).await.e()?; + stream.read_exact(&mut buf).await.anyerr()?; info!("Accepted 1 stream, received {buf:?}. Closing now."); // close the connection conn.close(7u8.into(), b"bye"); @@ -2196,13 +2196,13 @@ mod tests { info!("client connecting"); let endpoint_addr = EndpointAddr::new(server_peer_id).with_relay_url(relay_url); let conn = ep.connect(endpoint_addr, TEST_ALPN).await?; - let mut stream = conn.open_uni().await.e()?; + let mut stream = conn.open_uni().await.anyerr()?; // First write is accepted by server. We need this bit of synchronisation // because if the server closes after simply accepting the connection we can // not be sure our .open_uni() call would succeed as it may already receive // the error. - stream.write_all(b"hello").await.e()?; + stream.write_all(b"hello").await.anyerr()?; info!("waiting for closed"); // Remote now closes the connection, we should see an error sometime soon. @@ -2228,9 +2228,9 @@ mod tests { n0_future::future::zip(server, client), ) .await - .e()?; - server.e()??; - client.e()??; + .anyerr()?; + server.anyerr()??; + client.anyerr()??; Ok(()) } @@ -2267,17 +2267,17 @@ mod tests { for i in 0..n_clients { let round_start = Instant::now(); info!("[server] round {i}"); - let incoming = ep.accept().await.e()?; - let conn = incoming.await.e()?; + let incoming = ep.accept().await.anyerr()?; + let conn = incoming.await.anyerr()?; let endpoint_id = conn.remote_id()?; info!(%i, peer = %endpoint_id.fmt_short(), "accepted connection"); - let (mut send, mut recv) = conn.accept_bi().await.e()?; + let (mut send, mut recv) = conn.accept_bi().await.anyerr()?; let mut buf = vec![0u8; chunk_size]; for _i in 0..n_chunks_per_client { - recv.read_exact(&mut buf).await.e()?; - send.write_all(&buf).await.e()?; + recv.read_exact(&mut buf).await.anyerr()?; + send.write_all(&buf).await.anyerr()?; } - send.finish().e()?; + send.finish().anyerr()?; conn.closed().await; // we're the last to send data, so we wait for the other side to close info!(%i, peer = %endpoint_id.fmt_short(), "finished"); info!("[server] round {i} done in {:?}", round_start.elapsed()); @@ -2307,14 +2307,14 @@ mod tests { let endpoint_addr = EndpointAddr::new(server_endpoint_id).with_relay_url(relay_url.clone()); info!(to = ?endpoint_addr, "client connecting"); - let conn = ep.connect(endpoint_addr, TEST_ALPN).await.e()?; + let conn = ep.connect(endpoint_addr, TEST_ALPN).await.anyerr()?; info!("client connected"); - let (mut send, mut recv) = conn.open_bi().await.e()?; + let (mut send, mut recv) = conn.open_bi().await.anyerr()?; for i in 0..n_chunks_per_client { let mut buf = vec![i; chunk_size]; - send.write_all(&buf).await.e()?; - recv.read_exact(&mut buf).await.e()?; + send.write_all(&buf).await.anyerr()?; + recv.read_exact(&mut buf).await.anyerr()?; assert_eq!(buf, vec![i; chunk_size]); } // we're the last to receive data, so we close @@ -2329,7 +2329,7 @@ mod tests { info!("[client] round {i} done in {:?}", round_start.elapsed()); } - server.await.e()??; + server.await.anyerr()??; // We appear to have seen this being very slow at times. So ensure we fail if this // test is too slow. We're only making two connections transferring very little @@ -2361,11 +2361,11 @@ mod tests { let Some(conn) = server.accept().await else { n0_error::bail_any!("Expected an incoming connection"); }; - let conn = conn.await.e()?; - let (mut send, mut recv) = conn.accept_bi().await.e()?; - let data = recv.read_to_end(1000).await.e()?; - send.write_all(&data).await.e()?; - send.finish().e()?; + let conn = conn.await.anyerr()?; + let (mut send, mut recv) = conn.accept_bi().await.anyerr()?; + let data = recv.read_to_end(1000).await.anyerr()?; + send.write_all(&data).await.anyerr()?; + send.finish().anyerr()?; conn.closed().await; Ok::<_, Error>(()) @@ -2374,13 +2374,13 @@ mod tests { let addr = server.addr(); let conn = client.connect(addr, TEST_ALPN).await?; - let (mut send, mut recv) = conn.open_bi().await.e()?; - send.write_all(b"Hello, world!").await.e()?; - send.finish().e()?; - let data = recv.read_to_end(1000).await.e()?; + let (mut send, mut recv) = conn.open_bi().await.anyerr()?; + send.write_all(b"Hello, world!").await.anyerr()?; + send.finish().anyerr()?; + let data = recv.read_to_end(1000).await.anyerr()?; conn.close(0u32.into(), b"bye!"); - task.await.e()??; + task.await.anyerr()??; client.close().await; server.close().await; @@ -2412,11 +2412,11 @@ mod tests { let Some(conn) = server.accept().await else { n0_error::bail_any!("Expected an incoming connection"); }; - let conn = conn.await.e()?; - let (mut send, mut recv) = conn.accept_bi().await.e()?; - let data = recv.read_to_end(1000).await.e()?; - send.write_all(&data).await.e()?; - send.finish().e()?; + let conn = conn.await.anyerr()?; + let (mut send, mut recv) = conn.accept_bi().await.anyerr()?; + let data = recv.read_to_end(1000).await.anyerr()?; + send.write_all(&data).await.anyerr()?; + send.finish().anyerr()?; conn.closed().await; } Ok::<_, Error>(()) @@ -2433,10 +2433,10 @@ mod tests { .retain(|addr| !matches!(addr, TransportAddr::Ip(_))); let conn = client.connect(addr, TEST_ALPN).await?; - let (mut send, mut recv) = conn.open_bi().await.e()?; - send.write_all(b"Hello, world!").await.e()?; - send.finish().e()?; - let data = recv.read_to_end(1000).await.e()?; + let (mut send, mut recv) = conn.open_bi().await.anyerr()?; + send.write_all(b"Hello, world!").await.anyerr()?; + send.finish().anyerr()?; + let data = recv.read_to_end(1000).await.anyerr()?; conn.close(0u32.into(), b"bye!"); assert_eq!(&data, b"Hello, world!"); @@ -2473,7 +2473,7 @@ mod tests { panic!("failed to change relay"); }) .await - .e()?; + .anyerr()?; println!("round2: {:?}", addr); assert_eq!(addr.relay_urls().next(), Some(&new_relay_url)); @@ -2483,13 +2483,13 @@ mod tests { .retain(|addr| !matches!(addr, TransportAddr::Ip(_))); let conn = client.connect(addr, TEST_ALPN).await?; - let (mut send, mut recv) = conn.open_bi().await.e()?; - send.write_all(b"Hello, world!").await.e()?; - send.finish().e()?; - let data = recv.read_to_end(1000).await.e()?; + let (mut send, mut recv) = conn.open_bi().await.anyerr()?; + send.write_all(b"Hello, world!").await.anyerr()?; + send.finish().anyerr()?; + let data = recv.read_to_end(1000).await.anyerr()?; conn.close(0u32.into(), b"bye!"); - task.await.e()??; + task.await.anyerr()??; client.close().await; server.close().await; @@ -2525,32 +2525,32 @@ mod tests { async fn connect_hello(ep: Endpoint, dst: EndpointId) -> Result { let conn = ep.connect(dst, TEST_ALPN).await?; - let (mut send, mut recv) = conn.open_bi().await.e()?; + let (mut send, mut recv) = conn.open_bi().await.anyerr()?; info!("sending hello"); - send.write_all(b"hello").await.e()?; - send.finish().e()?; + send.write_all(b"hello").await.anyerr()?; + send.finish().anyerr()?; info!("receiving world"); - let m = recv.read_to_end(100).await.e()?; + let m = recv.read_to_end(100).await.anyerr()?; assert_eq!(m, b"world"); conn.close(1u8.into(), b"done"); Ok(()) } async fn accept_world(ep: Endpoint, src: EndpointId) -> Result { - let incoming = ep.accept().await.e()?; - let mut iconn = incoming.accept().e()?; + let incoming = ep.accept().await.anyerr()?; + let mut iconn = incoming.accept().anyerr()?; let alpn = iconn.alpn().await?; - let conn = iconn.await.e()?; + let conn = iconn.await.anyerr()?; let endpoint_id = conn.remote_id()?; assert_eq!(endpoint_id, src); assert_eq!(alpn, TEST_ALPN); - let (mut send, mut recv) = conn.accept_bi().await.e()?; + let (mut send, mut recv) = conn.accept_bi().await.anyerr()?; info!("receiving hello"); - let m = recv.read_to_end(100).await.e()?; + let m = recv.read_to_end(100).await.anyerr()?; assert_eq!(m, b"hello"); info!("sending hello"); - send.write_all(b"world").await.e()?; - send.finish().e()?; + send.write_all(b"world").await.anyerr()?; + send.finish().anyerr()?; match conn.closed().await { ConnectionError::ApplicationClosed(closed) => { assert_eq!(closed.error_code, 1u8.into()); @@ -2589,10 +2589,10 @@ mod tests { ), )); - p1_accept.await.e()??; - p2_accept.await.e()??; - p1_connect.await.e()??; - p2_connect.await.e()??; + p1_accept.await.anyerr()??; + p2_accept.await.anyerr()??; + p1_connect.await.anyerr()??; + p2_connect.await.anyerr()??; Ok(()) } @@ -2636,7 +2636,7 @@ mod tests { async fn accept(ep: &Endpoint) -> Result { let incoming = ep.accept().await.expect("ep closed"); - let conn = incoming.await.e()?; + let conn = incoming.await.anyerr()?; let endpoint_id = conn.remote_id()?; tracing::info!(endpoint_id=%endpoint_id.fmt_short(), "accepted connection"); Ok(conn) @@ -2654,19 +2654,19 @@ mod tests { let ep1_side = tokio::time::timeout(TIMEOUT, async move { let conn = accept(&ep1).await?; - let mut send = conn.open_uni().await.e()?; + let mut send = conn.open_uni().await.anyerr()?; wait_for_conn_type_direct(&ep1, ep2_endpointid).await?; - send.write_all(b"Conn is direct").await.e()?; - send.finish().e()?; + send.write_all(b"Conn is direct").await.anyerr()?; + send.finish().anyerr()?; conn.closed().await; Ok::<(), Error>(()) }); let ep2_side = tokio::time::timeout(TIMEOUT, async move { let conn = ep2.connect(ep1_endpointaddr, TEST_ALPN).await?; - let mut recv = conn.accept_uni().await.e()?; + let mut recv = conn.accept_uni().await.anyerr()?; wait_for_conn_type_direct(&ep2, ep1_endpointid).await?; - let read = recv.read_to_end(100).await.e()?; + let read = recv.read_to_end(100).await.anyerr()?; assert_eq!(read, b"Conn is direct".to_vec()); conn.close(0u32.into(), b"done"); conn.closed().await; @@ -2676,9 +2676,9 @@ mod tests { let res_ep1 = AbortOnDropHandle::new(tokio::spawn(ep1_side)); let res_ep2 = AbortOnDropHandle::new(tokio::spawn(ep2_side)); - let (r1, r2) = tokio::try_join!(res_ep1, res_ep2).e()?; - r1.e()??; - r2.e()??; + let (r1, r2) = tokio::try_join!(res_ep1, res_ep2).anyerr()?; + r1.anyerr()??; + r2.anyerr()??; Ok(()) } @@ -2790,12 +2790,12 @@ mod tests { .into_0rtt() .expect_err("expected 0rtt to fail") .await - .e()?; + .anyerr()?; - let (mut send, mut recv) = conn.open_bi().await.e()?; - send.write_all(b"hello").await.e()?; - send.finish().e()?; - let received = recv.read_to_end(1_000).await.e()?; + let (mut send, mut recv) = conn.open_bi().await.anyerr()?; + send.write_all(b"hello").await.anyerr()?; + send.finish().anyerr()?; + let received = recv.read_to_end(1_000).await.anyerr()?; assert_eq!(&received, b"hello"); conn.close(0u32.into(), b"thx"); Ok(()) @@ -2812,13 +2812,13 @@ mod tests { .await? .into_0rtt() .ok() - .e()?; + .anyerr()?; tracing::trace!("Client established 0-RTT connection"); // This is how we send data in 0-RTT: - let (mut send, recv) = conn.open_bi().await.e()?; - send.write_all(b"hello").await.e()?; - send.finish().e()?; + let (mut send, recv) = conn.open_bi().await.anyerr()?; + send.write_all(b"hello").await.anyerr()?; + send.finish().anyerr()?; tracing::trace!("Client sent 0-RTT data, waiting for server response"); // When this resolves, we've gotten a response from the server about whether the 0-RTT data above was accepted: let accepted = accepted_0rtt.await; @@ -2828,12 +2828,12 @@ mod tests { recv } else { // in this case we need to re-send data by re-creating the connection. - let (mut send, recv) = conn.open_bi().await.e()?; - send.write_all(b"hello").await.e()?; - send.finish().e()?; + let (mut send, recv) = conn.open_bi().await.anyerr()?; + send.write_all(b"hello").await.anyerr()?; + send.finish().anyerr()?; recv }; - let received = recv.read_to_end(1_000).await.e()?; + let received = recv.read_to_end(1_000).await.anyerr()?; assert_eq!(&received, b"hello"); conn.close(0u32.into(), b"thx"); Ok(()) @@ -2920,25 +2920,25 @@ mod tests { .await?; let server_addr = server.addr(); let server_task = tokio::spawn(async move { - let incoming = server.accept().await.e()?; - let conn = incoming.await.e()?; - let (mut send, mut recv) = conn.accept_bi().await.e()?; - let msg = recv.read_to_end(1_000).await.e()?; - send.write_all(&msg).await.e()?; - send.finish().e()?; + let incoming = server.accept().await.anyerr()?; + let conn = incoming.await.anyerr()?; + let (mut send, mut recv) = conn.accept_bi().await.anyerr()?; + let msg = recv.read_to_end(1_000).await.anyerr()?; + send.write_all(&msg).await.anyerr()?; + send.finish().anyerr()?; let close_reason = conn.closed().await; Ok::<_, Error>(close_reason) }); let conn = client.connect(server_addr, TEST_ALPN).await?; - let (mut send, mut recv) = conn.open_bi().await.e()?; - send.write_all(b"Hello, world!").await.e()?; - send.finish().e()?; - recv.read_to_end(1_000).await.e()?; + let (mut send, mut recv) = conn.open_bi().await.anyerr()?; + send.write_all(b"Hello, world!").await.anyerr()?; + send.finish().anyerr()?; + recv.read_to_end(1_000).await.anyerr()?; conn.close(42u32.into(), b"thanks, bye!"); client.close().await; - let close_err = server_task.await.e()??; + let close_err = server_task.await.anyerr()??; let ConnectionError::ApplicationClosed(app_close) = close_err else { panic!("Unexpected close reason: {close_err:?}"); }; @@ -2968,19 +2968,26 @@ mod tests { .await?; let server_addr = server.addr(); let server_task = tokio::task::spawn(async move { - let conn = server.accept().await.e()?.accept().e()?.await.e()?; - let mut uni = conn.accept_uni().await.e()?; - uni.read_to_end(10).await.e()?; + let conn = server + .accept() + .await + .anyerr()? + .accept() + .anyerr()? + .await + .anyerr()?; + let mut uni = conn.accept_uni().await.anyerr()?; + uni.read_to_end(10).await.anyerr()?; drop(conn); Ok::<_, Error>(server) }); let conn = client.connect(server_addr, TEST_ALPN).await?; - let mut uni = conn.open_uni().await.e()?; - uni.write_all(b"helloworld").await.e()?; - uni.finish().e()?; + let mut uni = conn.open_uni().await.anyerr()?; + uni.write_all(b"helloworld").await.anyerr()?; + uni.finish().anyerr()?; conn.closed().await; drop(conn); - let server = server_task.await.e()??; + let server = server_task.await.anyerr()??; let m = client.metrics(); assert_eq!(m.magicsock.num_direct_conns_added.get(), 1); @@ -3005,7 +3012,7 @@ mod tests { let mut registry = Registry::default(); register_endpoint(&mut registry, &client); register_endpoint(&mut registry, &server); - let s = registry.encode_openmetrics_to_string().e()?; + let s = registry.encode_openmetrics_to_string().anyerr()?; assert!(s.contains(r#"magicsock_endpoints_contacted_directly_total{id="3b6a27bcce"} 1"#)); assert!(s.contains(r#"magicsock_endpoints_contacted_directly_total{id="8a88e3dd74"} 1"#)); Ok(()) @@ -3027,8 +3034,8 @@ mod tests { let server_task = tokio::spawn({ let server = server.clone(); async move { - let incoming = server.accept().await.e()?; - let conn = incoming.await.e()?; + let incoming = server.accept().await.anyerr()?; + let conn = incoming.await.anyerr()?; conn.close(0u32.into(), b"bye!"); n0_error::Ok(conn.alpn()) } @@ -3041,13 +3048,13 @@ mod tests { ConnectOptions::new().with_additional_alpns(secondary_connect_alpns), ) .await?; - let conn = conn.await.e()?; + let conn = conn.await.anyerr()?; let client_alpn = conn.alpn(); conn.closed().await; client.close().await; server.close().await; - let server_alpn = server_task.await.e()??; + let server_alpn = server_task.await.anyerr()??; assert_eq!(client_alpn, server_alpn); @@ -3111,7 +3118,7 @@ mod tests { let endpoint = Endpoint::empty_builder(RelayMode::Staging).bind().await?; // can get a first report - endpoint.net_report().updated().await.e()?; + endpoint.net_report().updated().await.anyerr()?; Ok(()) } @@ -3142,7 +3149,7 @@ mod tests { let endpoint = Endpoint::empty_builder(RelayMode::Disabled) .bind() .await - .e()?; + .anyerr()?; let addr = endpoint.addr(); let router = Router::builder(endpoint).accept(NOOP_ALPN, Noop).spawn(); Ok((router, addr)) @@ -3155,7 +3162,7 @@ mod tests { .await .into_iter() .collect::, _>>() - .e()?; + .anyerr()?; let addrs = routers .iter() @@ -3167,7 +3174,7 @@ mod tests { .discovery(discovery) .bind() .await - .e()?; + .anyerr()?; // wait for the endpoint to be initialized. This should not be needed, // but we don't want to measure endpoint init time but connection time // from a fully initialized endpoint. diff --git a/iroh/src/magicsock.rs b/iroh/src/magicsock.rs index 157efbe6766..b4a4b572f62 100644 --- a/iroh/src/magicsock.rs +++ b/iroh/src/magicsock.rs @@ -2907,7 +2907,7 @@ mod tests { async move { while let Some(incoming) = endpoint.accept().await { println!("Incoming first conn!"); - let conn = incoming.await.e()?; + let conn = incoming.await.anyerr()?; conn.closed().await; } @@ -3160,7 +3160,7 @@ mod tests { &tls::name::encode(endpoint_id), ) .std_context("connect")?; - let connection = connect.await.e()?; + let connection = connect.await.anyerr()?; Ok(connection) } diff --git a/iroh/src/net_report.rs b/iroh/src/net_report.rs index 4a462b02395..65b8c037361 100644 --- a/iroh/src/net_report.rs +++ b/iroh/src/net_report.rs @@ -966,7 +966,8 @@ mod tests { async fn test_basic() -> Result<()> { let (server, relay) = test_utils::relay().await; let client_config = iroh_relay::client::make_dangerous_client_config(); - let ep = quinn::Endpoint::client(SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0)).e()?; + let ep = + quinn::Endpoint::client(SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0)).anyerr()?; let quic_addr_disc = QuicConfig { ep: ep.clone(), client_config, diff --git a/iroh/src/net_report/reportgen.rs b/iroh/src/net_report/reportgen.rs index fad42a2f65b..8b9fe40642f 100644 --- a/iroh/src/net_report/reportgen.rs +++ b/iroh/src/net_report/reportgen.rs @@ -882,8 +882,9 @@ mod tests { let (server, relay) = test_utils::relay().await; let relay = Arc::new(relay); let client_config = iroh_relay::client::make_dangerous_client_config(); - let ep = quinn::Endpoint::client(SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0)).e()?; - let client_addr = ep.local_addr().e()?; + let ep = + quinn::Endpoint::client(SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0)).anyerr()?; + let client_addr = ep.local_addr().anyerr()?; let quic_client = iroh_relay::quic::QuicClient::new(ep.clone(), client_config); let dns_resolver = DnsResolver::default(); diff --git a/iroh/src/protocol.rs b/iroh/src/protocol.rs index 9c2f7be526f..078e3b3790b 100644 --- a/iroh/src/protocol.rs +++ b/iroh/src/protocol.rs @@ -586,7 +586,7 @@ mod tests { assert!(!router.is_shutdown()); assert!(!endpoint.is_closed()); - router.shutdown().await.e()?; + router.shutdown().await.anyerr()?; assert!(router.is_shutdown()); assert!(endpoint.is_closed()); @@ -630,11 +630,11 @@ mod tests { println!("connecting"); let conn = e2.connect(addr1, ECHO_ALPN).await?; - let (_send, mut recv) = conn.open_bi().await.e()?; + let (_send, mut recv) = conn.open_bi().await.anyerr()?; let response = recv.read_to_end(1000).await.unwrap_err(); assert!(format!("{response:#?}").contains("not allowed")); - r1.shutdown().await.e()?; + r1.shutdown().await.anyerr()?; e2.close().await; Ok(()) @@ -678,7 +678,7 @@ mod tests { let conn = endpoint2.connect(addr, TEST_ALPN).await?; eprintln!("starting shutdown"); - router.shutdown().await.e()?; + router.shutdown().await.anyerr()?; eprintln!("waiting for closed conn"); let reason = conn.closed().await; diff --git a/iroh/tests/integration.rs b/iroh/tests/integration.rs index 04b97490042..2102dbde32c 100644 --- a/iroh/tests/integration.rs +++ b/iroh/tests/integration.rs @@ -61,17 +61,17 @@ async fn simple_endpoint_id_based_connection_transfer() -> Result { async move { while let Some(incoming) = server.accept().await { tracing::info!("accepting connection"); - let conn = incoming.await.e()?; + let conn = incoming.await.anyerr()?; let endpoint_id = conn.remote_id()?; tracing::info!(endpoint_id = %endpoint_id.fmt_short(), "Accepted connection"); - let (mut send, mut recv) = conn.accept_bi().await.e()?; + let (mut send, mut recv) = conn.accept_bi().await.anyerr()?; let mut bytes_sent = 0; - while let Some(chunk) = recv.read_chunk(10_000, true).await.e()? { + while let Some(chunk) = recv.read_chunk(10_000, true).await.anyerr()? { bytes_sent += chunk.bytes.len(); - send.write_chunk(chunk.bytes).await.e()?; + send.write_chunk(chunk.bytes).await.anyerr()?; } - send.finish().e()?; + send.finish().anyerr()?; tracing::info!("Copied over {bytes_sent} byte(s)"); let code = conn.closed().await; @@ -111,18 +111,18 @@ async fn simple_endpoint_id_based_connection_transfer() -> Result { } }) .await - .e()?; + .anyerr()?; tracing::info!(to = %server.id().fmt_short(), "Opening a connection"); let conn = client.connect(server.id(), ECHO_ALPN).await?; tracing::info!("Connection opened"); - let (mut send, mut recv) = conn.open_bi().await.e()?; - send.write_all(b"Hello, World!").await.e()?; - send.finish().e()?; + let (mut send, mut recv) = conn.open_bi().await.anyerr()?; + send.write_all(b"Hello, World!").await.anyerr()?; + send.finish().anyerr()?; tracing::info!("Sent request"); - let response = recv.read_to_end(10_000).await.e()?; + let response = recv.read_to_end(10_000).await.anyerr()?; tracing::info!(len = response.len(), "Received response"); assert_eq!(&response, b"Hello, World!"); From e0eb6aaf2a6959df5431bc7c27bdf9a3ddd06386 Mon Sep 17 00:00:00 2001 From: Frando Date: Tue, 28 Oct 2025 13:14:06 +0100 Subject: [PATCH 42/58] fixup --- iroh/src/net_report.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iroh/src/net_report.rs b/iroh/src/net_report.rs index 65b8c037361..24484bcaeaf 100644 --- a/iroh/src/net_report.rs +++ b/iroh/src/net_report.rs @@ -67,7 +67,7 @@ mod options; pub(crate) mod portmapper { /// Output of a port mapping probe. #[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)] - #[error("portmap={{ UPnP: {upnp}, PMP: {nat_pmp}, PCP: {pcp} }}")] + #[display("portmap={{ UPnP: {upnp}, PMP: {nat_pmp}, PCP: {pcp} }}")] pub struct ProbeOutput { /// If UPnP can be considered available. pub upnp: bool, From db2c9fd8d3b2db23d7177fa803451b89186a5780 Mon Sep 17 00:00:00 2001 From: Frando Date: Tue, 28 Oct 2025 13:15:03 +0100 Subject: [PATCH 43/58] bump n0-error --- Cargo.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 63f6c54e5d1..89d0e67c290 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1162,7 +1162,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -1925,7 +1925,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -2330,7 +2330,7 @@ dependencies = [ [[package]] name = "iroh-metrics" version = "0.36.2" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#4f7afa784b5efe8ee013145dfd7907abab2dc59d" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#148ae84d9d584cd036d3f6161f2926cfada0c9b7" dependencies = [ "http-body-util", "hyper", @@ -2349,7 +2349,7 @@ dependencies = [ [[package]] name = "iroh-metrics-derive" version = "0.3.1" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#4f7afa784b5efe8ee013145dfd7907abab2dc59d" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#148ae84d9d584cd036d3f6161f2926cfada0c9b7" dependencies = [ "heck", "proc-macro2", @@ -2720,7 +2720,7 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=main#e3d7f3c44399c4c4dafb43331ae0ee98ee9ebb95" +source = "git+https://github.com/n0-computer/n0-error?branch=main#672bfd820aa6474e640c2bcae5495548e38e40c3" dependencies = [ "anyhow", "derive_more 2.0.1", @@ -2731,7 +2731,7 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=main#e3d7f3c44399c4c4dafb43331ae0ee98ee9ebb95" +source = "git+https://github.com/n0-computer/n0-error?branch=main#672bfd820aa6474e640c2bcae5495548e38e40c3" dependencies = [ "darling", "heck", @@ -2927,7 +2927,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -3397,7 +3397,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.6.1", + "socket2 0.5.10", "thiserror 2.0.17", "tokio", "tracing", @@ -3434,9 +3434,9 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.1", + "socket2 0.5.10", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -3735,7 +3735,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -4415,7 +4415,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] From d194524df9e39eee645d53f8c25265ee7322f2b6 Mon Sep 17 00:00:00 2001 From: Frando Date: Fri, 31 Oct 2025 00:20:13 +0100 Subject: [PATCH 44/58] bump n0-error --- Cargo.lock | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b9c4db49f21..232c0ea40c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,12 +120,6 @@ dependencies = [ "windows-sys 0.60.2", ] -[[package]] -name = "anyhow" -version = "1.0.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" - [[package]] name = "anymap2" version = "0.13.0" @@ -1162,7 +1156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -1925,7 +1919,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -2330,7 +2324,7 @@ dependencies = [ [[package]] name = "iroh-metrics" version = "0.36.2" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#148ae84d9d584cd036d3f6161f2926cfada0c9b7" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#10c8ea376f2377e1bcabf4b6d8b9163d5d6350db" dependencies = [ "http-body-util", "hyper", @@ -2349,7 +2343,7 @@ dependencies = [ [[package]] name = "iroh-metrics-derive" version = "0.3.1" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#148ae84d9d584cd036d3f6161f2926cfada0c9b7" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#10c8ea376f2377e1bcabf4b6d8b9163d5d6350db" dependencies = [ "heck", "proc-macro2", @@ -2720,9 +2714,8 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=main#a00ff9bdf550f22d64a429a8b62d7bb9d90a861a" +source = "git+https://github.com/n0-computer/n0-error?branch=main#1c518f29bc8719665041cfe727d8e261567e7a77" dependencies = [ - "anyhow", "derive_more 2.0.1", "n0-error-macros", "spez", @@ -2731,7 +2724,7 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=main#a00ff9bdf550f22d64a429a8b62d7bb9d90a861a" +source = "git+https://github.com/n0-computer/n0-error?branch=main#1c518f29bc8719665041cfe727d8e261567e7a77" dependencies = [ "darling", "heck", @@ -2927,7 +2920,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -3397,7 +3390,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.6.1", + "socket2 0.5.10", "thiserror 2.0.17", "tokio", "tracing", @@ -3434,9 +3427,9 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.1", + "socket2 0.5.10", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -3735,7 +3728,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -4415,7 +4408,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -5201,7 +5194,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.48.0", ] [[package]] From 304525b8c9fd4e0c6378db234685a7f8d8d29a94 Mon Sep 17 00:00:00 2001 From: Frando Date: Fri, 31 Oct 2025 00:44:58 +0100 Subject: [PATCH 45/58] fixup --- Cargo.lock | 172 +++++++++++++++++++++++------------------------------ 1 file changed, 76 insertions(+), 96 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 232c0ea40c1..6ac68176b80 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,9 +42,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -368,9 +368,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64-url" -version = "3.0.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38e2b6c78c06f7288d5e3c3d683bde35a79531127c83b087e5d0d77c974b4b28" +checksum = "f5b428e9fb429c6fda7316e9b006f993e6b4c33005e4659339fb5214479dddec" dependencies = [ "base64", ] @@ -551,9 +551,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.50" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2cfd7bf8a6017ddaa4e32ffe7403d547790db06bd171c1c53926faab501623" +checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5" dependencies = [ "clap_builder", "clap_derive", @@ -561,9 +561,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.50" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a4c05b9e80c5ccd3a7ef080ad7b6ba7d6fc00a985b8b157197075677c82c7a0" +checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a" dependencies = [ "anstream", "anstyle", @@ -1156,7 +1156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1919,7 +1919,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.1", "tokio", "tower-service", "tracing", @@ -1951,9 +1951,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -1964,9 +1964,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -1977,11 +1977,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -1992,42 +1991,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -2095,9 +2090,9 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.18.1" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e0ddd45fe8e09ee1a607920b12271f8a5528a41ecaf6e1d1440d6493315b6b" +checksum = "ade6dfcba0dfb62ad59e59e7241ec8912af34fd29e0e743e3db992bd278e8b65" dependencies = [ "console", "portable-atomic", @@ -2514,9 +2509,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "js-sys" -version = "0.3.81" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ "once_cell", "wasm-bindgen", @@ -2558,9 +2553,9 @@ checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "litrs" @@ -2920,7 +2915,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3277,9 +3272,9 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -3390,7 +3385,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.5.10", + "socket2 0.6.1", "thiserror 2.0.17", "tokio", "tracing", @@ -3427,9 +3422,9 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.1", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -3728,7 +3723,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3841,9 +3836,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.7" +version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ "ring", "rustls-pki-types", @@ -4408,7 +4403,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4496,9 +4491,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -4882,9 +4877,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-width" @@ -5012,9 +5007,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ "cfg-if", "once_cell", @@ -5023,25 +5018,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - [[package]] name = "wasm-bindgen-futures" -version = "0.4.54" +version = "0.4.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" dependencies = [ "cfg-if", "js-sys", @@ -5052,9 +5033,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5062,31 +5043,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-bindgen-test" -version = "0.3.54" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e381134e148c1062f965a42ed1f5ee933eef2927c3f70d1812158f711d39865" +checksum = "bfc379bfb624eb59050b509c13e77b4eb53150c350db69628141abce842f2373" dependencies = [ "js-sys", "minicov", @@ -5097,9 +5078,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.54" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b673bca3298fe582aeef8352330ecbad91849f85090805582400850f8270a2e8" +checksum = "085b2df989e1e6f9620c1311df6c996e83fe16f57792b272ce1e024ac16a90f1" dependencies = [ "proc-macro2", "quote", @@ -5121,9 +5102,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.81" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" dependencies = [ "js-sys", "wasm-bindgen", @@ -5194,7 +5175,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] @@ -5741,9 +5722,9 @@ dependencies = [ [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "ws_stream_wasm" @@ -5784,9 +5765,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.27" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" [[package]] name = "xmltree" @@ -5814,11 +5795,10 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -5826,9 +5806,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", @@ -5905,9 +5885,9 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -5916,9 +5896,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -5927,9 +5907,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", From a1dbd6cafd0dc132452ad98c64073962a03bbfa8 Mon Sep 17 00:00:00 2001 From: Frando Date: Fri, 31 Oct 2025 00:49:25 +0100 Subject: [PATCH 46/58] bump n0-error --- Cargo.lock | 68 +++++++++++------------------------------------------- 1 file changed, 13 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ac68176b80..90cd6f05ff4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -859,41 +859,6 @@ dependencies = [ "syn", ] -[[package]] -name = "darling" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" -dependencies = [ - "darling_core", - "quote", - "syn", -] - [[package]] name = "dashmap" version = "6.1.0" @@ -1156,7 +1121,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -1919,7 +1884,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -2030,12 +1995,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "idna" version = "1.1.0" @@ -2319,7 +2278,7 @@ dependencies = [ [[package]] name = "iroh-metrics" version = "0.36.2" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#10c8ea376f2377e1bcabf4b6d8b9163d5d6350db" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#fe4937507fc144085fd53862219a1ddfaf5bde89" dependencies = [ "http-body-util", "hyper", @@ -2338,7 +2297,7 @@ dependencies = [ [[package]] name = "iroh-metrics-derive" version = "0.3.1" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#10c8ea376f2377e1bcabf4b6d8b9163d5d6350db" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#fe4937507fc144085fd53862219a1ddfaf5bde89" dependencies = [ "heck", "proc-macro2", @@ -2709,7 +2668,7 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=main#1c518f29bc8719665041cfe727d8e261567e7a77" +source = "git+https://github.com/n0-computer/n0-error?branch=main#54dea84b75d577eedc0b83ddbd0bec7ca62f0c9e" dependencies = [ "derive_more 2.0.1", "n0-error-macros", @@ -2719,9 +2678,8 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=main#1c518f29bc8719665041cfe727d8e261567e7a77" +source = "git+https://github.com/n0-computer/n0-error?branch=main#54dea84b75d577eedc0b83ddbd0bec7ca62f0c9e" dependencies = [ - "darling", "heck", "proc-macro2", "quote", @@ -2915,7 +2873,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -3385,7 +3343,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.6.1", + "socket2 0.5.10", "thiserror 2.0.17", "tokio", "tracing", @@ -3422,9 +3380,9 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.1", + "socket2 0.5.10", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -3723,7 +3681,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -4403,7 +4361,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -5175,7 +5133,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.48.0", ] [[package]] From 69ae70e7f93f683587ccbe297a7c1f5259af326c Mon Sep 17 00:00:00 2001 From: Frando Date: Fri, 31 Oct 2025 01:17:43 +0100 Subject: [PATCH 47/58] bump to released n0-error --- Cargo.lock | 26 ++++++++++++++------------ iroh-base/Cargo.toml | 2 +- iroh-dns-server/Cargo.toml | 2 +- iroh-relay/Cargo.toml | 2 +- iroh/Cargo.toml | 2 +- iroh/bench/Cargo.toml | 2 +- 6 files changed, 19 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 90cd6f05ff4..3f55ee77ebf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1121,7 +1121,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1884,7 +1884,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.1", "tokio", "tower-service", "tracing", @@ -2278,7 +2278,7 @@ dependencies = [ [[package]] name = "iroh-metrics" version = "0.36.2" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#fe4937507fc144085fd53862219a1ddfaf5bde89" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#53cf550e13144722de713e9c73cd76c81f68b854" dependencies = [ "http-body-util", "hyper", @@ -2297,7 +2297,7 @@ dependencies = [ [[package]] name = "iroh-metrics-derive" version = "0.3.1" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#fe4937507fc144085fd53862219a1ddfaf5bde89" +source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#53cf550e13144722de713e9c73cd76c81f68b854" dependencies = [ "heck", "proc-macro2", @@ -2668,7 +2668,8 @@ dependencies = [ [[package]] name = "n0-error" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=main#54dea84b75d577eedc0b83ddbd0bec7ca62f0c9e" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a4839a11b62f1fdd75be912ee20634053c734c2240e867ded41c7f50822c549" dependencies = [ "derive_more 2.0.1", "n0-error-macros", @@ -2678,7 +2679,8 @@ dependencies = [ [[package]] name = "n0-error-macros" version = "0.1.0" -source = "git+https://github.com/n0-computer/n0-error?branch=main#54dea84b75d577eedc0b83ddbd0bec7ca62f0c9e" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed2a7e5ca3cb5729d4a162d7bcab5b338bed299a2fee8457568d7e0a747ed89" dependencies = [ "heck", "proc-macro2", @@ -2873,7 +2875,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3343,7 +3345,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.5.10", + "socket2 0.6.1", "thiserror 2.0.17", "tokio", "tracing", @@ -3380,9 +3382,9 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.1", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -3681,7 +3683,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4361,7 +4363,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/iroh-base/Cargo.toml b/iroh-base/Cargo.toml index a409c2eaf47..5dc3d0d7c98 100644 --- a/iroh-base/Cargo.toml +++ b/iroh-base/Cargo.toml @@ -22,7 +22,7 @@ derive_more = { version = "2.0.1", features = ["display"], optional = true } url = { version = "2.5.3", features = ["serde"], optional = true } rand_core = { version = "0.9.3", optional = true } serde = { version = "1", features = ["derive", "rc"] } -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } +n0-error = "0.1.0" zeroize = { version = "1.8.2", optional = true, features = ["derive"] } zeroize_derive = { version = "1.4.2", optional = true } # needed for minimal versions diff --git a/iroh-dns-server/Cargo.toml b/iroh-dns-server/Cargo.toml index cb56212a67e..f630cffa821 100644 --- a/iroh-dns-server/Cargo.toml +++ b/iroh-dns-server/Cargo.toml @@ -39,7 +39,7 @@ rustls = { version = "0.23.33", default-features = false, features = ["ring"] } rustls-pemfile = { version = "2.1" } serde = { version = "1", features = ["derive"] } struct_iterable = "0.1.1" -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } +n0-error = "0.1.0" strum = { version = "0.27", features = ["derive"] } tokio = { version = "1", features = ["full"] } tokio-rustls = { version = "0.26", default-features = false, features = [ diff --git a/iroh-relay/Cargo.toml b/iroh-relay/Cargo.toml index 02bdd62650f..e7e5ad8b794 100644 --- a/iroh-relay/Cargo.toml +++ b/iroh-relay/Cargo.toml @@ -70,7 +70,7 @@ webpki_types = { package = "rustls-pki-types", version = "1.12" } data-encoding = "2.6.0" lru = "0.16" z32 = "1.0.3" -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } +n0-error = "0.1.0" # server feature clap = { version = "4", features = ["derive"], optional = true } diff --git a/iroh/Cargo.toml b/iroh/Cargo.toml index de2fbe3007f..b4be59359da 100644 --- a/iroh/Cargo.toml +++ b/iroh/Cargo.toml @@ -39,7 +39,7 @@ http = "1" iroh-base = { version = "0.94.1", default-features = false, features = ["key", "relay"], path = "../iroh-base" } iroh-relay = { version = "0.94", path = "../iroh-relay", default-features = false } n0-future = "0.3.0" -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } +n0-error = "0.1.0" n0-watcher = "0.4" nested_enum_utils = "0.2.1" netwatch = { version = "0.11" } diff --git a/iroh/bench/Cargo.toml b/iroh/bench/Cargo.toml index 1c44f5e30c7..50bf4122f7e 100644 --- a/iroh/bench/Cargo.toml +++ b/iroh/bench/Cargo.toml @@ -11,7 +11,7 @@ hdrhistogram = { version = "7.2", default-features = false } iroh = { path = ".." } iroh-metrics = "0.36" n0-future = "0.3.0" -n0-error = { git = "https://github.com/n0-computer/n0-error", branch = "main" } +n0-error = "0.1.0" quinn = { package = "iroh-quinn", version = "0.14" } rand = "0.9.2" rcgen = "0.14" From 199899440762a23e43ac391635432aee1da1463d Mon Sep 17 00:00:00 2001 From: Frando Date: Fri, 31 Oct 2025 14:16:42 +0100 Subject: [PATCH 48/58] deps: remove nested_enum_utils --- Cargo.lock | 1 - iroh/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3f55ee77ebf..fcb970ea271 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2144,7 +2144,6 @@ dependencies = [ "n0-error", "n0-future", "n0-watcher", - "nested_enum_utils", "netdev", "netwatch", "parse-size", diff --git a/iroh/Cargo.toml b/iroh/Cargo.toml index b4be59359da..a8895ecfcc7 100644 --- a/iroh/Cargo.toml +++ b/iroh/Cargo.toml @@ -41,7 +41,6 @@ iroh-relay = { version = "0.94", path = "../iroh-relay", default-features = fals n0-future = "0.3.0" n0-error = "0.1.0" n0-watcher = "0.4" -nested_enum_utils = "0.2.1" netwatch = { version = "0.11" } pin-project = "1" pkarr = { version = "5", default-features = false, features = ["relays"] } From 8eef3178b2393cbf13de94bcfcaf8bbac9807c3a Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 1 Nov 2025 12:14:22 +0100 Subject: [PATCH 49/58] refactor: use ensure more --- iroh-base/src/key.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/iroh-base/src/key.rs b/iroh-base/src/key.rs index 69e61f3e9a5..9cb7b01bdd6 100644 --- a/iroh-base/src/key.rs +++ b/iroh-base/src/key.rs @@ -11,7 +11,7 @@ use std::{ use curve25519_dalek::edwards::CompressedEdwardsY; use ed25519_dalek::{SigningKey, VerifyingKey}; -use n0_error::{e, stack_error}; +use n0_error::{ensure, stack_error}; use rand_core::CryptoRng; use serde::{Deserialize, Serialize, de, ser}; @@ -424,16 +424,18 @@ fn decode_base32_hex(s: &str) -> Result<[u8; 32], KeyParsingError> { } else { let input = s.to_ascii_uppercase(); let input = input.as_bytes(); - if data_encoding::BASE32_NOPAD.decode_len(input.len())? != bytes.len() { - return Err(e!(KeyParsingError::DecodeInvalidLength)); - } + ensure!( + data_encoding::BASE32_NOPAD.decode_len(input.len())? == bytes.len(), + KeyParsingError::DecodeInvalidLength + ); data_encoding::BASE32_NOPAD.decode_mut(input, &mut bytes) }; match res { Ok(len) => { - if len != PublicKey::LENGTH { - return Err(e!(KeyParsingError::DecodeInvalidLength)); - } + ensure!( + len == PublicKey::LENGTH, + KeyParsingError::DecodeInvalidLength + ); } Err(partial) => return Err(partial.error.into()), } From 0f78cc8907e45565ab9759f6de04f486b7f67ffb Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 1 Nov 2025 16:58:22 +0100 Subject: [PATCH 50/58] refactor(iroh-dns-server): use concrete erros in utils --- iroh-dns-server/src/store.rs | 17 +++++++++------ iroh-dns-server/src/util.rs | 42 +++++++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/iroh-dns-server/src/store.rs b/iroh-dns-server/src/store.rs index 08d492fdef4..537075598d9 100644 --- a/iroh-dns-server/src/store.rs +++ b/iroh-dns-server/src/store.rs @@ -2,9 +2,12 @@ use std::{collections::BTreeMap, num::NonZeroUsize, path::Path, sync::Arc, time::Duration}; -use hickory_server::proto::rr::{Name, RecordSet, RecordType, RrKey}; +use hickory_server::proto::{ + ProtoError, + rr::{Name, RecordSet, RecordType, RrKey}, +}; use lru::LruCache; -use n0_error::Result; +use n0_error::{Result, StdResultExt}; use pkarr::{Client as PkarrClient, SignedPacket}; use tokio::sync::Mutex; use tracing::{debug, trace, warn}; @@ -234,7 +237,7 @@ impl ZoneCache { record_type: RecordType, ) -> Result>> { let pubkey = PublicKeyBytes::from_signed_packet(signed_packet); - let zone = CachedZone::from_signed_packet(signed_packet)?; + let zone = CachedZone::from_signed_packet(signed_packet).anyerr()?; let res = zone.resolve(name, record_type); self.dht_cache.insert(pubkey, zone, DHT_CACHE_TTL); Ok(res) @@ -251,8 +254,10 @@ impl ZoneCache { trace!("insert skip: cached is newer"); Ok(()) } else { - self.cache - .put(pubkey, CachedZone::from_signed_packet(signed_packet)?); + self.cache.put( + pubkey, + CachedZone::from_signed_packet(signed_packet).anyerr()?, + ); trace!("inserted into cache"); Ok(()) } @@ -271,7 +276,7 @@ struct CachedZone { } impl CachedZone { - fn from_signed_packet(signed_packet: &SignedPacket) -> Result { + fn from_signed_packet(signed_packet: &SignedPacket) -> Result { let (_label, records) = signed_packet_to_hickory_records_without_origin(signed_packet, |_| true)?; Ok(Self { diff --git a/iroh-dns-server/src/util.rs b/iroh-dns-server/src/util.rs index 060498527c2..6419b6adc5a 100644 --- a/iroh-dns-server/src/util.rs +++ b/iroh-dns-server/src/util.rs @@ -6,6 +6,7 @@ use std::{ }; use hickory_server::proto::{ + ProtoError, op::Message, rr::{ Name, Record, RecordSet, RecordType, RrKey, @@ -13,7 +14,7 @@ use hickory_server::proto::{ }, serialize::binary::BinDecodable, }; -use n0_error::{AnyError, Result, StdResultExt}; +use n0_error::{AnyError, StdResultExt, e, stack_error}; use pkarr::SignedPacket; #[derive( @@ -21,14 +22,26 @@ use pkarr::SignedPacket; )] pub struct PublicKeyBytes([u8; 32]); +#[stack_error(derive, add_meta, from_sources)] +pub enum InvalidPublicKeyBytes { + #[error(transparent)] + Encoding { + #[error(std_err)] + source: z32::Z32Error, + }, + #[error("invalid length, must be 32 bytes")] + InvalidLength, +} + impl PublicKeyBytes { pub fn new(bytes: [u8; 32]) -> Self { Self(bytes) } - pub fn from_z32(s: &str) -> Result { - let bytes = z32::decode(s.as_bytes()).anyerr()?; - let bytes = TryInto::<[u8; 32]>::try_into(&bytes[..]).std_context("invalid length")?; + pub fn from_z32(s: &str) -> Result { + let bytes = z32::decode(s.as_bytes())?; + let bytes = TryInto::<[u8; 32]>::try_into(&bytes[..]) + .map_err(|_| e!(InvalidPublicKeyBytes::InvalidLength))?; Ok(Self(bytes)) } @@ -75,7 +88,8 @@ impl TryFrom for pkarr::PublicKey { } impl FromStr for PublicKeyBytes { - type Err = AnyError; + type Err = InvalidPublicKeyBytes; + fn from_str(s: &str) -> Result { Self::from_z32(s) } @@ -87,17 +101,19 @@ impl AsRef<[u8; 32]> for PublicKeyBytes { } } -pub fn signed_packet_to_hickory_message(signed_packet: &SignedPacket) -> Result { +pub fn signed_packet_to_hickory_message( + signed_packet: &SignedPacket, +) -> Result { let encoded = signed_packet.encoded_packet(); - let message = Message::from_bytes(&encoded).anyerr()?; + let message = Message::from_bytes(&encoded)?; Ok(message) } pub fn signed_packet_to_hickory_records_without_origin( signed_packet: &SignedPacket, filter: impl Fn(&Record) -> bool, -) -> Result<(Label, BTreeMap>)> { - let common_zone = Label::from_utf8(&signed_packet.public_key().to_z32()).anyerr()?; +) -> Result<(Label, BTreeMap>), ProtoError> { + let common_zone = Label::from_utf8(&signed_packet.public_key().to_z32())?; let mut message = signed_packet_to_hickory_message(signed_packet)?; let answers = message.take_answers(); let mut output: BTreeMap> = BTreeMap::new(); @@ -111,7 +127,7 @@ pub fn signed_packet_to_hickory_records_without_origin( if name.num_labels() < 1 { continue; } - let zone = name.iter().next_back().unwrap().into_label().anyerr()?; + let zone = name.iter().next_back().unwrap().into_label()?; if zone != common_zone { continue; } @@ -120,7 +136,7 @@ pub fn signed_packet_to_hickory_records_without_origin( } let name_without_zone = - Name::from_labels(name.iter().take(name.num_labels() as usize - 1)).anyerr()?; + Name::from_labels(name.iter().take(name.num_labels() as usize - 1))?; record.set_name(name_without_zone); let rrkey = RrKey::new(record.name().into(), record.record_type()); @@ -144,8 +160,8 @@ pub fn record_set_append_origin( input: &RecordSet, origin: &Name, serial: u32, -) -> Result { - let new_name = input.name().clone().append_name(origin).anyerr()?; +) -> Result { + let new_name = input.name().clone().append_name(origin)?; let mut output = RecordSet::new(new_name.clone(), input.record_type(), serial); // TODO: less clones for record in input.records_without_rrsigs() { From 1f12fd38cc4b56dbe5c18725cfa9701c307d3c86 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 3 Nov 2025 09:44:45 +0100 Subject: [PATCH 51/58] fix: use imports more --- iroh-dns-server/src/store/signed_packets.rs | 3 ++- iroh-relay/src/client.rs | 9 ++++---- iroh-relay/src/client/conn.rs | 6 +++--- iroh-relay/src/endpoint_info.rs | 6 +++--- iroh-relay/src/protos/handshake.rs | 6 +++--- iroh-relay/src/protos/relay.rs | 24 ++++++++++----------- iroh-relay/src/server/streams.rs | 8 +++---- iroh/src/key.rs | 4 ++-- 8 files changed, 34 insertions(+), 32 deletions(-) diff --git a/iroh-dns-server/src/store/signed_packets.rs b/iroh-dns-server/src/store/signed_packets.rs index acfb1221c62..bac21016f30 100644 --- a/iroh-dns-server/src/store/signed_packets.rs +++ b/iroh-dns-server/src/store/signed_packets.rs @@ -162,7 +162,8 @@ impl Actor { tables.update_time.remove(&existing.timestamp().to_bytes(), key.as_bytes()).anyerr()?; true } - } _ => { + }, + _ => { false } }; diff --git a/iroh-relay/src/client.rs b/iroh-relay/src/client.rs index d67458cdcf6..14482e38098 100644 --- a/iroh-relay/src/client.rs +++ b/iroh-relay/src/client.rs @@ -278,11 +278,12 @@ impl ClientBuilder { } let (conn, response) = builder.connect_on(stream).await?; - if response.status() != hyper::StatusCode::SWITCHING_PROTOCOLS { - return Err(e!(ConnectError::UnexpectedUpgradeStatus { + n0_error::ensure!( + response.status() == hyper::StatusCode::SWITCHING_PROTOCOLS, + ConnectError::UnexpectedUpgradeStatus { code: response.status() - })); - } + } + ); let conn = Conn::new(conn, self.key_cache.clone(), &self.secret_key).await?; diff --git a/iroh-relay/src/client/conn.rs b/iroh-relay/src/client/conn.rs index c02aea8a0c5..a361f8ac967 100644 --- a/iroh-relay/src/client/conn.rs +++ b/iroh-relay/src/client/conn.rs @@ -8,7 +8,7 @@ use std::{ }; use iroh_base::SecretKey; -use n0_error::stack_error; +use n0_error::{ensure, stack_error}; use n0_future::{Sink, Stream}; use tracing::debug; @@ -135,12 +135,12 @@ impl Sink for Conn { fn start_send(mut self: Pin<&mut Self>, frame: ClientToRelayMsg) -> Result<(), Self::Error> { let size = frame.encoded_len(); - n0_error::ensure!( + ensure!( size <= MAX_PACKET_SIZE, SendError::ExceedsMaxPacketSize { size } ); if let ClientToRelayMsg::Datagrams { datagrams, .. } = &frame { - n0_error::ensure!(!datagrams.contents.is_empty(), SendError::EmptyPacket); + ensure!(!datagrams.contents.is_empty(), SendError::EmptyPacket); } Pin::new(&mut self.conn) diff --git a/iroh-relay/src/endpoint_info.rs b/iroh-relay/src/endpoint_info.rs index aaf7b4c5e83..5cd582b5b73 100644 --- a/iroh-relay/src/endpoint_info.rs +++ b/iroh-relay/src/endpoint_info.rs @@ -41,7 +41,7 @@ use std::{ }; use iroh_base::{EndpointAddr, EndpointId, KeyParsingError, RelayUrl, SecretKey, TransportAddr}; -use n0_error::{e, stack_error}; +use n0_error::{e, ensure, stack_error}; use url::Url; /// The DNS name for the iroh TXT record. @@ -251,7 +251,7 @@ impl TryFrom for UserData { type Error = MaxLengthExceededError; fn try_from(value: String) -> Result { - n0_error::ensure!(value.len() <= Self::MAX_LENGTH, MaxLengthExceededError); + ensure!(value.len() <= Self::MAX_LENGTH, MaxLengthExceededError); Ok(Self(value)) } } @@ -260,7 +260,7 @@ impl FromStr for UserData { type Err = MaxLengthExceededError; fn from_str(s: &str) -> std::result::Result { - n0_error::ensure!(s.len() <= Self::MAX_LENGTH, MaxLengthExceededError); + ensure!(s.len() <= Self::MAX_LENGTH, MaxLengthExceededError); Ok(Self(s.to_string())) } } diff --git a/iroh-relay/src/protos/handshake.rs b/iroh-relay/src/protos/handshake.rs index 2f1123550df..e3be23081ee 100644 --- a/iroh-relay/src/protos/handshake.rs +++ b/iroh-relay/src/protos/handshake.rs @@ -31,7 +31,7 @@ use http::HeaderValue; #[cfg(feature = "server")] use iroh_base::Signature; use iroh_base::{PublicKey, SecretKey}; -use n0_error::{e, stack_error}; +use n0_error::{e, ensure, stack_error}; use n0_future::{SinkExt, TryStreamExt}; #[cfg(feature = "server")] use rand::CryptoRng; @@ -302,7 +302,7 @@ impl KeyMaterialClientAuth { // there must be something wrong with the client's secret key or signature. let (message, suffix) = key_material.split_at(16); let suffix: [u8; 16] = suffix.try_into().expect("hardcoded length"); - n0_error::ensure!( + ensure!( suffix == self.key_material_suffix, VerificationError::MismatchedSuffix { expected: self.key_material_suffix, @@ -508,7 +508,7 @@ async fn read_frame( let frame_type = FrameType::from_bytes(&mut payload)?; trace!(?frame_type, "Reading frame"); - n0_error::ensure!( + ensure!( expected_types.contains(&frame_type), Error::UnexpectedFrameType { frame_type, diff --git a/iroh-relay/src/protos/relay.rs b/iroh-relay/src/protos/relay.rs index cf7c5837e94..991f4472f54 100644 --- a/iroh-relay/src/protos/relay.rs +++ b/iroh-relay/src/protos/relay.rs @@ -11,7 +11,7 @@ use std::num::NonZeroU16; use bytes::{Buf, BufMut, Bytes, BytesMut}; use iroh_base::{EndpointId, KeyParsingError}; -use n0_error::{e, stack_error}; +use n0_error::{e, ensure, stack_error}; use n0_future::time::Duration; use super::common::{FrameType, FrameTypeError}; @@ -220,9 +220,9 @@ impl Datagrams { fn from_bytes(mut bytes: Bytes, is_batch: bool) -> Result { if is_batch { // 1 bytes ECN, 2 bytes segment size - n0_error::ensure!(bytes.len() >= 3, Error::InvalidFrame); + ensure!(bytes.len() >= 3, Error::InvalidFrame); } else { - n0_error::ensure!(bytes.len() >= 1, Error::InvalidFrame); + ensure!(bytes.len() >= 1, Error::InvalidFrame); } let ecn_byte = bytes.get_u8(); @@ -329,14 +329,14 @@ impl RelayToClientMsg { pub(crate) fn from_bytes(mut content: Bytes, cache: &KeyCache) -> Result { let frame_type = FrameType::from_bytes(&mut content)?; let frame_len = content.len(); - n0_error::ensure!( + ensure!( frame_len <= MAX_PACKET_SIZE, Error::FrameTooLarge { frame_len } ); let res = match frame_type { FrameType::RelayToClientDatagram | FrameType::RelayToClientDatagramBatch => { - n0_error::ensure!(content.len() >= EndpointId::LENGTH, Error::InvalidFrame); + ensure!(content.len() >= EndpointId::LENGTH, Error::InvalidFrame); let remote_endpoint_id = cache.key_from_slice(&content[..EndpointId::LENGTH])?; let datagrams = Datagrams::from_bytes( @@ -349,18 +349,18 @@ impl RelayToClientMsg { } } FrameType::EndpointGone => { - n0_error::ensure!(content.len() == EndpointId::LENGTH, Error::InvalidFrame); + ensure!(content.len() == EndpointId::LENGTH, Error::InvalidFrame); let endpoint_id = cache.key_from_slice(content.as_ref())?; Self::EndpointGone(endpoint_id) } FrameType::Ping => { - n0_error::ensure!(content.len() == 8, Error::InvalidFrame); + ensure!(content.len() == 8, Error::InvalidFrame); let mut data = [0u8; 8]; data.copy_from_slice(&content[..8]); Self::Ping(data) } FrameType::Pong => { - n0_error::ensure!(content.len() == 8, Error::InvalidFrame); + ensure!(content.len() == 8, Error::InvalidFrame); let mut data = [0u8; 8]; data.copy_from_slice(&content[..8]); Self::Pong(data) @@ -370,7 +370,7 @@ impl RelayToClientMsg { Self::Health { problem } } FrameType::Restarting => { - n0_error::ensure!(content.len() == 4 + 4, Error::InvalidFrame); + ensure!(content.len() == 4 + 4, Error::InvalidFrame); let reconnect_in = u32::from_be_bytes( content[..4] .try_into() @@ -457,7 +457,7 @@ impl ClientToRelayMsg { pub(crate) fn from_bytes(mut content: Bytes, cache: &KeyCache) -> Result { let frame_type = FrameType::from_bytes(&mut content)?; let frame_len = content.len(); - n0_error::ensure!( + ensure!( frame_len <= MAX_PACKET_SIZE, Error::FrameTooLarge { frame_len } ); @@ -475,13 +475,13 @@ impl ClientToRelayMsg { } } FrameType::Ping => { - n0_error::ensure!(content.len() == 8, Error::InvalidFrame); + ensure!(content.len() == 8, Error::InvalidFrame); let mut data = [0u8; 8]; data.copy_from_slice(&content[..8]); Self::Ping(data) } FrameType::Pong => { - n0_error::ensure!(content.len() == 8, Error::InvalidFrame); + ensure!(content.len() == 8, Error::InvalidFrame); let mut data = [0u8; 8]; data.copy_from_slice(&content[..8]); Self::Pong(data) diff --git a/iroh-relay/src/server/streams.rs b/iroh-relay/src/server/streams.rs index 9745e7c2f64..168f6ae0b80 100644 --- a/iroh-relay/src/server/streams.rs +++ b/iroh-relay/src/server/streams.rs @@ -6,7 +6,7 @@ use std::{ task::{Context, Poll}, }; -use n0_error::stack_error; +use n0_error::{ensure, stack_error}; use n0_future::{FutureExt, Sink, Stream, ready, time}; use tokio::io::{AsyncRead, AsyncWrite}; use tracing::instrument; @@ -98,12 +98,12 @@ impl Sink for RelayedStream { fn start_send(mut self: Pin<&mut Self>, item: RelayToClientMsg) -> Result<(), Self::Error> { let size = item.encoded_len(); - n0_error::ensure!( + ensure!( size <= MAX_PACKET_SIZE, SendError::ExceedsMaxPacketSize { size } ); if let RelayToClientMsg::Datagrams { datagrams, .. } = &item { - n0_error::ensure!(!datagrams.contents.is_empty(), SendError::EmptyPacket); + ensure!(!datagrams.contents.is_empty(), SendError::EmptyPacket); } Pin::new(&mut self.inner) @@ -302,7 +302,7 @@ impl Bucket { ) -> Result { // milliseconds is the tokio timer resolution let refill = bytes_per_second.saturating_mul(refill_period.as_millis() as i64) / 1000; - n0_error::ensure!( + ensure!( max > 0 && bytes_per_second > 0 && refill_period.as_millis() as u32 > 0 && refill > 0, InvalidBucketConfig { max, diff --git a/iroh/src/key.rs b/iroh/src/key.rs index 43f58396909..c6b9f6ee483 100644 --- a/iroh/src/key.rs +++ b/iroh/src/key.rs @@ -4,7 +4,7 @@ use std::fmt::Debug; use aead::{AeadCore, AeadInOut, Buffer}; use iroh_base::{PublicKey, SecretKey}; -use n0_error::{e, stack_error}; +use n0_error::{e, ensure, stack_error}; pub(crate) const NONCE_LEN: usize = 24; @@ -63,7 +63,7 @@ impl SharedSecret { /// Opens the ciphertext, which must have been created using `Self::seal`, and places the clear text into the provided buffer. pub fn open(&self, buffer: &mut dyn Buffer) -> Result<(), DecryptionError> { - n0_error::ensure!(buffer.len() >= NONCE_LEN, DecryptionError::InvalidNonce); + ensure!(buffer.len() >= NONCE_LEN, DecryptionError::InvalidNonce); let offset = buffer.len() - NONCE_LEN; let nonce: [u8; NONCE_LEN] = buffer.as_ref()[offset..] From ad6e742a26fe2051d9a98ae6627821996ae58e0e Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 3 Nov 2025 10:54:49 +0100 Subject: [PATCH 52/58] refactor: simplify line in tests --- iroh/src/endpoint.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 52e359e5db6..b4385490cdf 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -2968,14 +2968,7 @@ mod tests { .await?; let server_addr = server.addr(); let server_task = tokio::task::spawn(async move { - let conn = server - .accept() - .await - .anyerr()? - .accept() - .anyerr()? - .await - .anyerr()?; + let conn = server.accept().await.anyerr()?.await.anyerr()?; let mut uni = conn.accept_uni().await.anyerr()?; uni.read_to_end(10).await.anyerr()?; drop(conn); From 9667f8b040364146f24de91cd91df5f8d1907f8e Mon Sep 17 00:00:00 2001 From: Franz Heinzmann Date: Mon, 3 Nov 2025 11:01:51 +0100 Subject: [PATCH 53/58] refactor(iroh-dns-server): move block from `select!` to fn (#3597) ## Description `cargo fmt` can't handle code inside `tokio::select!` and the big match statement had numerous formatting issues, so I moved it into a function. ## Breaking Changes ## Notes & open questions ## Change checklist - [ ] Self-review. - [ ] Documentation updates following the [style guide](https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text), if relevant. - [ ] Tests if relevant. - [ ] All breaking changes documented. - [ ] List all breaking changes in the above "Breaking Changes" section. - [ ] Open an issue or PR on any number0 repos that are affected by this breaking change. Give guidance on how the updates should be handled or do the actual updates themselves. The major ones are: - [ ] [`quic-rpc`](https://github.com/n0-computer/quic-rpc) - [ ] [`iroh-gossip`](https://github.com/n0-computer/iroh-gossip) - [ ] [`iroh-blobs`](https://github.com/n0-computer/iroh-blobs) - [ ] [`dumbpipe`](https://github.com/n0-computer/dumbpipe) - [ ] [`sendme`](https://github.com/n0-computer/sendme) --- iroh-dns-server/src/store/signed_packets.rs | 188 +++++++++++--------- 1 file changed, 106 insertions(+), 82 deletions(-) diff --git a/iroh-dns-server/src/store/signed_packets.rs b/iroh-dns-server/src/store/signed_packets.rs index bac21016f30..79866942ce0 100644 --- a/iroh-dns-server/src/store/signed_packets.rs +++ b/iroh-dns-server/src/store/signed_packets.rs @@ -6,7 +6,7 @@ use std::{ time::{Duration, SystemTime}, }; -use n0_error::{Result, StdResultExt, anyerr}; +use n0_error::{Result, StackResultExt, StdResultExt, anyerr}; use pkarr::{SignedPacket, Timestamp}; use redb::{ Database, MultimapTableDefinition, ReadableDatabase, ReadableTable, TableDefinition, @@ -111,7 +111,6 @@ impl Actor { } async fn run0(&mut self) -> Result<()> { - let expiry_us = self.options.eviction.as_micros() as u64; while let Some(msg) = self.recv.recv().await { // if we get a snapshot message here we don't need to do a write transaction let msg = if let Message::Snapshot { res } = msg { @@ -135,86 +134,7 @@ impl Actor { return Ok(()); } _ = &mut timeout => break, - Some(msg) = self.recv.recv() => { - match msg { - Message::Get { key, res } => { - match get_packet(&tables.signed_packets, &key) { - Ok(packet) => { - trace!("get {key}: {}", packet.is_some()); - res.send(packet).ok(); - }, - Err(err) => { - warn!("get {key} failed: {err:#}"); - return Err(err).std_context(format!("get packet for {key} failed")) - } - } - } - Message::Upsert { packet, res } => { - let key = PublicKeyBytes::from_signed_packet(&packet); - trace!("upsert {}", key); - let replaced = match get_packet(&tables.signed_packets, &key)? { - Some(existing) => { - if existing.more_recent_than(&packet) { - res.send(false).ok(); - continue; - } else { - // remove the old packet from the update time index - tables.update_time.remove(&existing.timestamp().to_bytes(), key.as_bytes()).anyerr()?; - true - } - }, - _ => { - false - } - }; - let value = packet.serialize(); - tables.signed_packets - .insert(key.as_bytes(), &value[..]).anyerr()?; - tables.update_time - .insert(&packet.timestamp().to_bytes(), key.as_bytes()).anyerr()?; - if replaced { - self.metrics.store_packets_updated.inc(); - } else { - self.metrics.store_packets_inserted.inc(); - } - res.send(true).ok(); - } - Message::Remove { key, res } => { - trace!("remove {}", key); - let updated = match tables.signed_packets.remove(key.as_bytes()).anyerr()? { Some(row) => { - let packet = SignedPacket::deserialize(row.value()).anyerr()?; - tables.update_time.remove(&packet.timestamp().to_bytes(), key.as_bytes()).anyerr()?; - self.metrics.store_packets_removed.inc(); - true - } _ => { - false - }}; - res.send(updated).ok(); - } - Message::Snapshot { res } => { - trace!("snapshot"); - res.send(Snapshot::new(&self.db)?).ok(); - } - Message::CheckExpired { key, time } => { - trace!("check expired {} at {}", key, fmt_time(time)); - match get_packet(&tables.signed_packets, &key)? { Some(packet) => { - let expired = Timestamp::now() - expiry_us; - if packet.timestamp() < expired { - tables.update_time.remove(&time.to_bytes(), key.as_bytes()).anyerr()?; - let _ = tables.signed_packets.remove(key.as_bytes()).anyerr()?; - self.metrics.store_packets_expired.inc(); - debug!("removed expired packet {key}"); - } else { - debug!("packet {key} is no longer expired, removing obsolete expiry entry"); - tables.update_time.remove(&time.to_bytes(), key.as_bytes()).anyerr()?; - } - } _ => { - debug!("expired packet {key} not found, remove from expiry table"); - tables.update_time.remove(&time.to_bytes(), key.as_bytes()).anyerr()?; - }} - } - } - } + Some(msg) = self.recv.recv() => self.handle_message(msg, &mut tables)?, } } drop(tables); @@ -222,6 +142,110 @@ impl Actor { } Ok(()) } + + fn handle_message(&self, msg: Message, tables: &mut Tables) -> Result<()> { + match msg { + Message::Get { key, res } => match get_packet(&tables.signed_packets, &key) { + Ok(packet) => { + trace!("get {key}: {}", packet.is_some()); + res.send(packet).ok(); + } + Err(err) => { + warn!("get {key} failed: {err:#}"); + return Err(err).context(format!("get packet for {key} failed")); + } + }, + Message::Upsert { packet, res } => { + let key = PublicKeyBytes::from_signed_packet(&packet); + trace!("upsert {}", key); + let replaced = match get_packet(&tables.signed_packets, &key)? { + Some(existing) => { + if existing.more_recent_than(&packet) { + res.send(false).ok(); + return Ok(()); + } else { + // remove the old packet from the update time index + tables + .update_time + .remove(&existing.timestamp().to_bytes(), key.as_bytes()) + .anyerr()?; + true + } + } + _ => false, + }; + let value = packet.serialize(); + tables + .signed_packets + .insert(key.as_bytes(), &value[..]) + .anyerr()?; + tables + .update_time + .insert(&packet.timestamp().to_bytes(), key.as_bytes()) + .anyerr()?; + if replaced { + self.metrics.store_packets_updated.inc(); + } else { + self.metrics.store_packets_inserted.inc(); + } + res.send(true).ok(); + } + Message::Remove { key, res } => { + trace!("remove {}", key); + let updated = match tables.signed_packets.remove(key.as_bytes()).anyerr()? { + Some(row) => { + let packet = SignedPacket::deserialize(row.value()).anyerr()?; + tables + .update_time + .remove(&packet.timestamp().to_bytes(), key.as_bytes()) + .anyerr()?; + self.metrics.store_packets_removed.inc(); + true + } + _ => false, + }; + res.send(updated).ok(); + } + Message::Snapshot { res } => { + trace!("snapshot"); + res.send(Snapshot::new(&self.db)?).ok(); + } + Message::CheckExpired { key, time } => { + trace!("check expired {} at {}", key, fmt_time(time)); + match get_packet(&tables.signed_packets, &key)? { + Some(packet) => { + let expiry_us = self.options.eviction.as_micros() as u64; + let expired = Timestamp::now() - expiry_us; + if packet.timestamp() < expired { + tables + .update_time + .remove(&time.to_bytes(), key.as_bytes()) + .anyerr()?; + let _ = tables.signed_packets.remove(key.as_bytes()).anyerr()?; + self.metrics.store_packets_expired.inc(); + debug!("removed expired packet {key}"); + } else { + debug!( + "packet {key} is no longer expired, removing obsolete expiry entry" + ); + tables + .update_time + .remove(&time.to_bytes(), key.as_bytes()) + .anyerr()?; + } + } + None => { + debug!("expired packet {key} not found, remove from expiry table"); + tables + .update_time + .remove(&time.to_bytes(), key.as_bytes()) + .anyerr()?; + } + } + } + } + Ok(()) + } } fn fmt_time(t: Timestamp) -> String { From 24aeb244c7b75324dfa2c757d01d798c90782178 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 3 Nov 2025 16:31:47 +0100 Subject: [PATCH 54/58] bump n0-watcher, iroh-metrics, and add git dep for portmapper and netwatch --- Cargo.lock | 63 +++++++++----------------------------- Cargo.toml | 3 +- iroh-dns-server/Cargo.toml | 2 +- iroh-relay/Cargo.toml | 2 +- iroh/Cargo.toml | 4 +-- iroh/bench/Cargo.toml | 2 +- 6 files changed, 21 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fcb970ea271..9f6888ac325 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2276,8 +2276,9 @@ dependencies = [ [[package]] name = "iroh-metrics" -version = "0.36.2" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#53cf550e13144722de713e9c73cd76c81f68b854" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79e3381da7c93c12d353230c74bba26131d1c8bf3a4d8af0fec041546454582e" dependencies = [ "http-body-util", "hyper", @@ -2295,8 +2296,9 @@ dependencies = [ [[package]] name = "iroh-metrics-derive" -version = "0.3.1" -source = "git+https://github.com/n0-computer/iroh-metrics?branch=Frando%2Fn0-error#53cf550e13144722de713e9c73cd76c81f68b854" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e12bd0763fd16062f5cc5e8db15dd52d26e75a8af4c7fb57ccee3589b344b8" dependencies = [ "heck", "proc-macro2", @@ -2710,25 +2712,13 @@ dependencies = [ [[package]] name = "n0-watcher" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34c65e127e06e5a2781b28df6a33ea474a7bddc0ac0cfea888bd20c79a1b6516" +checksum = "38acf13c1ddafc60eb7316d52213467f8ccb70b6f02b65e7d97f7799b1f50be4" dependencies = [ "derive_more 2.0.1", + "n0-error", "n0-future", - "snafu", -] - -[[package]] -name = "nested_enum_utils" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d5475271bdd36a4a2769eac1ef88df0f99428ea43e52dfd8b0ee5cb674695f" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", ] [[package]] @@ -2799,8 +2789,7 @@ dependencies = [ [[package]] name = "netwatch" version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98d7ec7abdbfe67ee70af3f2002326491178419caea22254b9070e6ff0c83491" +source = "git+https://github.com/n0-computer/net-tools?branch=Frando%2Fn0-snafu#29ed0df8ea644358b64d30ba37ddefe97628df26" dependencies = [ "atomic-waker", "bytes", @@ -2809,9 +2798,9 @@ dependencies = [ "iroh-quinn-udp", "js-sys", "libc", + "n0-error", "n0-future", "n0-watcher", - "nested_enum_utils", "netdev", "netlink-packet-core", "netlink-packet-route", @@ -2819,7 +2808,6 @@ dependencies = [ "netlink-sys", "pin-project-lite", "serde", - "snafu", "socket2 0.6.1", "time", "tokio", @@ -3176,8 +3164,7 @@ checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "portmapper" version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d73aa9bd141e0ff6060fea89a5437883f3b9ceea1cda71c790b90e17d072a3b3" +source = "git+https://github.com/n0-computer/net-tools?branch=Frando%2Fn0-snafu#29ed0df8ea644358b64d30ba37ddefe97628df26" dependencies = [ "base64", "bytes", @@ -3188,13 +3175,12 @@ dependencies = [ "igd-next", "iroh-metrics", "libc", - "nested_enum_utils", + "n0-error", "netwatch", "num_enum", "rand 0.9.2", "serde", "smallvec", - "snafu", "socket2 0.6.1", "time", "tokio", @@ -4125,27 +4111,6 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fad6c857cbab2627dcf01ec85a623ca4e7dcb5691cbaa3d7fb7653671f0d09c9" -[[package]] -name = "snafu" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e84b3f4eacbf3a1ce05eac6763b4d629d60cbc94d632e4092c54ade71f1e1a2" -dependencies = [ - "snafu-derive", -] - -[[package]] -name = "snafu-derive" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1c97747dbf44bb1ca44a561ece23508e99cb592e862f22222dcf42f51d1e451" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "socket2" version = "0.5.10" @@ -5134,7 +5099,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 7332475992e..b1b77489603 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,4 +42,5 @@ unexpected_cfgs = { level = "warn", check-cfg = ["cfg(iroh_docsrs)", "cfg(iroh_l unused-async = "warn" [patch.crates-io] -iroh-metrics = { git = "https://github.com/n0-computer/iroh-metrics", branch = "Frando/n0-error" } +netwatch = { git = "https://github.com/n0-computer/net-tools", branch = "Frando/n0-snafu" } +portmapper = { git = "https://github.com/n0-computer/net-tools", branch = "Frando/n0-snafu" } diff --git a/iroh-dns-server/Cargo.toml b/iroh-dns-server/Cargo.toml index f630cffa821..51eedeb3a69 100644 --- a/iroh-dns-server/Cargo.toml +++ b/iroh-dns-server/Cargo.toml @@ -28,7 +28,7 @@ hickory-server = { version = "0.25.1", features = ["https-ring"] } http = "1.0.0" humantime = "2.2.0" humantime-serde = "1.1.1" -iroh-metrics = { version = "0.36", features = ["service"] } +iroh-metrics = { version = "0.37", features = ["service"] } lru = "0.16" n0-future = "0.3.0" pkarr = { version = "5", features = ["relays", "dht"], default-features = false } diff --git a/iroh-relay/Cargo.toml b/iroh-relay/Cargo.toml index e7e5ad8b794..afa43e5242f 100644 --- a/iroh-relay/Cargo.toml +++ b/iroh-relay/Cargo.toml @@ -32,7 +32,7 @@ http-body-util = "0.1.0" hyper = { version = "1", features = ["server", "client", "http1"] } hyper-util = "0.1.1" iroh-base = { version = "0.94.1", path = "../iroh-base", default-features = false, features = ["key", "relay"] } -iroh-metrics = { version = "0.36", default-features = false } +iroh-metrics = { version = "0.37", default-features = false } n0-future = "0.3.0" num_enum = "0.7" pin-project = "1" diff --git a/iroh/Cargo.toml b/iroh/Cargo.toml index a8895ecfcc7..287698f7002 100644 --- a/iroh/Cargo.toml +++ b/iroh/Cargo.toml @@ -40,7 +40,7 @@ iroh-base = { version = "0.94.1", default-features = false, features = ["key", " iroh-relay = { version = "0.94", path = "../iroh-relay", default-features = false } n0-future = "0.3.0" n0-error = "0.1.0" -n0-watcher = "0.4" +n0-watcher = "0.5" netwatch = { version = "0.11" } pin-project = "1" pkarr = { version = "5", default-features = false, features = ["relays"] } @@ -74,7 +74,7 @@ pkcs8 = "0.11.0-rc.7" rustls-platform-verifier = "0.5.3" # metrics -iroh-metrics = { version = "0.36", default-features = false } +iroh-metrics = { version = "0.37", default-features = false } # local-swarm-discovery swarm-discovery = { version = "0.4", optional = true } diff --git a/iroh/bench/Cargo.toml b/iroh/bench/Cargo.toml index 50bf4122f7e..5ae9fcb08f3 100644 --- a/iroh/bench/Cargo.toml +++ b/iroh/bench/Cargo.toml @@ -9,7 +9,7 @@ publish = false bytes = "1.7" hdrhistogram = { version = "7.2", default-features = false } iroh = { path = ".." } -iroh-metrics = "0.36" +iroh-metrics = "0.37" n0-future = "0.3.0" n0-error = "0.1.0" quinn = { package = "iroh-quinn", version = "0.14" } From 49848b85097ac4e42b946fa1f4e692c2ac991bf1 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 3 Nov 2025 16:39:43 +0100 Subject: [PATCH 55/58] fix: less std errors --- iroh/src/magicsock.rs | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/iroh/src/magicsock.rs b/iroh/src/magicsock.rs index b4a4b572f62..fb3f3d22a30 100644 --- a/iroh/src/magicsock.rs +++ b/iroh/src/magicsock.rs @@ -1335,30 +1335,15 @@ impl DirectAddrUpdateState { #[non_exhaustive] pub enum CreateHandleError { #[error("Failed to create bind sockets")] - BindSockets { - #[error(std_err)] - source: io::Error, - }, + BindSockets { source: io::Error }, #[error("Failed to create internal quinn endpoint")] - CreateQuinnEndpoint { - #[error(std_err)] - source: io::Error, - }, + CreateQuinnEndpoint { source: io::Error }, #[error("Failed to create socket state")] - CreateSocketState { - #[error(std_err)] - source: io::Error, - }, + CreateSocketState { source: io::Error }, #[error("Failed to create netmon monitor")] - CreateNetmonMonitor { - #[error(std_err)] - source: netmon::Error, - }, + CreateNetmonMonitor { source: netmon::Error }, #[error("Failed to subscribe netmon monitor")] - SubscribeNetmonMonitor { - #[error(std_err)] - source: netmon::Error, - }, + SubscribeNetmonMonitor { source: netmon::Error }, } impl Handle { From a9875edf78a85a3ef7d90d27725bc5297da8377c Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 3 Nov 2025 18:08:50 +0100 Subject: [PATCH 56/58] update portmapper and netwatch --- Cargo.lock | 10 ++++++---- Cargo.toml | 4 ---- iroh/Cargo.toml | 4 ++-- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9f6888ac325..0e21ccf9b1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2788,8 +2788,9 @@ dependencies = [ [[package]] name = "netwatch" -version = "0.11.0" -source = "git+https://github.com/n0-computer/net-tools?branch=Frando%2Fn0-snafu#29ed0df8ea644358b64d30ba37ddefe97628df26" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26f2acd376ef48b6c326abf3ba23c449e0cb8aa5c2511d189dd8a8a3bfac889b" dependencies = [ "atomic-waker", "bytes", @@ -3163,8 +3164,9 @@ checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "portmapper" -version = "0.11.0" -source = "git+https://github.com/n0-computer/net-tools?branch=Frando%2Fn0-snafu#29ed0df8ea644358b64d30ba37ddefe97628df26" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b575f975dcf03e258b0c7ab3f81497d7124f508884c37da66a7314aa2a8d467" dependencies = [ "base64", "bytes", diff --git a/Cargo.toml b/Cargo.toml index b1b77489603..0d0681861f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,3 @@ unexpected_cfgs = { level = "warn", check-cfg = ["cfg(iroh_docsrs)", "cfg(iroh_l [workspace.lints.clippy] unused-async = "warn" - -[patch.crates-io] -netwatch = { git = "https://github.com/n0-computer/net-tools", branch = "Frando/n0-snafu" } -portmapper = { git = "https://github.com/n0-computer/net-tools", branch = "Frando/n0-snafu" } diff --git a/iroh/Cargo.toml b/iroh/Cargo.toml index 287698f7002..16932bc647a 100644 --- a/iroh/Cargo.toml +++ b/iroh/Cargo.toml @@ -41,7 +41,7 @@ iroh-relay = { version = "0.94", path = "../iroh-relay", default-features = fals n0-future = "0.3.0" n0-error = "0.1.0" n0-watcher = "0.5" -netwatch = { version = "0.11" } +netwatch = { version = "0.12" } pin-project = "1" pkarr = { version = "5", default-features = false, features = ["relays"] } quinn = { package = "iroh-quinn", version = "0.14.0", default-features = false, features = ["rustls-ring"] } @@ -88,7 +88,7 @@ axum = { version = "0.8", optional = true } hickory-resolver = "0.25.1" igd-next = { version = "0.16", features = ["aio_tokio"] } netdev = { version = "0.38.1" } -portmapper = { version = "0.11", default-features = false } +portmapper = { version = "0.12", default-features = false } quinn = { package = "iroh-quinn", version = "0.14.0", default-features = false, features = ["runtime-tokio", "rustls-ring"] } tokio = { version = "1", features = [ "io-util", From 10a85586b51ceeacba126c9ba2d8ece9d574967e Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 3 Nov 2025 18:45:59 +0100 Subject: [PATCH 57/58] address some nits --- iroh-base/src/relay_url.rs | 2 +- iroh-relay/src/client.rs | 2 +- iroh-relay/src/server/client.rs | 6 +++--- iroh-relay/src/server/http_server.rs | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/iroh-base/src/relay_url.rs b/iroh-base/src/relay_url.rs index c49389e329b..5925a39f092 100644 --- a/iroh-base/src/relay_url.rs +++ b/iroh-base/src/relay_url.rs @@ -51,7 +51,7 @@ impl FromStr for RelayUrl { type Err = RelayUrlParseError; fn from_str(s: &str) -> Result { - let inner = Url::from_str(s).map_err(|err| RelayUrlParseError::new(err))?; + let inner = Url::from_str(s).map_err(RelayUrlParseError::new)?; Ok(RelayUrl::from(inner)) } } diff --git a/iroh-relay/src/client.rs b/iroh-relay/src/client.rs index 14482e38098..3bba68cdb41 100644 --- a/iroh-relay/src/client.rs +++ b/iroh-relay/src/client.rs @@ -96,7 +96,7 @@ pub enum ConnectError { #[allow(missing_docs)] #[non_exhaustive] pub enum DialError { - #[error("Invliad target port")] + #[error("Invalid target port")] InvalidTargetPort {}, #[error(transparent)] #[cfg(not(wasm_browser))] diff --git a/iroh-relay/src/server/client.rs b/iroh-relay/src/server/client.rs index 81cf58c9a16..b1af242de8e 100644 --- a/iroh-relay/src/server/client.rs +++ b/iroh-relay/src/server/client.rs @@ -534,7 +534,7 @@ impl ClientCounter { #[cfg(test)] mod tests { use iroh_base::SecretKey; - use n0_error::{Result, StdResultExt}; + use n0_error::{Result, StdResultExt, bail_any}; use n0_future::Stream; use rand::SeedableRng; use tracing::info; @@ -553,7 +553,7 @@ mod tests { match stream.next().await { Some(Ok(frame)) => { if frame_type != frame.typ() { - n0_error::bail_any!( + bail_any!( "Unexpected frame, got {:?}, but expected {:?}", frame.typ(), frame_type @@ -562,7 +562,7 @@ mod tests { Ok(frame) } Some(Err(err)) => Err(err).anyerr(), - None => n0_error::bail_any!("Unexpected EOF, expected frame {frame_type:?}"), + None => bail_any!("Unexpected EOF, expected frame {frame_type:?}"), } } diff --git a/iroh-relay/src/server/http_server.rs b/iroh-relay/src/server/http_server.rs index 31244a4b84e..40b1d773c35 100644 --- a/iroh-relay/src/server/http_server.rs +++ b/iroh-relay/src/server/http_server.rs @@ -15,7 +15,7 @@ use hyper::{ service::Service, upgrade::Upgraded, }; -use n0_error::{e, stack_error}; +use n0_error::{e, ensure, stack_error}; use n0_future::time::Elapsed; use tokio::net::{TcpListener, TcpStream}; use tokio_rustls_acme::AcmeAcceptor; @@ -454,7 +454,7 @@ impl RelayService { } let upgrade_header = expect_header(&req, UPGRADE)?; - n0_error::ensure!( + ensure!( upgrade_header == HeaderValue::from_static(WEBSOCKET_UPGRADE_PROTOCOL), RelayUpgradeReqError::InvalidHeader { header: UPGRADE, @@ -465,7 +465,7 @@ impl RelayService { let key = expect_header(&req, SEC_WEBSOCKET_KEY)?.clone(); let version = expect_header(&req, SEC_WEBSOCKET_VERSION)?.clone(); - n0_error::ensure!( + ensure!( version.as_bytes() == SUPPORTED_WEBSOCKET_VERSION.as_bytes(), RelayUpgradeReqError::UnsupportedWebsocketVersion ); @@ -482,7 +482,7 @@ impl RelayService { let supports_our_version = subprotocols .split_whitespace() .any(|p| p == RELAY_PROTOCOL_VERSION); - n0_error::ensure!( + ensure!( supports_our_version, RelayUpgradeReqError::UnsupportedRelayVersion { we_support: RELAY_PROTOCOL_VERSION, From 5924089e9fd50c1fafcf1e39d8b83f3149360f9f Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 3 Nov 2025 19:47:51 +0100 Subject: [PATCH 58/58] tests: mark integration_mainline as flaky --- iroh-dns-server/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/iroh-dns-server/src/lib.rs b/iroh-dns-server/src/lib.rs index a20573603fc..c3f7475a674 100644 --- a/iroh-dns-server/src/lib.rs +++ b/iroh-dns-server/src/lib.rs @@ -223,6 +223,7 @@ mod tests { #[tokio::test] #[traced_test] + #[ignore = "flaky"] async fn integration_mainline() -> Result { let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(0u64);