From 1be22d8b646d623660e5fa745febe8f3d122e49f Mon Sep 17 00:00:00 2001 From: Diva M Date: Thu, 16 May 2024 14:18:23 -0500 Subject: [PATCH 01/14] remove unnecessary trait bounds --- iroh-net/src/dns.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/iroh-net/src/dns.rs b/iroh-net/src/dns.rs index 068166bb54..ac61b721f3 100644 --- a/iroh-net/src/dns.rs +++ b/iroh-net/src/dns.rs @@ -78,14 +78,14 @@ fn create_default_resolver() -> Result { /// Extension trait to [`DnsResolver`]. pub trait ResolverExt { /// Perform an ipv4 lookup with a timeout. - fn lookup_ipv4( + fn lookup_ipv4( &self, host: N, timeout: Duration, ) -> impl Future>>; /// Perform an ipv6 lookup with a timeout. - fn lookup_ipv6( + fn lookup_ipv6( &self, host: N, timeout: Duration, @@ -100,7 +100,7 @@ pub trait ResolverExt { } impl ResolverExt for DnsResolver { - async fn lookup_ipv4( + async fn lookup_ipv4( &self, host: N, timeout: Duration, @@ -109,7 +109,7 @@ impl ResolverExt for DnsResolver { Ok(addrs.into_iter().map(|ip| IpAddr::V4(ip.0))) } - async fn lookup_ipv6( + async fn lookup_ipv6( &self, host: N, timeout: Duration, From 5670adf6303e2175854a821d5b895c36f2864d72 Mon Sep 17 00:00:00 2001 From: Diva M Date: Fri, 17 May 2024 16:20:41 -0500 Subject: [PATCH 02/14] unify dns capabilities under ResolverExt --- iroh-dns-server/src/lib.rs | 9 +++------ iroh-net/src/discovery.rs | 6 +++--- iroh-net/src/discovery/dns.rs | 6 +++--- iroh-net/src/dns.rs | 31 +++++++++++++++++++++++++++++++ iroh-net/src/dns/node_info.rs | 21 --------------------- 5 files changed, 40 insertions(+), 33 deletions(-) diff --git a/iroh-dns-server/src/lib.rs b/iroh-dns-server/src/lib.rs index 95e09bfc1e..117b2c6d9c 100644 --- a/iroh-dns-server/src/lib.rs +++ b/iroh-dns-server/src/lib.rs @@ -22,10 +22,7 @@ mod tests { }; use iroh_net::{ discovery::pkarr_publish::PkarrRelayClient, - dns::{ - node_info::{lookup_by_id, NodeInfo}, - DnsResolver, - }, + dns::{node_info::NodeInfo, DnsResolver, ResolverExt}, key::SecretKey, }; use pkarr::{PkarrClient, SignedPacket}; @@ -168,7 +165,7 @@ mod tests { pkarr.publish(&signed_packet).await?; let resolver = test_resolver(nameserver); - let res = lookup_by_id(&resolver, &node_id, origin).await?; + let res = resolver.lookup_by_id(&node_id, origin).await?; assert_eq!(res.node_id, node_id); assert_eq!(res.info.relay_url.map(Url::from), Some(relay_url)); @@ -204,7 +201,7 @@ mod tests { // resolve via DNS from our server, which will lookup from our DHT let resolver = test_resolver(nameserver); - let res = lookup_by_id(&resolver, &node_id, origin).await?; + let res = resolver.lookup_by_id(&node_id, origin).await?; assert_eq!(res.node_id, node_id); assert_eq!(res.info.relay_url.map(Url::from), Some(relay_url)); diff --git a/iroh-net/src/discovery.rs b/iroh-net/src/discovery.rs index 0fba47ca29..0b935621c2 100644 --- a/iroh-net/src/discovery.rs +++ b/iroh-net/src/discovery.rs @@ -562,7 +562,7 @@ mod test_dns_pkarr { use crate::{ discovery::pkarr_publish::PkarrPublisher, - dns::node_info::{lookup_by_id, NodeInfo}, + dns::{node_info::NodeInfo, ResolverExt}, relay::{RelayMap, RelayMode}, test_utils::{ dns_server::{create_dns_resolver, run_dns_server}, @@ -590,7 +590,7 @@ mod test_dns_pkarr { state.upsert(signed_packet)?; let resolver = create_dns_resolver(nameserver)?; - let resolved = lookup_by_id(&resolver, &node_info.node_id, &origin).await?; + let resolved = resolver.lookup_by_id(&node_info.node_id, &origin).await?; assert_eq!(resolved, node_info.into()); @@ -620,7 +620,7 @@ mod test_dns_pkarr { publisher.update_addr_info(&addr_info); // wait until our shared state received the update from pkarr publishing dns_pkarr_server.on_node(&node_id, timeout).await?; - let resolved = lookup_by_id(&resolver, &node_id, &origin).await?; + let resolved = resolver.lookup_by_id(&node_id, &origin).await?; let expected = NodeAddr { info: addr_info, diff --git a/iroh-net/src/discovery/dns.rs b/iroh-net/src/discovery/dns.rs index 76f487456f..8c8428474a 100644 --- a/iroh-net/src/discovery/dns.rs +++ b/iroh-net/src/discovery/dns.rs @@ -5,7 +5,8 @@ use futures_lite::stream::Boxed as BoxStream; use crate::{ discovery::{Discovery, DiscoveryItem}, - dns, Endpoint, NodeId, + dns::ResolverExt, + Endpoint, NodeId, }; /// The n0 testing DNS node origin @@ -53,8 +54,7 @@ impl Discovery for DnsDiscovery { let resolver = ep.dns_resolver().clone(); let origin_domain = self.origin_domain.clone(); let fut = async move { - let node_addr = - dns::node_info::lookup_by_id(&resolver, &node_id, &origin_domain).await?; + let node_addr = resolver.lookup_by_id(&node_id, &origin_domain).await?; Ok(DiscoveryItem { provenance: "dns", last_updated: None, diff --git a/iroh-net/src/dns.rs b/iroh-net/src/dns.rs index ac61b721f3..d3e1df844b 100644 --- a/iroh-net/src/dns.rs +++ b/iroh-net/src/dns.rs @@ -7,6 +7,8 @@ use std::time::Duration; use anyhow::Result; use futures_lite::Future; use hickory_resolver::{AsyncResolver, IntoName, TokioAsyncResolver}; +use iroh_base::key::NodeId; +use iroh_base::node_addr::NodeAddr; use once_cell::sync::Lazy; pub mod node_info; @@ -97,6 +99,16 @@ pub trait ResolverExt { host: N, timeout: Duration, ) -> impl Future>>; + + /// Looks up node info by DNS name. + fn lookup_by_domain(&self, name: &str) -> impl Future>; + + /// Looks up node info by [`NodeId`] and origin domain name. + fn lookup_by_id( + &self, + node_id: &NodeId, + origin: &str, + ) -> impl Future>; } impl ResolverExt for DnsResolver { @@ -142,6 +154,25 @@ impl ResolverExt for DnsResolver { } } } + + /// Looks up node info by DNS name. + /// + /// The resource records returned for `name` must either contain an [`IROH_TXT_NAME`] TXT + /// record or be a CNAME record that leads to an [`node_info::IROH_TXT_NAME`] TXT record. + async fn lookup_by_domain(&self, name: &str) -> Result { + let attrs = + node_info::TxtAttrs::::lookup_by_domain(self, name).await?; + let info: node_info::NodeInfo = attrs.into(); + Ok(info.into()) + } + + /// Looks up node info by [`NodeId`] and origin domain name. + async fn lookup_by_id(&self, node_id: &NodeId, origin: &str) -> Result { + let attrs = + node_info::TxtAttrs::::lookup_by_id(self, node_id, origin).await?; + let info: node_info::NodeInfo = attrs.into(); + Ok(info.into()) + } } /// Helper enum to give a unified type to the iterators of [`ResolverExt::lookup_ipv4_ipv6`] diff --git a/iroh-net/src/dns/node_info.rs b/iroh-net/src/dns/node_info.rs index 4e34107674..2d61b40228 100644 --- a/iroh-net/src/dns/node_info.rs +++ b/iroh-net/src/dns/node_info.rs @@ -62,27 +62,6 @@ pub enum IrohAttr { Addr, } -/// Looks up node info by DNS name. -/// -/// The resource records returned for `name` must either contain an [`IROH_TXT_NAME`] TXT -/// record or be a CNAME record that leads to an [`IROH_TXT_NAME`] TXT record. -pub async fn lookup_by_domain(resolver: &TokioAsyncResolver, name: &str) -> Result { - let attrs = TxtAttrs::::lookup_by_domain(resolver, name).await?; - let info: NodeInfo = attrs.into(); - Ok(info.into()) -} - -/// Looks up node info by [`NodeId`] and origin domain name. -pub async fn lookup_by_id( - resolver: &TokioAsyncResolver, - node_id: &NodeId, - origin: &str, -) -> Result { - let attrs = TxtAttrs::::lookup_by_id(resolver, node_id, origin).await?; - let info: NodeInfo = attrs.into(); - Ok(info.into()) -} - /// Encodes a [`NodeId`] in [`z-base-32`] encoding. /// /// [z-base-32]: https://philzimmermann.com/docs/human-oriented-base-32-encoding.txt From 638e4dba300aae6cac099d6ae9ebef55f232a69e Mon Sep 17 00:00:00 2001 From: Diva M Date: Sat, 18 May 2024 12:50:55 -0500 Subject: [PATCH 03/14] Add helper fn stagger_call --- iroh-net/src/dns.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/iroh-net/src/dns.rs b/iroh-net/src/dns.rs index d3e1df844b..71a723302e 100644 --- a/iroh-net/src/dns.rs +++ b/iroh-net/src/dns.rs @@ -5,7 +5,7 @@ use std::net::{IpAddr, Ipv6Addr}; use std::time::Duration; use anyhow::Result; -use futures_lite::Future; +use futures_lite::{Future, StreamExt}; use hickory_resolver::{AsyncResolver, IntoName, TokioAsyncResolver}; use iroh_base::key::NodeId; use iroh_base::node_addr::NodeAddr; @@ -194,8 +194,48 @@ impl, B: Iterator> Iterator for Lookup } } +/// Staggers calls to the future F with the given delays. +/// +/// The first call is performed immediately. The first call to succeed generates an Ok result +/// ignoring any previous error. If all calls fail, an error sumarizing all errors is returned. +async fn stagger_call Fut, Fut: Future>>( + f: F, + delays_ms: &[u64], +) -> Result { + let mut calls = futures_buffered::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. + for delay in std::iter::once(&0u64).chain(delays_ms) { + let delay = std::time::Duration::from_millis(*delay); + let fut = f(); + let staggered_fut = async move { + tokio::time::sleep(delay).await; + fut.await + }; + calls.push(staggered_fut) + } + + let mut errors = vec![]; + while let Some(call_result) = calls.next().await { + match call_result { + Ok(t) => return Ok(t), + Err(e) => errors.push(e), + } + } + + anyhow::bail!( + "no calls succeed: [ {}]", + errors + .into_iter() + .map(|e| format!("{e} ")) + .collect::() + ) +} + #[cfg(test)] pub(crate) mod tests { + use std::sync::atomic::AtomicUsize; + use crate::defaults::NA_RELAY_HOSTNAME; use super::*; @@ -224,4 +264,22 @@ pub(crate) mod tests { assert!(!res.is_empty()); dbg!(res); } + + #[tokio::test] + async fn stagger_basic() { + let _logging = iroh_test::logging::setup(); + const CALL_RESULTS: &[Result] = &[Err(2), Ok(3), Ok(5), Ok(7)]; + static DONE_CALL: AtomicUsize = AtomicUsize::new(0); + let f = || { + 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(|e| anyhow::anyhow!("{e}")) + } + }; + + let delays = [1000, 15]; + let result = stagger_call(f, &delays).await.unwrap(); + assert_eq!(result, 5) + } } From 918b3866898596b1179b8f486aed2f1c7b482b40 Mon Sep 17 00:00:00 2001 From: Diva M Date: Sat, 18 May 2024 13:14:47 -0500 Subject: [PATCH 04/14] add staggering versions of the ResolverExt functions --- iroh-net/src/dns.rs | 111 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/iroh-net/src/dns.rs b/iroh-net/src/dns.rs index 71a723302e..bd0f29b4ca 100644 --- a/iroh-net/src/dns.rs +++ b/iroh-net/src/dns.rs @@ -109,6 +109,57 @@ pub trait ResolverExt { node_id: &NodeId, origin: &str, ) -> impl Future>; + + /// Perform an ipv4 lookup with a timeout in a staggered fashion. + /// + /// The first call is done immediately, with added calls according to the staggering strategy. + fn staggered_lookup_ipv4( + &self, + host: N, + timeout: Duration, + delays_ms: &[u64], + ) -> impl Future>>; + + /// Perform an ipv6 lookup with a timeout in a staggered fashion. + /// + /// The first call is done immediately, with added calls according to the staggering strategy. + fn staggered_lookup_ipv6( + &self, + host: N, + timeout: Duration, + + delays_ms: &[u64], + ) -> impl Future>>; + + /// Race an ipv4 and ipv6 lookup with a timeout in a staggered fashion. + /// + /// The first call is done immediately, with added calls according to the staggering strategy. + fn staggered_lookup_ipv4_ipv6( + &self, + host: N, + timeout: Duration, + + delays_ms: &[u64], + ) -> impl Future>>; + + /// Looks up node info by DNS name in a staggered fashion. + /// + /// The first call is done immediately, with added calls according to the staggering strategy. + fn staggered_lookup_by_domain( + &self, + name: &str, + delays_ms: &[u64], + ) -> impl Future>; + + /// Looks up node info by [`NodeId`] and origin domain name. + /// + /// The first call is done immediately, with added calls according to the staggering strategy. + fn staggered_lookup_by_id( + &self, + node_id: &NodeId, + origin: &str, + delays_ms: &[u64], + ) -> impl Future>; } impl ResolverExt for DnsResolver { @@ -173,6 +224,66 @@ impl ResolverExt for DnsResolver { let info: node_info::NodeInfo = attrs.into(); Ok(info.into()) } + + /// Perform an ipv4 lookup with a timeout in a staggered fashion. + /// + /// The first call is done immediately, with added calls according to the staggering strategy. + async fn staggered_lookup_ipv4( + &self, + host: N, + timeout: Duration, + delays_ms: &[u64], + ) -> Result> { + let f = || self.lookup_ipv4(host.clone(), timeout); + stagger_call(f, delays_ms).await + } + + /// Perform an ipv6 lookup with a timeout in a staggered fashion. + /// + /// The first call is done immediately, with added calls according to the staggering strategy. + async fn staggered_lookup_ipv6( + &self, + host: N, + timeout: Duration, + delays_ms: &[u64], + ) -> Result> { + let f = || self.lookup_ipv6(host.clone(), timeout); + stagger_call(f, delays_ms).await + } + + /// Race an ipv4 and ipv6 lookup with a timeout in a staggered fashion. + /// + /// The first call is done immediately, with added calls according to the staggering strategy. + async fn staggered_lookup_ipv4_ipv6( + &self, + host: N, + timeout: Duration, + delays_ms: &[u64], + ) -> Result> { + let f = || self.lookup_ipv4_ipv6(host.clone(), timeout); + stagger_call(f, delays_ms).await + } + + /// Looks up node info by DNS name in a staggered fashion. + /// + /// The first call is done immediately, with added calls according to the staggering strategy. + async fn staggered_lookup_by_domain(&self, name: &str, delays_ms: &[u64]) -> Result { + let f = || self.lookup_by_domain(name); + stagger_call(f, delays_ms).await + } + + /// Looks up node info by [`NodeId`] and origin domain name. + /// + /// The first call is done immediately, with added calls according to the staggering strategy. + async fn staggered_lookup_by_id( + &self, + node_id: &NodeId, + origin: &str, + delays_ms: &[u64], + ) -> Result { + let f = || self.lookup_by_id(node_id, origin); + stagger_call(f, delays_ms).await + } } /// Helper enum to give a unified type to the iterators of [`ResolverExt::lookup_ipv4_ipv6`] From 552cd27927835fbce8e4c792b0f7ae1732695e58 Mon Sep 17 00:00:00 2001 From: Diva M Date: Sat, 18 May 2024 13:16:46 -0500 Subject: [PATCH 05/14] fmt --- iroh-net/src/dns.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/iroh-net/src/dns.rs b/iroh-net/src/dns.rs index bd0f29b4ca..b6c59bd880 100644 --- a/iroh-net/src/dns.rs +++ b/iroh-net/src/dns.rs @@ -127,7 +127,6 @@ pub trait ResolverExt { &self, host: N, timeout: Duration, - delays_ms: &[u64], ) -> impl Future>>; @@ -138,7 +137,6 @@ pub trait ResolverExt { &self, host: N, timeout: Duration, - delays_ms: &[u64], ) -> impl Future>>; From 173e841379bf0dbc65ef37947cd0e94f9af6eaae Mon Sep 17 00:00:00 2001 From: Diva M Date: Sat, 18 May 2024 13:27:10 -0500 Subject: [PATCH 06/14] clarify timeouts and adjust flaky test --- iroh-net/src/dns.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/iroh-net/src/dns.rs b/iroh-net/src/dns.rs index b6c59bd880..96eb6268d6 100644 --- a/iroh-net/src/dns.rs +++ b/iroh-net/src/dns.rs @@ -226,6 +226,7 @@ impl ResolverExt for DnsResolver { /// Perform an ipv4 lookup with a timeout in a staggered fashion. /// /// The first call is done immediately, with added calls according to the staggering strategy. + /// The timeout is passed to every individual call to [`ResolverExt::lookup_ipv4`]. async fn staggered_lookup_ipv4( &self, host: N, @@ -239,6 +240,7 @@ impl ResolverExt for DnsResolver { /// Perform an ipv6 lookup with a timeout in a staggered fashion. /// /// The first call is done immediately, with added calls according to the staggering strategy. + /// The timeout is passed to every individual call to [`ResolverExt::lookup_ipv6`]. async fn staggered_lookup_ipv6( &self, host: N, @@ -252,6 +254,7 @@ impl ResolverExt for DnsResolver { /// Race an ipv4 and ipv6 lookup with a timeout in a staggered fashion. /// /// The first call is done immediately, with added calls according to the staggering strategy. + /// The timeout is passed to every individual call to [`ResolverExt::lookup_ipv4_ipv6`]. async fn staggered_lookup_ipv4_ipv6( &self, host: N, @@ -284,7 +287,7 @@ impl ResolverExt for DnsResolver { } } -/// Helper enum to give a unified type to the iterators of [`ResolverExt::lookup_ipv4_ipv6`] +/// Helper enum to give a unified type to the iterators of [`ResolverExt::lookup_ipv4_ipv6`]. enum LookupIter { Ipv4(A), Ipv6(B), @@ -348,6 +351,8 @@ pub(crate) mod tests { use crate::defaults::NA_RELAY_HOSTNAME; use super::*; + const TIMEOUT: Duration = Duration::from_secs(5); + const STAGGERING_DELAYS: &[u64] = &[200, 300]; #[tokio::test] #[cfg_attr(target_os = "windows", ignore = "flaky")] @@ -361,12 +366,11 @@ pub(crate) mod tests { } #[tokio::test] - #[cfg_attr(target_os = "windows", ignore = "flaky")] async fn test_dns_lookup_ipv4_ipv6() { let _logging = iroh_test::logging::setup(); let resolver = default_resolver(); let res: Vec<_> = resolver - .lookup_ipv4_ipv6(NA_RELAY_HOSTNAME, Duration::from_secs(5)) + .staggered_lookup_ipv4_ipv6(NA_RELAY_HOSTNAME, TIMEOUT, STAGGERING_DELAYS) .await .unwrap() .collect(); From a315e2b3e49c357b7a4f43c86add2d1d56b24838 Mon Sep 17 00:00:00 2001 From: Diva M Date: Mon, 20 May 2024 00:34:50 -0500 Subject: [PATCH 07/14] use staggered options and turn on tests --- iroh-net/src/discovery/dns.rs | 5 ++++- iroh-net/src/netcheck/reportgen.rs | 16 ++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/iroh-net/src/discovery/dns.rs b/iroh-net/src/discovery/dns.rs index 8c8428474a..d850daf579 100644 --- a/iroh-net/src/discovery/dns.rs +++ b/iroh-net/src/discovery/dns.rs @@ -11,6 +11,7 @@ use crate::{ /// The n0 testing DNS node origin pub const N0_DNS_NODE_ORIGIN: &str = "dns.iroh.link"; +const DNS_STAGGERING_MS: &[u64] = &[200, 300]; /// DNS node discovery /// @@ -54,7 +55,9 @@ impl Discovery for DnsDiscovery { let resolver = ep.dns_resolver().clone(); let origin_domain = self.origin_domain.clone(); let fut = async move { - let node_addr = resolver.lookup_by_id(&node_id, &origin_domain).await?; + let node_addr = resolver + .staggered_lookup_by_id(&node_id, &origin_domain, DNS_STAGGERING_MS) + .await?; Ok(DiscoveryItem { provenance: "dns", last_updated: None, diff --git a/iroh-net/src/netcheck/reportgen.rs b/iroh-net/src/netcheck/reportgen.rs index 2085610bde..227440aaf6 100644 --- a/iroh-net/src/netcheck/reportgen.rs +++ b/iroh-net/src/netcheck/reportgen.rs @@ -73,6 +73,9 @@ const ENOUGH_NODES: usize = 3; const DNS_TIMEOUT: Duration = Duration::from_secs(3); +/// Delay used to perform staggered dns queries. +const DNS_STAGGERING_MS: &[u64] = &[200, 300]; + /// Holds the state for a single invocation of [`netcheck::Client::get_report`]. /// /// Dropping this will cancel the actor and stop the report generation. @@ -192,7 +195,7 @@ struct Actor { /// /// This is essentially the summary of all the work the [`Actor`] is doing. outstanding_tasks: OutstandingTasks, - /// The DNS resolver to use for probes that need to resolve DNS records + /// The DNS resolver to use for probes that need to resolve DNS records. dns_resolver: DnsResolver, } @@ -945,7 +948,10 @@ async fn get_relay_addr( ProbeProto::StunIpv4 | ProbeProto::IcmpV4 => match relay_node.url.host() { Some(url::Host::Domain(hostname)) => { debug!(?proto, %hostname, "Performing DNS A lookup for relay addr"); - match dns_resolver.lookup_ipv4(hostname, DNS_TIMEOUT).await { + match dns_resolver + .staggered_lookup_ipv4(hostname, DNS_TIMEOUT, DNS_STAGGERING_MS) + .await + { Ok(mut addrs) => addrs .next() .map(ip::to_canonical) @@ -962,7 +968,10 @@ async fn get_relay_addr( ProbeProto::StunIpv6 | ProbeProto::IcmpV6 => match relay_node.url.host() { Some(url::Host::Domain(hostname)) => { debug!(?proto, %hostname, "Performing DNS AAAA lookup for relay addr"); - match dns_resolver.lookup_ipv6(hostname, DNS_TIMEOUT).await { + match dns_resolver + .staggered_lookup_ipv6(hostname, DNS_TIMEOUT, DNS_STAGGERING_MS) + .await + { Ok(mut addrs) => addrs .next() .map(ip::to_canonical) @@ -1316,7 +1325,6 @@ mod tests { // // TODO: Not sure what about IPv6 pings using sysctl. #[tokio::test] - #[cfg_attr(target_os = "windows", ignore = "flaky")] async fn test_icmpk_probe_eu_relayer() { let _logging_guard = iroh_test::logging::setup(); let pinger = Pinger::new(); From 245564635efe5a60103f07eda52529f66acd1c4e Mon Sep 17 00:00:00 2001 From: Diva M Date: Mon, 20 May 2024 00:42:07 -0500 Subject: [PATCH 08/14] make clippy happy --- iroh-net/src/dns.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/iroh-net/src/dns.rs b/iroh-net/src/dns.rs index 96eb6268d6..c351710ea4 100644 --- a/iroh-net/src/dns.rs +++ b/iroh-net/src/dns.rs @@ -1,6 +1,7 @@ //! This module exports a DNS resolver, which is also the default resolver used in the //! [`crate::Endpoint`] if no custom resolver is configured. +use std::fmt::Write; use std::net::{IpAddr, Ipv6Addr}; use std::time::Duration; @@ -337,10 +338,10 @@ async fn stagger_call Fut, Fut: Future>>( anyhow::bail!( "no calls succeed: [ {}]", - errors - .into_iter() - .map(|e| format!("{e} ")) - .collect::() + errors.into_iter().fold(String::new(), |mut summary, e| { + write!(summary, "{e} ").expect("infallible"); + summary + }) ) } From cd4c1c7bbc8784f2acc326f1af4cfdbaef16dbef Mon Sep 17 00:00:00 2001 From: Diva M Date: Mon, 20 May 2024 00:57:02 -0500 Subject: [PATCH 09/14] fix docs --- iroh-net/src/dns.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iroh-net/src/dns.rs b/iroh-net/src/dns.rs index c351710ea4..29c65c9861 100644 --- a/iroh-net/src/dns.rs +++ b/iroh-net/src/dns.rs @@ -207,7 +207,7 @@ impl ResolverExt for DnsResolver { /// Looks up node info by DNS name. /// - /// The resource records returned for `name` must either contain an [`IROH_TXT_NAME`] TXT + /// The resource records returned for `name` must either contain an [`node_info::IROH_TXT_NAME`] TXT /// record or be a CNAME record that leads to an [`node_info::IROH_TXT_NAME`] TXT record. async fn lookup_by_domain(&self, name: &str) -> Result { let attrs = From 00e848daf8898cb29b50dd53220f2196187889fe Mon Sep 17 00:00:00 2001 From: Diva M Date: Tue, 21 May 2024 09:56:47 -0500 Subject: [PATCH 10/14] change to by_name --- iroh-dns-server/examples/resolve.rs | 2 +- iroh-net/src/dns.rs | 13 ++++++------- iroh-net/src/dns/node_info.rs | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/iroh-dns-server/examples/resolve.rs b/iroh-dns-server/examples/resolve.rs index b9464ab38c..e660c6335c 100644 --- a/iroh-dns-server/examples/resolve.rs +++ b/iroh-dns-server/examples/resolve.rs @@ -57,7 +57,7 @@ async fn main() -> anyhow::Result<()> { TxtAttrs::::lookup_by_id(&resolver, &node_id, origin).await? } Command::Domain { domain } => { - TxtAttrs::::lookup_by_domain(&resolver, &domain).await? + TxtAttrs::::lookup_by_name(&resolver, &domain).await? } }; println!("resolved node {}", resolved.node_id()); diff --git a/iroh-net/src/dns.rs b/iroh-net/src/dns.rs index 29c65c9861..293f08a27e 100644 --- a/iroh-net/src/dns.rs +++ b/iroh-net/src/dns.rs @@ -102,7 +102,7 @@ pub trait ResolverExt { ) -> impl Future>>; /// Looks up node info by DNS name. - fn lookup_by_domain(&self, name: &str) -> impl Future>; + fn lookup_by_name(&self, name: &str) -> impl Future>; /// Looks up node info by [`NodeId`] and origin domain name. fn lookup_by_id( @@ -144,7 +144,7 @@ pub trait ResolverExt { /// Looks up node info by DNS name in a staggered fashion. /// /// The first call is done immediately, with added calls according to the staggering strategy. - fn staggered_lookup_by_domain( + fn staggered_lookup_by_name( &self, name: &str, delays_ms: &[u64], @@ -209,9 +209,8 @@ impl ResolverExt for DnsResolver { /// /// The resource records returned for `name` must either contain an [`node_info::IROH_TXT_NAME`] TXT /// record or be a CNAME record that leads to an [`node_info::IROH_TXT_NAME`] TXT record. - async fn lookup_by_domain(&self, name: &str) -> Result { - let attrs = - node_info::TxtAttrs::::lookup_by_domain(self, name).await?; + async fn lookup_by_name(&self, name: &str) -> Result { + let attrs = node_info::TxtAttrs::::lookup_by_name(self, name).await?; let info: node_info::NodeInfo = attrs.into(); Ok(info.into()) } @@ -269,8 +268,8 @@ impl ResolverExt for DnsResolver { /// Looks up node info by DNS name in a staggered fashion. /// /// The first call is done immediately, with added calls according to the staggering strategy. - async fn staggered_lookup_by_domain(&self, name: &str, delays_ms: &[u64]) -> Result { - let f = || self.lookup_by_domain(name); + async fn staggered_lookup_by_name(&self, name: &str, delays_ms: &[u64]) -> Result { + let f = || self.lookup_by_name(name); stagger_call(f, delays_ms).await } diff --git a/iroh-net/src/dns/node_info.rs b/iroh-net/src/dns/node_info.rs index 2d61b40228..16bf532cf4 100644 --- a/iroh-net/src/dns/node_info.rs +++ b/iroh-net/src/dns/node_info.rs @@ -279,7 +279,7 @@ impl TxtAttrs { } /// Looks up attributes by DNS name. - pub async fn lookup_by_domain(resolver: &TokioAsyncResolver, name: &str) -> Result { + pub async fn lookup_by_name(resolver: &TokioAsyncResolver, name: &str) -> Result { let name = Name::from_str(name)?; TxtAttrs::lookup(resolver, name).await } From ead3cf8e2f38d9f300eaf4e6237d12ef224eb9ed Mon Sep 17 00:00:00 2001 From: Diva M Date: Tue, 21 May 2024 10:03:26 -0500 Subject: [PATCH 11/14] change naming order to keep prefix --- iroh-net/src/discovery/dns.rs | 2 +- iroh-net/src/dns.rs | 22 +++++++++++----------- iroh-net/src/netcheck/reportgen.rs | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/iroh-net/src/discovery/dns.rs b/iroh-net/src/discovery/dns.rs index d850daf579..13706deb5d 100644 --- a/iroh-net/src/discovery/dns.rs +++ b/iroh-net/src/discovery/dns.rs @@ -56,7 +56,7 @@ impl Discovery for DnsDiscovery { let origin_domain = self.origin_domain.clone(); let fut = async move { let node_addr = resolver - .staggered_lookup_by_id(&node_id, &origin_domain, DNS_STAGGERING_MS) + .lookup_by_id_staggered(&node_id, &origin_domain, DNS_STAGGERING_MS) .await?; Ok(DiscoveryItem { provenance: "dns", diff --git a/iroh-net/src/dns.rs b/iroh-net/src/dns.rs index 293f08a27e..fc146c4867 100644 --- a/iroh-net/src/dns.rs +++ b/iroh-net/src/dns.rs @@ -114,7 +114,7 @@ pub trait ResolverExt { /// Perform an ipv4 lookup with a timeout in a staggered fashion. /// /// The first call is done immediately, with added calls according to the staggering strategy. - fn staggered_lookup_ipv4( + fn lookup_ipv4_staggered( &self, host: N, timeout: Duration, @@ -124,7 +124,7 @@ pub trait ResolverExt { /// Perform an ipv6 lookup with a timeout in a staggered fashion. /// /// The first call is done immediately, with added calls according to the staggering strategy. - fn staggered_lookup_ipv6( + fn lookup_ipv6_staggered( &self, host: N, timeout: Duration, @@ -134,7 +134,7 @@ pub trait ResolverExt { /// Race an ipv4 and ipv6 lookup with a timeout in a staggered fashion. /// /// The first call is done immediately, with added calls according to the staggering strategy. - fn staggered_lookup_ipv4_ipv6( + fn lookup_ipv4_ipv6_staggered( &self, host: N, timeout: Duration, @@ -144,7 +144,7 @@ pub trait ResolverExt { /// Looks up node info by DNS name in a staggered fashion. /// /// The first call is done immediately, with added calls according to the staggering strategy. - fn staggered_lookup_by_name( + fn lookup_by_name_staggered( &self, name: &str, delays_ms: &[u64], @@ -153,7 +153,7 @@ pub trait ResolverExt { /// Looks up node info by [`NodeId`] and origin domain name. /// /// The first call is done immediately, with added calls according to the staggering strategy. - fn staggered_lookup_by_id( + fn lookup_by_id_staggered( &self, node_id: &NodeId, origin: &str, @@ -227,7 +227,7 @@ impl ResolverExt for DnsResolver { /// /// The first call is done immediately, with added calls according to the staggering strategy. /// The timeout is passed to every individual call to [`ResolverExt::lookup_ipv4`]. - async fn staggered_lookup_ipv4( + async fn lookup_ipv4_staggered( &self, host: N, timeout: Duration, @@ -241,7 +241,7 @@ impl ResolverExt for DnsResolver { /// /// The first call is done immediately, with added calls according to the staggering strategy. /// The timeout is passed to every individual call to [`ResolverExt::lookup_ipv6`]. - async fn staggered_lookup_ipv6( + async fn lookup_ipv6_staggered( &self, host: N, timeout: Duration, @@ -255,7 +255,7 @@ impl ResolverExt for DnsResolver { /// /// The first call is done immediately, with added calls according to the staggering strategy. /// The timeout is passed to every individual call to [`ResolverExt::lookup_ipv4_ipv6`]. - async fn staggered_lookup_ipv4_ipv6( + async fn lookup_ipv4_ipv6_staggered( &self, host: N, timeout: Duration, @@ -268,7 +268,7 @@ impl ResolverExt for DnsResolver { /// Looks up node info by DNS name in a staggered fashion. /// /// The first call is done immediately, with added calls according to the staggering strategy. - async fn staggered_lookup_by_name(&self, name: &str, delays_ms: &[u64]) -> Result { + async fn lookup_by_name_staggered(&self, name: &str, delays_ms: &[u64]) -> Result { let f = || self.lookup_by_name(name); stagger_call(f, delays_ms).await } @@ -276,7 +276,7 @@ impl ResolverExt for DnsResolver { /// Looks up node info by [`NodeId`] and origin domain name. /// /// The first call is done immediately, with added calls according to the staggering strategy. - async fn staggered_lookup_by_id( + async fn lookup_by_id_staggered( &self, node_id: &NodeId, origin: &str, @@ -370,7 +370,7 @@ pub(crate) mod tests { let _logging = iroh_test::logging::setup(); let resolver = default_resolver(); let res: Vec<_> = resolver - .staggered_lookup_ipv4_ipv6(NA_RELAY_HOSTNAME, TIMEOUT, STAGGERING_DELAYS) + .lookup_ipv4_ipv6_staggered(NA_RELAY_HOSTNAME, TIMEOUT, STAGGERING_DELAYS) .await .unwrap() .collect(); diff --git a/iroh-net/src/netcheck/reportgen.rs b/iroh-net/src/netcheck/reportgen.rs index 227440aaf6..665ea66e54 100644 --- a/iroh-net/src/netcheck/reportgen.rs +++ b/iroh-net/src/netcheck/reportgen.rs @@ -949,7 +949,7 @@ async fn get_relay_addr( Some(url::Host::Domain(hostname)) => { debug!(?proto, %hostname, "Performing DNS A lookup for relay addr"); match dns_resolver - .staggered_lookup_ipv4(hostname, DNS_TIMEOUT, DNS_STAGGERING_MS) + .lookup_ipv4_staggered(hostname, DNS_TIMEOUT, DNS_STAGGERING_MS) .await { Ok(mut addrs) => addrs @@ -969,7 +969,7 @@ async fn get_relay_addr( Some(url::Host::Domain(hostname)) => { debug!(?proto, %hostname, "Performing DNS AAAA lookup for relay addr"); match dns_resolver - .staggered_lookup_ipv6(hostname, DNS_TIMEOUT, DNS_STAGGERING_MS) + .lookup_ipv6_staggered(hostname, DNS_TIMEOUT, DNS_STAGGERING_MS) .await { Ok(mut addrs) => addrs From 03d9690e675426482f56998261398b1d76f379bb Mon Sep 17 00:00:00 2001 From: Diva M Date: Tue, 21 May 2024 10:23:24 -0500 Subject: [PATCH 12/14] further unify the dns api by mentioning the trait and the submodule docs --- iroh-net/src/dns.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/iroh-net/src/dns.rs b/iroh-net/src/dns.rs index fc146c4867..49a8a29870 100644 --- a/iroh-net/src/dns.rs +++ b/iroh-net/src/dns.rs @@ -1,5 +1,9 @@ //! This module exports a DNS resolver, which is also the default resolver used in the //! [`crate::Endpoint`] if no custom resolver is configured. +//! +//! It also exports [`ResolverExt`]: A extension trait over [`DnsResolver`] to perform DNS queries +//! by ipv4, ipv6, name and node_id. See the [`node_info`] module documentation for details on how +//! iroh node records are structured. use std::fmt::Write; use std::net::{IpAddr, Ipv6Addr}; From d78c2870c4df2d0d5ad81269e44c340e8e27776d Mon Sep 17 00:00:00 2001 From: Diva M Date: Wed, 22 May 2024 11:12:40 -0500 Subject: [PATCH 13/14] clarify timeouts a bit more --- iroh-net/src/dns.rs | 55 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/iroh-net/src/dns.rs b/iroh-net/src/dns.rs index 49a8a29870..81a09d7153 100644 --- a/iroh-net/src/dns.rs +++ b/iroh-net/src/dns.rs @@ -117,7 +117,10 @@ pub trait ResolverExt { /// Perform an ipv4 lookup with a timeout in a staggered fashion. /// - /// The first call is done immediately, with added calls according to the staggering strategy. + /// From the moment this function is called, each lookup is scheduled after the delays in + /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// at T+0ms, T+200ms and T+300ms. The `timeout` is applied to each call individually. The + /// result of the first successful call is returned, or a summary of all errors otherwise. fn lookup_ipv4_staggered( &self, host: N, @@ -127,7 +130,10 @@ pub trait ResolverExt { /// Perform an ipv6 lookup with a timeout in a staggered fashion. /// - /// The first call is done immediately, with added calls according to the staggering strategy. + /// From the moment this function is called, each lookup is scheduled after the delays in + /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// at T+0ms, T+200ms and T+300ms. The `timeout` is applied to each call individually. The + /// result of the first successful call is returned, or a summary of all errors otherwise. fn lookup_ipv6_staggered( &self, host: N, @@ -137,7 +143,11 @@ pub trait ResolverExt { /// Race an ipv4 and ipv6 lookup with a timeout in a staggered fashion. /// - /// The first call is done immediately, with added calls according to the staggering strategy. + /// From the moment this function is called, each lookup is scheduled after the delays in + /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// at T+0ms, T+200ms and T+300ms. The `timeout` is applied as stated in + /// [`Self::lookup_ipv4_ipv6`]. The result of the first successful call is returned, or a + /// summary of all errors otherwise. fn lookup_ipv4_ipv6_staggered( &self, host: N, @@ -147,7 +157,10 @@ pub trait ResolverExt { /// Looks up node info by DNS name in a staggered fashion. /// - /// The first call is done immediately, with added calls according to the staggering strategy. + /// From the moment this function is called, each lookup is scheduled after the delays in + /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// at T+0ms, T+200ms and T+300ms. The result of the first successful call is returned, or a + /// summary of all errors otherwise. fn lookup_by_name_staggered( &self, name: &str, @@ -156,7 +169,10 @@ pub trait ResolverExt { /// Looks up node info by [`NodeId`] and origin domain name. /// - /// The first call is done immediately, with added calls according to the staggering strategy. + /// From the moment this function is called, each lookup is scheduled after the delays in + /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// at T+0ms, T+200ms and T+300ms. The result of the first successful call is returned, or a + /// summary of all errors otherwise. fn lookup_by_id_staggered( &self, node_id: &NodeId, @@ -229,8 +245,10 @@ impl ResolverExt for DnsResolver { /// Perform an ipv4 lookup with a timeout in a staggered fashion. /// - /// The first call is done immediately, with added calls according to the staggering strategy. - /// The timeout is passed to every individual call to [`ResolverExt::lookup_ipv4`]. + /// From the moment this function is called, each lookup is scheduled after the delays in + /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// at T+0ms, T+200ms and T+300ms. The `timeout` is applied to each call individually. The + /// result of the first successful call is returned, or a summary of all errors otherwise. async fn lookup_ipv4_staggered( &self, host: N, @@ -243,8 +261,10 @@ impl ResolverExt for DnsResolver { /// Perform an ipv6 lookup with a timeout in a staggered fashion. /// - /// The first call is done immediately, with added calls according to the staggering strategy. - /// The timeout is passed to every individual call to [`ResolverExt::lookup_ipv6`]. + /// From the moment this function is called, each lookup is scheduled after the delays in + /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// at T+0ms, T+200ms and T+300ms. The `timeout` is applied to each call individually. The + /// result of the first successful call is returned, or a summary of all errors otherwise. async fn lookup_ipv6_staggered( &self, host: N, @@ -257,8 +277,11 @@ impl ResolverExt for DnsResolver { /// Race an ipv4 and ipv6 lookup with a timeout in a staggered fashion. /// - /// The first call is done immediately, with added calls according to the staggering strategy. - /// The timeout is passed to every individual call to [`ResolverExt::lookup_ipv4_ipv6`]. + /// From the moment this function is called, each lookup is scheduled after the delays in + /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// at T+0ms, T+200ms and T+300ms. The `timeout` is applied as stated in + /// [`Self::lookup_ipv4_ipv6`]. The result of the first successful call is returned, or a + /// summary of all errors otherwise. async fn lookup_ipv4_ipv6_staggered( &self, host: N, @@ -271,7 +294,10 @@ impl ResolverExt for DnsResolver { /// Looks up node info by DNS name in a staggered fashion. /// - /// The first call is done immediately, with added calls according to the staggering strategy. + /// From the moment this function is called, each lookup is scheduled after the delays in + /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// at T+0ms, T+200ms and T+300ms. The result of the first successful call is returned, or a + /// summary of all errors otherwise. async fn lookup_by_name_staggered(&self, name: &str, delays_ms: &[u64]) -> Result { let f = || self.lookup_by_name(name); stagger_call(f, delays_ms).await @@ -279,7 +305,10 @@ impl ResolverExt for DnsResolver { /// Looks up node info by [`NodeId`] and origin domain name. /// - /// The first call is done immediately, with added calls according to the staggering strategy. + /// From the moment this function is called, each lookup is scheduled after the delays in + /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// at T+0ms, T+200ms and T+300ms. The result of the first successful call is returned, or a + /// summary of all errors otherwise. async fn lookup_by_id_staggered( &self, node_id: &NodeId, From f21801c1b94914d0e2780fc65ac6e756d6196485 Mon Sep 17 00:00:00 2001 From: Diva M Date: Wed, 22 May 2024 11:15:50 -0500 Subject: [PATCH 14/14] fix docs --- iroh-net/src/dns.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/iroh-net/src/dns.rs b/iroh-net/src/dns.rs index 81a09d7153..1ac64c2f7f 100644 --- a/iroh-net/src/dns.rs +++ b/iroh-net/src/dns.rs @@ -118,7 +118,7 @@ pub trait ResolverExt { /// Perform an ipv4 lookup with a timeout in a staggered fashion. /// /// From the moment this function is called, each lookup is scheduled after the delays in - /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// `delays_ms` with the first call being done immediately. `[200ms, 300ms]` results in calls /// at T+0ms, T+200ms and T+300ms. The `timeout` is applied to each call individually. The /// result of the first successful call is returned, or a summary of all errors otherwise. fn lookup_ipv4_staggered( @@ -131,7 +131,7 @@ pub trait ResolverExt { /// Perform an ipv6 lookup with a timeout in a staggered fashion. /// /// From the moment this function is called, each lookup is scheduled after the delays in - /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// `delays_ms` with the first call being done immediately. `[200ms, 300ms]` results in calls /// at T+0ms, T+200ms and T+300ms. The `timeout` is applied to each call individually. The /// result of the first successful call is returned, or a summary of all errors otherwise. fn lookup_ipv6_staggered( @@ -144,7 +144,7 @@ pub trait ResolverExt { /// Race an ipv4 and ipv6 lookup with a timeout in a staggered fashion. /// /// From the moment this function is called, each lookup is scheduled after the delays in - /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// `delays_ms` with the first call being done immediately. `[200ms, 300ms]` results in calls /// at T+0ms, T+200ms and T+300ms. The `timeout` is applied as stated in /// [`Self::lookup_ipv4_ipv6`]. The result of the first successful call is returned, or a /// summary of all errors otherwise. @@ -158,7 +158,7 @@ pub trait ResolverExt { /// Looks up node info by DNS name in a staggered fashion. /// /// From the moment this function is called, each lookup is scheduled after the delays in - /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// `delays_ms` with the first call being done immediately. `[200ms, 300ms]` results in calls /// at T+0ms, T+200ms and T+300ms. The result of the first successful call is returned, or a /// summary of all errors otherwise. fn lookup_by_name_staggered( @@ -170,7 +170,7 @@ pub trait ResolverExt { /// Looks up node info by [`NodeId`] and origin domain name. /// /// From the moment this function is called, each lookup is scheduled after the delays in - /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// `delays_ms` with the first call being done immediately. `[200ms, 300ms]` results in calls /// at T+0ms, T+200ms and T+300ms. The result of the first successful call is returned, or a /// summary of all errors otherwise. fn lookup_by_id_staggered( @@ -246,7 +246,7 @@ impl ResolverExt for DnsResolver { /// Perform an ipv4 lookup with a timeout in a staggered fashion. /// /// From the moment this function is called, each lookup is scheduled after the delays in - /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// `delays_ms` with the first call being done immediately. `[200ms, 300ms]` results in calls /// at T+0ms, T+200ms and T+300ms. The `timeout` is applied to each call individually. The /// result of the first successful call is returned, or a summary of all errors otherwise. async fn lookup_ipv4_staggered( @@ -262,7 +262,7 @@ impl ResolverExt for DnsResolver { /// Perform an ipv6 lookup with a timeout in a staggered fashion. /// /// From the moment this function is called, each lookup is scheduled after the delays in - /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// `delays_ms` with the first call being done immediately. `[200ms, 300ms]` results in calls /// at T+0ms, T+200ms and T+300ms. The `timeout` is applied to each call individually. The /// result of the first successful call is returned, or a summary of all errors otherwise. async fn lookup_ipv6_staggered( @@ -278,7 +278,7 @@ impl ResolverExt for DnsResolver { /// Race an ipv4 and ipv6 lookup with a timeout in a staggered fashion. /// /// From the moment this function is called, each lookup is scheduled after the delays in - /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// `delays_ms` with the first call being done immediately. `[200ms, 300ms]` results in calls /// at T+0ms, T+200ms and T+300ms. The `timeout` is applied as stated in /// [`Self::lookup_ipv4_ipv6`]. The result of the first successful call is returned, or a /// summary of all errors otherwise. @@ -295,7 +295,7 @@ impl ResolverExt for DnsResolver { /// Looks up node info by DNS name in a staggered fashion. /// /// From the moment this function is called, each lookup is scheduled after the delays in - /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// `delays_ms` with the first call being done immediately. `[200ms, 300ms]` results in calls /// at T+0ms, T+200ms and T+300ms. The result of the first successful call is returned, or a /// summary of all errors otherwise. async fn lookup_by_name_staggered(&self, name: &str, delays_ms: &[u64]) -> Result { @@ -306,7 +306,7 @@ impl ResolverExt for DnsResolver { /// Looks up node info by [`NodeId`] and origin domain name. /// /// From the moment this function is called, each lookup is scheduled after the delays in - /// [`delays_ms`] with the first call being done immediately. `[200ms, 300ms]` results in calls + /// `delays_ms` with the first call being done immediately. `[200ms, 300ms]` results in calls /// at T+0ms, T+200ms and T+300ms. The result of the first successful call is returned, or a /// summary of all errors otherwise. async fn lookup_by_id_staggered(