From 7dfaea19fb26c57d2575e4edf877a2ae030a41ea Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Thu, 16 Oct 2025 22:19:40 +0200 Subject: [PATCH 1/9] feat!: transport generic EndpointAddr --- iroh-base/src/endpoint_addr.rs | 70 +++++++++++------- iroh-base/src/lib.rs | 6 +- iroh-base/src/ticket/endpoint.rs | 2 +- iroh-relay/src/endpoint_info.rs | 123 +++++++++++++++++-------------- 4 files changed, 115 insertions(+), 86 deletions(-) diff --git a/iroh-base/src/endpoint_addr.rs b/iroh-base/src/endpoint_addr.rs index f6c378d6248..ccaa98e2ac9 100644 --- a/iroh-base/src/endpoint_addr.rs +++ b/iroh-base/src/endpoint_addr.rs @@ -39,26 +39,33 @@ use crate::{EndpointId, PublicKey, RelayUrl}; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct EndpointAddr { /// The endpoint's identifier. - pub endpoint_id: EndpointId, - /// The endpoint's home relay url. - pub relay_url: Option, - /// Socket addresses where the peer might be reached directly. - pub direct_addresses: BTreeSet, + pub id: EndpointId, + /// The endpoint's addresses + pub addrs: BTreeSet, +} + +/// Available address types. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[non_exhaustive] +pub enum AddrType { + /// IP based addresses + Ip(SocketAddr), + /// Relays + Relay(RelayUrl), } impl EndpointAddr { /// Creates a new [`EndpointAddr`] with no `relay_url` and no `direct_addresses`. - pub fn new(endpoint_id: PublicKey) -> Self { + pub fn new(id: PublicKey) -> Self { EndpointAddr { - endpoint_id, - relay_url: None, - direct_addresses: Default::default(), + id, + addrs: Default::default(), } } /// Adds a relay url. pub fn with_relay_url(mut self, relay_url: RelayUrl) -> Self { - self.relay_url = Some(relay_url); + self.addrs.insert(AddrType::Relay(relay_url)); self } @@ -67,47 +74,56 @@ impl EndpointAddr { mut self, addresses: impl IntoIterator, ) -> Self { - self.direct_addresses = addresses.into_iter().collect(); + for addr in addresses.into_iter() { + self.addrs.insert(AddrType::Ip(addr)); + } self } /// Creates a new [`EndpointAddr`] from its parts. - pub fn from_parts( - endpoint_id: PublicKey, - relay_url: Option, - direct_addresses: impl IntoIterator, - ) -> Self { + pub fn from_parts(id: PublicKey, addrs: impl IntoIterator) -> Self { Self { - endpoint_id, - relay_url, - direct_addresses: direct_addresses.into_iter().collect(), + id, + addrs: addrs.into_iter().collect(), } } /// Returns true, if only a [`EndpointId`] is present. pub fn is_empty(&self) -> bool { - self.relay_url.is_none() && self.direct_addresses.is_empty() + self.addrs.is_empty() } /// Returns the direct addresses of this peer. pub fn direct_addresses(&self) -> impl Iterator { - self.direct_addresses.iter() + self.addrs.iter().filter_map(|addr| match addr { + AddrType::Ip(addr) => Some(addr), + _ => None, + }) } /// Returns the relay url of this peer. pub fn relay_url(&self) -> Option<&RelayUrl> { - self.relay_url.as_ref() + self.addrs + .iter() + .filter_map(|addr| match addr { + AddrType::Relay(url) => Some(url), + _ => None, + }) + .next() } } impl From<(PublicKey, Option, &[SocketAddr])> for EndpointAddr { fn from(value: (PublicKey, Option, &[SocketAddr])) -> Self { - let (endpoint_id, relay_url, direct_addresses_iter) = value; - EndpointAddr { - endpoint_id, - relay_url, - direct_addresses: direct_addresses_iter.iter().copied().collect(), + let (id, relay_url, direct_addresses_iter) = value; + let mut addrs = BTreeSet::new(); + if let Some(url) = relay_url { + addrs.insert(AddrType::Relay(url)); + } + for addr in direct_addresses_iter { + addrs.insert(AddrType::Ip(*addr)); } + EndpointAddr { id, addrs } } } diff --git a/iroh-base/src/lib.rs b/iroh-base/src/lib.rs index a4ebdb29a99..63a8f5b4ea9 100644 --- a/iroh-base/src/lib.rs +++ b/iroh-base/src/lib.rs @@ -4,8 +4,8 @@ #![cfg_attr(not(test), deny(clippy::unwrap_used))] // TODO: move to own crate -#[cfg(feature = "ticket")] -pub mod ticket; +//#[cfg(feature = "ticket")] +// b mod ticket; #[cfg(feature = "key")] mod endpoint_addr; @@ -15,7 +15,7 @@ mod key; mod relay_url; #[cfg(feature = "key")] -pub use self::endpoint_addr::EndpointAddr; +pub use self::endpoint_addr::{AddrType, EndpointAddr}; #[cfg(feature = "key")] pub use self::key::{EndpointId, KeyParsingError, PublicKey, SecretKey, Signature, SignatureError}; #[cfg(feature = "relay")] diff --git a/iroh-base/src/ticket/endpoint.rs b/iroh-base/src/ticket/endpoint.rs index 3c9347ffc9d..4ab285c663f 100644 --- a/iroh-base/src/ticket/endpoint.rs +++ b/iroh-base/src/ticket/endpoint.rs @@ -52,7 +52,7 @@ impl Ticket for EndpointTicket { fn to_bytes(&self) -> Vec { let data = TicketWireFormat::Variant0(Variant0NodeTicket { node: Variant0NodeAddr { - node_id: self.node.endpoint_id, + node_id: self.node.id, info: Variant0AddrInfo { relay_url: self.node.relay_url.clone(), direct_addresses: self.node.direct_addresses.clone(), diff --git a/iroh-relay/src/endpoint_info.rs b/iroh-relay/src/endpoint_info.rs index 1e6b2c59cdd..f97f58c3c1c 100644 --- a/iroh-relay/src/endpoint_info.rs +++ b/iroh-relay/src/endpoint_info.rs @@ -40,7 +40,7 @@ use std::{ str::{FromStr, Utf8Error}, }; -use iroh_base::{EndpointAddr, EndpointId, KeyParsingError, RelayUrl, SecretKey}; +use iroh_base::{AddrType, EndpointAddr, EndpointId, KeyParsingError, RelayUrl, SecretKey}; use nested_enum_utils::common_fields; use snafu::{Backtrace, ResultExt, Snafu}; use url::Url; @@ -126,33 +126,34 @@ impl EndpointIdExt for EndpointId { /// endpoint. See [`EndpointInfo`] for a struct that contains a [`EndpointId`] with associated [`EndpointData`]. #[derive(Debug, Clone, Default, Eq, PartialEq)] pub struct EndpointData { - /// URL of the home relay of this endpoint. - relay_url: Option, - /// Direct addresses where this endpoint can be reached. - direct_addresses: BTreeSet, + /// addresses where this endpoint can be reached. + addrs: BTreeSet, /// Optional user-defined [`UserData`] for this endpoint. user_data: Option, } impl EndpointData { /// Creates a new [`EndpointData`] with a relay URL and a set of direct addresses. - pub fn new(relay_url: Option, direct_addresses: BTreeSet) -> Self { + pub fn new(addrs: impl IntoIterator) -> Self { Self { - relay_url, - direct_addresses, + addrs: addrs.into_iter().collect(), user_data: None, } } /// Sets the relay URL and returns the updated endpoint data. pub fn with_relay_url(mut self, relay_url: Option) -> Self { - self.relay_url = relay_url; + if let Some(url) = relay_url { + self.addrs.insert(AddrType::Relay(url)); + } self } /// Sets the direct addresses and returns the updated endpoint data. - pub fn with_direct_addresses(mut self, direct_addresses: BTreeSet) -> Self { - self.direct_addresses = direct_addresses; + pub fn with_direct_addresses(mut self, addresses: BTreeSet) -> Self { + for addr in addresses.into_iter() { + self.addrs.insert(AddrType::Ip(addr)); + } self } @@ -164,7 +165,13 @@ impl EndpointData { /// Returns the relay URL of the endpoint. pub fn relay_url(&self) -> Option<&RelayUrl> { - self.relay_url.as_ref() + self.addrs + .iter() + .filter_map(|addr| match addr { + AddrType::Relay(url) => Some(url), + _ => None, + }) + .next() } /// Returns the optional user-defined data of the endpoint. @@ -173,23 +180,29 @@ impl EndpointData { } /// Returns the direct addresses of the endpoint. - pub fn direct_addresses(&self) -> &BTreeSet { - &self.direct_addresses + pub fn direct_addresses(&self) -> impl Iterator { + self.addrs.iter().filter_map(|addr| match addr { + AddrType::Ip(addr) => Some(addr), + _ => None, + }) } /// Removes all direct addresses from the endpoint data. pub fn clear_direct_addresses(&mut self) { - self.direct_addresses = Default::default(); + self.addrs.retain(|addr| !matches!(addr, AddrType::Ip(_))); } - /// Adds direct addresses to the endpoint data. - pub fn add_direct_addresses(&mut self, addrs: impl IntoIterator) { - self.direct_addresses.extend(addrs) + /// Removes all direct addresses from the endpoint data. + pub fn clear_relay_urls(&mut self) { + self.addrs + .retain(|addr| !matches!(addr, AddrType::Relay(_))); } - /// Sets the relay URL of the endpoint data. - pub fn set_relay_url(&mut self, relay_url: Option) { - self.relay_url = relay_url + /// Add addresses to the endpoint data. + pub fn add_addrs(&mut self, addrs: impl IntoIterator) { + for addr in addrs.into_iter() { + self.addrs.insert(addr); + } } /// Sets the user-defined data of the endpoint data. @@ -201,8 +214,7 @@ impl EndpointData { impl From for EndpointData { fn from(endpoint_addr: EndpointAddr) -> Self { Self { - relay_url: endpoint_addr.relay_url, - direct_addresses: endpoint_addr.direct_addresses, + addrs: endpoint_addr.addrs, user_data: None, } } @@ -288,29 +300,29 @@ impl From<&TxtAttrs> for EndpointInfo { fn from(attrs: &TxtAttrs) -> Self { let endpoint_id = attrs.endpoint_id(); let attrs = attrs.attrs(); - let relay_url = attrs + let relay_urls = attrs .get(&IrohAttr::Relay) .into_iter() .flatten() - .next() - .and_then(|s| Url::parse(s).ok()); + .filter_map(|s| Url::parse(s).ok()) + .map(|url| AddrType::Relay(url.into())); let direct_addresses = attrs .get(&IrohAttr::Addr) .into_iter() .flatten() .filter_map(|s| SocketAddr::from_str(s).ok()) - .collect(); + .map(AddrType::Ip); + let user_data = attrs .get(&IrohAttr::UserData) .into_iter() .flatten() .next() .and_then(|s| UserData::from_str(s).ok()); - let data = EndpointData { - relay_url: relay_url.map(Into::into), - direct_addresses, - user_data, - }; + let mut data = EndpointData::default(); + data.set_user_data(user_data); + data.add_addrs(relay_urls.chain(direct_addresses)); + Self { endpoint_id, data } } } @@ -323,9 +335,9 @@ impl From for EndpointAddr { impl From for EndpointInfo { fn from(addr: EndpointAddr) -> Self { - Self::new(addr.endpoint_id) - .with_relay_url(addr.relay_url) - .with_direct_addresses(addr.direct_addresses) + let mut info = Self::new(addr.id); + info.add_addrs(addr.addrs.into_iter()); + info } } @@ -361,18 +373,17 @@ impl EndpointInfo { /// Converts into a [`EndpointAddr`] by cloning the needed fields. pub fn to_endpoint_addr(&self) -> EndpointAddr { EndpointAddr { - endpoint_id: self.endpoint_id, - relay_url: self.data.relay_url.clone(), - direct_addresses: self.data.direct_addresses.clone(), + id: self.endpoint_id, + addrs: self.addrs.clone(), } } /// Converts into a [`EndpointAddr`] without cloning. pub fn into_endpoint_addr(self) -> EndpointAddr { + let Self { endpoint_id, data } = self; EndpointAddr { - endpoint_id: self.endpoint_id, - relay_url: self.data.relay_url, - direct_addresses: self.data.direct_addresses, + id: endpoint_id, + addrs: data.addrs, } } @@ -504,12 +515,14 @@ pub(crate) struct TxtAttrs { impl From<&EndpointInfo> for TxtAttrs { fn from(info: &EndpointInfo) -> Self { let mut attrs = vec![]; - if let Some(relay_url) = &info.data.relay_url { - attrs.push((IrohAttr::Relay, relay_url.to_string())); - } - for addr in &info.data.direct_addresses { - attrs.push((IrohAttr::Addr, addr.to_string())); + for addr in &info.data.addrs { + match addr { + AddrType::Relay(relay_url) => attrs.push((IrohAttr::Relay, relay_url.to_string())), + AddrType::Ip(addr) => attrs.push((IrohAttr::Addr, addr.to_string())), + _ => {} + } } + if let Some(user_data) = &info.data.user_data { attrs.push((IrohAttr::UserData, user_data.to_string())); } @@ -655,7 +668,7 @@ mod tests { }, }, }; - use iroh_base::{EndpointId, SecretKey}; + use iroh_base::{AddrType, EndpointId, SecretKey}; use n0_snafu::{Result, ResultExt}; use super::{EndpointData, EndpointIdExt, EndpointInfo}; @@ -663,10 +676,10 @@ mod tests { #[test] fn txt_attr_roundtrip() { - let endpoint_data = EndpointData::new( - Some("https://example.com".parse().unwrap()), - ["127.0.0.1:1234".parse().unwrap()].into_iter().collect(), - ) + let endpoint_data = EndpointData::new([ + AddrType::Relay("https://example.com".parse().unwrap()), + AddrType::Ip("127.0.0.1:1234".parse().unwrap()), + ]) .with_user_data(Some("foobar".parse().unwrap())); let endpoint_id = "vpnk377obfvzlipnsfbqba7ywkkenc4xlpmovt5tsfujoa75zqia" .parse() @@ -681,10 +694,10 @@ mod tests { fn signed_packet_roundtrip() { let secret_key = SecretKey::from_str("vpnk377obfvzlipnsfbqba7ywkkenc4xlpmovt5tsfujoa75zqia").unwrap(); - let endpoint_data = EndpointData::new( - Some("https://example.com".parse().unwrap()), - ["127.0.0.1:1234".parse().unwrap()].into_iter().collect(), - ) + let endpoint_data = EndpointData::new([ + AddrType::Relay("https://example.com".parse().unwrap()), + AddrType::Ip("127.0.0.1:1234".parse().unwrap()), + ]) .with_user_data(Some("foobar".parse().unwrap())); let expected = EndpointInfo::from_parts(secret_key.public(), endpoint_data); let packet = expected.to_pkarr_signed_packet(&secret_key, 30).unwrap(); From 516b9486d7363bcde285012793006e149fb1ee4c Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 17 Oct 2025 11:10:12 +0200 Subject: [PATCH 2/9] add test to check stability against new types --- iroh-base/src/endpoint_addr.rs | 48 ++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/iroh-base/src/endpoint_addr.rs b/iroh-base/src/endpoint_addr.rs index ccaa98e2ac9..fd6aedf5c32 100644 --- a/iroh-base/src/endpoint_addr.rs +++ b/iroh-base/src/endpoint_addr.rs @@ -132,3 +132,51 @@ impl From for EndpointAddr { EndpointAddr::new(endpoint_id) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] + #[non_exhaustive] + enum NewAddrType { + /// IP based addresses + Ip(SocketAddr), + /// Relays + Relay(RelayUrl), + /// New addr type for testing + Cool(u16), + } + + #[test] + fn test_roundtrip_new_addr_type() { + let old = vec![ + AddrType::Ip("127.0.0.1:9".parse().unwrap()), + AddrType::Relay("https://example.com".parse().unwrap()), + ]; + let old_ser = postcard::to_stdvec(&old).unwrap(); + let old_back: Vec = postcard::from_bytes(&old_ser).unwrap(); + assert_eq!(old, old_back); + + let new = vec![ + NewAddrType::Ip("127.0.0.1:9".parse().unwrap()), + NewAddrType::Relay("https://example.com".parse().unwrap()), + NewAddrType::Cool(4), + ]; + let new_ser = postcard::to_stdvec(&new).unwrap(); + let new_back: Vec = postcard::from_bytes(&new_ser).unwrap(); + + assert_eq!(new, new_back); + + // serialize old into new + let old_new_back: Vec = postcard::from_bytes(&old_ser).unwrap(); + + assert_eq!( + old_new_back, + vec![ + NewAddrType::Ip("127.0.0.1:9".parse().unwrap()), + NewAddrType::Relay("https://example.com".parse().unwrap()), + ] + ); + } +} From 5c6d271c676c58cc2e33eccc54aa95eacea75a14 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 17 Oct 2025 11:22:51 +0200 Subject: [PATCH 3/9] start naming improvements --- iroh-base/src/endpoint_addr.rs | 15 +++---- iroh-dns-server/examples/resolve.rs | 2 +- iroh-relay/src/endpoint_info.rs | 19 ++++----- iroh/examples/0rtt.rs | 2 +- iroh/examples/connect-unreliable.rs | 2 +- iroh/examples/connect.rs | 2 +- iroh/examples/listen-unreliable.rs | 2 +- iroh/examples/listen.rs | 2 +- iroh/examples/transfer.rs | 4 +- iroh/src/discovery/mdns.rs | 2 +- iroh/src/discovery/pkarr.rs | 2 +- iroh/src/discovery/pkarr/dht.rs | 2 +- iroh/src/discovery/static_provider.rs | 6 ++- iroh/src/endpoint.rs | 39 ++++++++++--------- iroh/src/magicsock.rs | 8 ++-- iroh/src/magicsock/endpoint_map.rs | 10 ++--- .../magicsock/endpoint_map/endpoint_state.rs | 15 ++++--- 17 files changed, 67 insertions(+), 67 deletions(-) diff --git a/iroh-base/src/endpoint_addr.rs b/iroh-base/src/endpoint_addr.rs index fd6aedf5c32..6631acaf5e0 100644 --- a/iroh-base/src/endpoint_addr.rs +++ b/iroh-base/src/endpoint_addr.rs @@ -94,7 +94,7 @@ impl EndpointAddr { } /// Returns the direct addresses of this peer. - pub fn direct_addresses(&self) -> impl Iterator { + pub fn ip_addresses(&self) -> impl Iterator { self.addrs.iter().filter_map(|addr| match addr { AddrType::Ip(addr) => Some(addr), _ => None, @@ -102,14 +102,11 @@ impl EndpointAddr { } /// Returns the relay url of this peer. - pub fn relay_url(&self) -> Option<&RelayUrl> { - self.addrs - .iter() - .filter_map(|addr| match addr { - AddrType::Relay(url) => Some(url), - _ => None, - }) - .next() + pub fn relay_urls(&self) -> impl Iterator { + self.addrs.iter().filter_map(|addr| match addr { + AddrType::Relay(url) => Some(url), + _ => None, + }) } } diff --git a/iroh-dns-server/examples/resolve.rs b/iroh-dns-server/examples/resolve.rs index 4155256a51b..18b622f3cef 100644 --- a/iroh-dns-server/examples/resolve.rs +++ b/iroh-dns-server/examples/resolve.rs @@ -82,7 +82,7 @@ async fn main() -> Result<()> { if let Some(url) = resolved.relay_url() { println!(" relay={url}") } - for addr in resolved.direct_addresses() { + for addr in resolved.ip_addresses() { println!(" addr={addr}") } if let Some(user_data) = resolved.user_data() { diff --git a/iroh-relay/src/endpoint_info.rs b/iroh-relay/src/endpoint_info.rs index f97f58c3c1c..113476337e9 100644 --- a/iroh-relay/src/endpoint_info.rs +++ b/iroh-relay/src/endpoint_info.rs @@ -150,7 +150,7 @@ impl EndpointData { } /// Sets the direct addresses and returns the updated endpoint data. - pub fn with_direct_addresses(mut self, addresses: BTreeSet) -> Self { + pub fn with_ip_addresses(mut self, addresses: BTreeSet) -> Self { for addr in addresses.into_iter() { self.addrs.insert(AddrType::Ip(addr)); } @@ -164,14 +164,11 @@ impl EndpointData { } /// Returns the relay URL of the endpoint. - pub fn relay_url(&self) -> Option<&RelayUrl> { - self.addrs - .iter() - .filter_map(|addr| match addr { - AddrType::Relay(url) => Some(url), - _ => None, - }) - .next() + pub fn relay_urls(&self) -> impl Iterator { + self.addrs.iter().filter_map(|addr| match addr { + AddrType::Relay(url) => Some(url), + _ => None, + }) } /// Returns the optional user-defined data of the endpoint. @@ -180,7 +177,7 @@ impl EndpointData { } /// Returns the direct addresses of the endpoint. - pub fn direct_addresses(&self) -> impl Iterator { + pub fn ip_addresses(&self) -> impl Iterator { self.addrs.iter().filter_map(|addr| match addr { AddrType::Ip(addr) => Some(addr), _ => None, @@ -360,7 +357,7 @@ impl EndpointInfo { /// Sets the direct addresses and returns the updated endpoint info. pub fn with_direct_addresses(mut self, direct_addresses: BTreeSet) -> Self { - self.data = self.data.with_direct_addresses(direct_addresses); + self.data = self.data.with_ip_addresses(direct_addresses); self } diff --git a/iroh/examples/0rtt.rs b/iroh/examples/0rtt.rs index 56b71d2af23..7da7be4e9a4 100644 --- a/iroh/examples/0rtt.rs +++ b/iroh/examples/0rtt.rs @@ -144,7 +144,7 @@ async fn accept(_args: Args) -> n0_snafu::Result<()> { let Some(addr) = addrs.next().await else { snafu::whatever!("Address stream closed"); }; - if !addr.direct_addresses.is_empty() { + if !addr.ip_addresses.is_empty() { break addr; } }; diff --git a/iroh/examples/connect-unreliable.rs b/iroh/examples/connect-unreliable.rs index e4b30accf21..dcaa94b6044 100644 --- a/iroh/examples/connect-unreliable.rs +++ b/iroh/examples/connect-unreliable.rs @@ -59,7 +59,7 @@ async fn main() -> n0_snafu::Result<()> { println!("endpoint id: {me}"); println!("endpoint listening addresses:"); endpoint_addr - .direct_addresses + .ip_addresses .iter() .for_each(|addr| println!("\t{addr}")); let relay_url = endpoint_addr diff --git a/iroh/examples/connect.rs b/iroh/examples/connect.rs index 960d9edd923..53ed24c9ac1 100644 --- a/iroh/examples/connect.rs +++ b/iroh/examples/connect.rs @@ -58,7 +58,7 @@ async fn main() -> Result<()> { let me = endpoint.id(); println!("endpoint id: {me}"); println!("endpoint listening addresses:"); - for addr in endpoint_addr.direct_addresses() { + for addr in endpoint_addr.ip_addresses() { println!("\t{addr}") } diff --git a/iroh/examples/listen-unreliable.rs b/iroh/examples/listen-unreliable.rs index 60274480dc3..bf41744fed1 100644 --- a/iroh/examples/listen-unreliable.rs +++ b/iroh/examples/listen-unreliable.rs @@ -41,7 +41,7 @@ async fn main() -> Result<()> { let endpoint_addr = endpoint.addr(); let local_addrs = endpoint_addr - .direct_addresses + .ip_addresses .into_iter() .map(|addr| { let addr = addr.to_string(); diff --git a/iroh/examples/listen.rs b/iroh/examples/listen.rs index af9ed0e75e4..63cec84e811 100644 --- a/iroh/examples/listen.rs +++ b/iroh/examples/listen.rs @@ -43,7 +43,7 @@ async fn main() -> n0_snafu::Result<()> { let endpoint_addr = endpoint.addr(); let local_addrs = endpoint_addr - .direct_addresses + .ip_addresses .iter() .map(|addr| { let addr = addr.to_string(); diff --git a/iroh/examples/transfer.rs b/iroh/examples/transfer.rs index c26d4c0d7fe..330c23435c5 100644 --- a/iroh/examples/transfer.rs +++ b/iroh/examples/transfer.rs @@ -288,7 +288,7 @@ impl EndpointArgs { let endpoint_addr = endpoint.addr(); println!("Our direct addresses:"); - for addr in &endpoint_addr.direct_addresses { + for addr in &endpoint_addr.ip_addresses { println!("\t{addr}"); } @@ -311,7 +311,7 @@ async fn provide(endpoint: Endpoint, size: u64) -> Result<()> { println!("Ticket with our home relay and direct addresses:\n{ticket}\n",); let mut endpoint_addr = endpoint.addr(); - endpoint_addr.direct_addresses = Default::default(); + endpoint_addr.ip_addresses = Default::default(); let ticket = EndpointTicket::new(endpoint_addr); println!("Ticket with our home relay but no direct addresses:\n{ticket}\n",); diff --git a/iroh/src/discovery/mdns.rs b/iroh/src/discovery/mdns.rs index f5a30fe0bbd..ff052ab8ad0 100644 --- a/iroh/src/discovery/mdns.rs +++ b/iroh/src/discovery/mdns.rs @@ -279,7 +279,7 @@ impl MdnsDiscovery { tracing::trace!(?data, "MdnsDiscovery address changed"); discovery.remove_all(); let addrs = - MdnsDiscovery::socketaddrs_to_addrs(data.direct_addresses()); + MdnsDiscovery::socketaddrs_to_addrs(data.ip_addresses()); for addr in addrs { discovery.add(addr.0, addr.1) } diff --git a/iroh/src/discovery/pkarr.rs b/iroh/src/discovery/pkarr.rs index 1e1f0e54055..ba6568e7645 100644 --- a/iroh/src/discovery/pkarr.rs +++ b/iroh/src/discovery/pkarr.rs @@ -315,7 +315,7 @@ impl PkarrPublisher { /// This is a nonblocking function, the actual update is performed in the background. pub fn update_endpoint_data(&self, data: &EndpointData) { let mut data = data.clone(); - if data.relay_url().is_some() { + if data.relay_urls().next().is_some() { // If relay url is set: only publish relay url, and no direct addrs. data.clear_direct_addresses(); } diff --git a/iroh/src/discovery/pkarr/dht.rs b/iroh/src/discovery/pkarr/dht.rs index c00b1172422..8080071444a 100644 --- a/iroh/src/discovery/pkarr/dht.rs +++ b/iroh/src/discovery/pkarr/dht.rs @@ -292,7 +292,7 @@ impl Discovery for DhtDiscovery { tracing::debug!("no keypair set, not publishing"); return; }; - if data.relay_url().is_none() && data.direct_addresses().is_empty() { + if data.relay_url().is_none() && data.ip_addresses().is_empty() { tracing::debug!("no relay url or direct addresses in endpoint data, not publishing"); return; } diff --git a/iroh/src/discovery/static_provider.rs b/iroh/src/discovery/static_provider.rs index 4fee934b4a3..636b973651c 100644 --- a/iroh/src/discovery/static_provider.rs +++ b/iroh/src/discovery/static_provider.rs @@ -176,8 +176,10 @@ impl StaticProvider { let existing = entry.get_mut(); existing .data - .add_direct_addresses(data.direct_addresses().iter().copied()); - existing.data.set_relay_url(data.relay_url().cloned()); + .add_direct_addresses(data.ip_addresses().copied()); + existing + .data + .set_relay_url(data.relay_urls().next().cloned()); existing.data.set_user_data(data.user_data().cloned()); existing.last_updated = last_updated; } diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 77cd506216c..693eb4e06ce 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -645,7 +645,7 @@ impl Endpoint { alpn: &[u8], ) -> Result { let endpoint_addr = endpoint_addr.into(); - let remote = endpoint_addr.endpoint_id; + let remote = endpoint_addr.id; let connecting = self .connect_with_opts(endpoint_addr, alpn, Default::default()) .await?; @@ -688,18 +688,18 @@ impl Endpoint { let endpoint_addr: EndpointAddr = endpoint_addr.into(); tracing::Span::current().record( "remote", - tracing::field::display(endpoint_addr.endpoint_id.fmt_short()), + tracing::field::display(endpoint_addr.id.fmt_short()), ); // Connecting to ourselves is not supported. - ensure!(endpoint_addr.endpoint_id != self.id(), SelfConnectSnafu); + ensure!(endpoint_addr.id != self.id(), SelfConnectSnafu); if !endpoint_addr.is_empty() { self.add_endpoint_addr(endpoint_addr.clone(), Source::App)?; } - let endpoint_id = endpoint_addr.endpoint_id; - let direct_addresses = endpoint_addr.direct_addresses.clone(); - let relay_url = endpoint_addr.relay_url.clone(); + let endpoint_id = endpoint_addr.id; + let ip_addresses: Vec<_> = endpoint_addr.ip_addresses().cloned().collect(); + let relay_url = endpoint_addr.relay_urls().next().cloned(); // Get the mapped IPv6 address from the magic socket. Quinn will connect to this // address. Start discovery for this endpoint if it's enabled and we have no valid or @@ -719,7 +719,7 @@ impl Endpoint { debug!( ?mapped_addr, - ?direct_addresses, + ?ip_addresses, ?relay_url, "Attempting connection..." ); @@ -799,7 +799,7 @@ impl Endpoint { source: Source, ) -> Result<(), AddEndpointAddrError> { // Connecting to ourselves is not supported. - snafu::ensure!(endpoint_addr.endpoint_id != self.id(), OwnAddressSnafu); + snafu::ensure!(endpoint_addr.id != self.id(), OwnAddressSnafu); self.msock.add_endpoint_addr(endpoint_addr, source) } @@ -876,13 +876,17 @@ impl Endpoint { watch_addrs .or(watch_relay) - .map(move |(addrs, mut relays)| { + .map(move |(addrs, relays)| { + use iroh_base::AddrType; + debug_assert!(!addrs.is_empty(), "direct addresses must never be empty"); EndpointAddr::from_parts( endpoint_id, - relays.pop(), - addrs.into_iter().map(|x| x.addr), + relays + .into_iter() + .map(AddrType::Relay) + .chain(addrs.into_iter().map(|x| AddrType::Ip(x.addr))), ) }) .expect("watchable is alive - cannot be disconnected yet") @@ -1263,7 +1267,7 @@ impl Endpoint { &self, endpoint_addr: EndpointAddr, ) -> Result<(EndpointIdMappedAddr, Option), GetMappingAddressError> { - let endpoint_id = endpoint_addr.endpoint_id; + let endpoint_id = endpoint_addr.id; // Only return a mapped addr if we have some way of dialing this endpoint, in other // words, we have either a relay URL or at least one direct address. @@ -2456,7 +2460,7 @@ mod tests { println!("round1: {:?}", addr); // remove direct addrs to force relay usage - addr.direct_addresses.clear(); + addr.ip_addresses.clear(); let conn = client.connect(addr, TEST_ALPN).await?; let (mut send, mut recv) = conn.open_bi().await.e()?; @@ -2505,7 +2509,7 @@ mod tests { assert_eq!(addr.relay_url, Some(new_relay_url)); // remove direct addrs to force relay usage - addr.direct_addresses.clear(); + addr.ip_addresses.clear(); let conn = client.connect(addr, TEST_ALPN).await?; let (mut send, mut recv) = conn.open_bi().await.e()?; @@ -2719,7 +2723,7 @@ mod tests { .bind() .await?; - assert!(!ep.addr().direct_addresses.is_empty()); + assert!(!ep.addr().ip_addresses.is_empty()); Ok(()) } @@ -3186,10 +3190,7 @@ mod tests { .iter() .map(|(_, addr)| addr.clone()) .collect::>(); - let ids = addrs - .iter() - .map(|addr| addr.endpoint_id) - .collect::>(); + let ids = addrs.iter().map(|addr| addr.id).collect::>(); let discovery = StaticProvider::from_endpoint_info(addrs); let endpoint = Endpoint::empty_builder(RelayMode::Disabled) .discovery(discovery) diff --git a/iroh/src/magicsock.rs b/iroh/src/magicsock.rs index 07a8618478b..72d3653a2df 100644 --- a/iroh/src/magicsock.rs +++ b/iroh/src/magicsock.rs @@ -410,8 +410,8 @@ impl MagicSock { ) -> Result<(), AddEndpointAddrError> { let mut pruned: usize = 0; for my_addr in self.direct_addrs.sockaddrs() { - if addr.direct_addresses.remove(&my_addr) { - warn!( endpoint_id=%addr.endpoint_id.fmt_short(), %my_addr, %source, "not adding our addr for endpoint"); + if addr.ip_addresses.remove(&my_addr) { + warn!( endpoint_id=%addr.id.fmt_short(), %my_addr, %source, "not adding our addr for endpoint"); pruned += 1; } } @@ -2687,8 +2687,8 @@ mod tests { let me = m.endpoint.id().fmt_short(); let mut stream = m.endpoint.watch_addr().stream(); while let Some(addr) = stream.next().await { - info!(%me, "conn{} endpoints update: {:?}", my_idx + 1, addr.direct_addresses); - update_direct_addrs(&stacks, my_idx, addr.direct_addresses); + info!(%me, "conn{} endpoints update: {:?}", my_idx + 1, addr.ip_addresses().collect::>()); + update_direct_addrs(&stacks, my_idx, addr.ip_addresses().copied().collect()); } }); } diff --git a/iroh/src/magicsock/endpoint_map.rs b/iroh/src/magicsock/endpoint_map.rs index 7c88c71731f..c56a7553db1 100644 --- a/iroh/src/magicsock/endpoint_map.rs +++ b/iroh/src/magicsock/endpoint_map.rs @@ -367,7 +367,7 @@ impl EndpointMapInner { } /// Add the contact information for an endpoint. - #[instrument(skip_all, fields(endpoint = %endpoint_addr.endpoint_id.fmt_short()))] + #[instrument(skip_all, fields(endpoint = %endpoint_addr.id.fmt_short()))] fn add_endpoint_addr( &mut self, endpoint_addr: EndpointAddr, @@ -376,8 +376,8 @@ impl EndpointMapInner { metrics: &Metrics, ) { let source0 = source.clone(); - let endpoint_id = endpoint_addr.endpoint_id; - let relay_url = endpoint_addr.relay_url.clone(); + let endpoint_id = endpoint_addr.id; + let relay_url = endpoint_addr.relay_urls().next().cloned(); #[cfg(any(test, feature = "test-utils"))] let path_selection = self.path_selection; let endpoint_state = @@ -391,13 +391,13 @@ impl EndpointMapInner { }); endpoint_state.update_from_endpoint_addr( endpoint_addr.relay_url.as_ref(), - &endpoint_addr.direct_addresses, + &endpoint_addr.ip_addresses, source0, have_ipv6, metrics, ); let id = endpoint_state.id(); - for addr in endpoint_addr.direct_addresses() { + for addr in endpoint_addr.ip_addresses() { self.set_endpoint_state_for_ip_port(*addr, id); } } diff --git a/iroh/src/magicsock/endpoint_map/endpoint_state.rs b/iroh/src/magicsock/endpoint_map/endpoint_state.rs index 9681b9b8037..ad611461b81 100644 --- a/iroh/src/magicsock/endpoint_map/endpoint_state.rs +++ b/iroh/src/magicsock/endpoint_map/endpoint_state.rs @@ -6,7 +6,7 @@ use std::{ }; use data_encoding::HEXLOWER; -use iroh_base::{EndpointAddr, EndpointId, PublicKey, RelayUrl}; +use iroh_base::{AddrType, EndpointAddr, EndpointId, PublicKey, RelayUrl}; use n0_future::{ task::{self, AbortOnDropHandle}, time::{self, Duration, Instant}, @@ -1220,16 +1220,19 @@ impl EndpointState { impl From for EndpointAddr { fn from(info: RemoteInfo) -> Self { - let direct_addresses = info + let mut addrs = info .addrs .into_iter() - .map(|info| info.addr) + .map(|info| AddrType::Ip(info.addr)) .collect::>(); + if let Some(url) = info.relay_url { + addrs.insert(AddrType::Relay(url.into())); + } + EndpointAddr { - endpoint_id: info.endpoint_id, - relay_url: info.relay_url.map(Into::into), - direct_addresses, + id: info.endpoint_id, + addrs, } } } From fc3a0903d5efac03ae64b04199f87ac26e136525 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 17 Oct 2025 11:44:39 +0200 Subject: [PATCH 4/9] update more code to new addr format --- iroh-relay/src/endpoint_info.rs | 7 +- iroh/examples/0rtt.rs | 4 +- iroh/examples/connect-unreliable.rs | 17 +++- iroh/examples/connect.rs | 12 ++- iroh/examples/listen-unreliable.rs | 6 +- iroh/examples/listen.rs | 5 +- iroh/examples/transfer.rs | 10 +- iroh/src/discovery.rs | 25 +++-- iroh/src/discovery/static_provider.rs | 28 +++--- iroh/src/endpoint.rs | 14 +-- iroh/src/lib.rs | 4 +- iroh/src/magicsock.rs | 94 ++++++++++--------- iroh/src/magicsock/endpoint_map.rs | 4 +- .../magicsock/endpoint_map/endpoint_state.rs | 8 +- iroh/tests/integration.rs | 2 +- 15 files changed, 132 insertions(+), 108 deletions(-) diff --git a/iroh-relay/src/endpoint_info.rs b/iroh-relay/src/endpoint_info.rs index 113476337e9..ba9a45d19ea 100644 --- a/iroh-relay/src/endpoint_info.rs +++ b/iroh-relay/src/endpoint_info.rs @@ -206,6 +206,11 @@ impl EndpointData { pub fn set_user_data(&mut self, user_data: Option) { self.user_data = user_data; } + + /// Returns the full list of all known addresses + pub fn addrs(&self) -> impl Iterator { + self.addrs.iter() + } } impl From for EndpointData { @@ -333,7 +338,7 @@ impl From for EndpointAddr { impl From for EndpointInfo { fn from(addr: EndpointAddr) -> Self { let mut info = Self::new(addr.id); - info.add_addrs(addr.addrs.into_iter()); + info.add_addrs(addr.addrs); info } } diff --git a/iroh/examples/0rtt.rs b/iroh/examples/0rtt.rs index 7da7be4e9a4..1113ec82e19 100644 --- a/iroh/examples/0rtt.rs +++ b/iroh/examples/0rtt.rs @@ -144,12 +144,12 @@ async fn accept(_args: Args) -> n0_snafu::Result<()> { let Some(addr) = addrs.next().await else { snafu::whatever!("Address stream closed"); }; - if !addr.ip_addresses.is_empty() { + if !addr.ip_addresses().count() == 0 { break addr; } }; println!("Listening on: {addr:?}"); - println!("Endpoint ID: {:?}", addr.endpoint_id); + println!("Endpoint ID: {:?}", addr.id); println!("Ticket: {}", EndpointTicket::from(addr)); let accept = async move { diff --git a/iroh/examples/connect-unreliable.rs b/iroh/examples/connect-unreliable.rs index dcaa94b6044..fc26bdac509 100644 --- a/iroh/examples/connect-unreliable.rs +++ b/iroh/examples/connect-unreliable.rs @@ -9,6 +9,7 @@ use std::net::SocketAddr; use clap::Parser; use iroh::{Endpoint, EndpointAddr, RelayMode, RelayUrl, SecretKey}; +use iroh_base::AddrType; use n0_snafu::ResultExt; use tracing::info; @@ -55,19 +56,25 @@ async fn main() -> n0_snafu::Result<()> { endpoint.online().await; let endpoint_addr = endpoint.addr(); - let me = endpoint_addr.endpoint_id; + let me = endpoint_addr.id; println!("endpoint id: {me}"); println!("endpoint listening addresses:"); endpoint_addr - .ip_addresses - .iter() + .ip_addresses() .for_each(|addr| println!("\t{addr}")); let relay_url = endpoint_addr - .relay_url + .relay_urls() + .next() .expect("Should have a relay URL, assuming a default endpoint setup."); println!("endpoint relay server url: {relay_url}\n"); // Build a `EndpointAddr` from the endpoint_id, relay url, and UDP addresses. - let addr = EndpointAddr::from_parts(args.endpoint_id, Some(args.relay_url), args.addrs); + let addrs = args + .addrs + .into_iter() + .map(AddrType::Ip) + .chain(std::iter::once(AddrType::Relay(args.relay_url))); + + let addr = EndpointAddr::from_parts(args.endpoint_id, addrs); // Attempt to connect, over the given ALPN. // Returns a QUIC connection. diff --git a/iroh/examples/connect.rs b/iroh/examples/connect.rs index 53ed24c9ac1..ecb8376d97d 100644 --- a/iroh/examples/connect.rs +++ b/iroh/examples/connect.rs @@ -8,7 +8,7 @@ use std::net::SocketAddr; use clap::Parser; -use iroh::{Endpoint, EndpointAddr, RelayMode, RelayUrl, SecretKey}; +use iroh::{AddrType, Endpoint, EndpointAddr, RelayMode, RelayUrl, SecretKey}; use n0_snafu::{Result, ResultExt}; use tracing::info; @@ -63,11 +63,17 @@ async fn main() -> Result<()> { } let relay_url = endpoint_addr - .relay_url + .relay_urls() + .next() .expect("should be connected to a relay server"); println!("endpoint relay server url: {relay_url}\n"); // Build a `EndpointAddr` from the endpoint_id, relay url, and UDP addresses. - let addr = EndpointAddr::from_parts(args.endpoint_id, Some(args.relay_url), args.addrs); + let addrs = args + .addrs + .into_iter() + .map(AddrType::Ip) + .chain(std::iter::once(AddrType::Relay(args.relay_url))); + let addr = EndpointAddr::from_parts(args.endpoint_id, addrs); // Attempt to connect, over the given ALPN. // Returns a Quinn connection. diff --git a/iroh/examples/listen-unreliable.rs b/iroh/examples/listen-unreliable.rs index bf41744fed1..ec6e59fac23 100644 --- a/iroh/examples/listen-unreliable.rs +++ b/iroh/examples/listen-unreliable.rs @@ -41,8 +41,7 @@ async fn main() -> Result<()> { let endpoint_addr = endpoint.addr(); let local_addrs = endpoint_addr - .ip_addresses - .into_iter() + .ip_addresses() .map(|addr| { let addr = addr.to_string(); println!("\t{addr}"); @@ -51,7 +50,8 @@ async fn main() -> Result<()> { .collect::>() .join(" "); let relay_url = endpoint_addr - .relay_url + .relay_urls() + .next() .expect("Should have a relay URL, assuming a default endpoint setup."); println!("endpoint relay server url: {relay_url}"); println!("\nin a separate terminal run:"); diff --git a/iroh/examples/listen.rs b/iroh/examples/listen.rs index 63cec84e811..09daea14de1 100644 --- a/iroh/examples/listen.rs +++ b/iroh/examples/listen.rs @@ -43,8 +43,7 @@ async fn main() -> n0_snafu::Result<()> { let endpoint_addr = endpoint.addr(); let local_addrs = endpoint_addr - .ip_addresses - .iter() + .ip_addresses() .map(|addr| { let addr = addr.to_string(); println!("\t{addr}"); @@ -52,7 +51,7 @@ async fn main() -> n0_snafu::Result<()> { }) .collect::>() .join(" "); - let relay_url = endpoint_addr.relay_url.expect("missing relay"); + let relay_url = endpoint_addr.relay_urls().next().expect("missing relay"); println!("endpoint relay server url: {relay_url}"); println!("\nin a separate terminal run:"); diff --git a/iroh/examples/transfer.rs b/iroh/examples/transfer.rs index 330c23435c5..e163c183453 100644 --- a/iroh/examples/transfer.rs +++ b/iroh/examples/transfer.rs @@ -8,7 +8,7 @@ use clap::{Parser, Subcommand}; use data_encoding::HEXLOWER; use indicatif::HumanBytes; use iroh::{ - Endpoint, EndpointAddr, EndpointId, RelayMap, RelayMode, RelayUrl, SecretKey, + AddrType, Endpoint, EndpointAddr, EndpointId, RelayMap, RelayMode, RelayUrl, SecretKey, discovery::{ dns::DnsDiscovery, pkarr::{N0_DNS_PKARR_RELAY_PROD, N0_DNS_PKARR_RELAY_STAGING, PkarrPublisher}, @@ -288,11 +288,11 @@ impl EndpointArgs { let endpoint_addr = endpoint.addr(); println!("Our direct addresses:"); - for addr in &endpoint_addr.ip_addresses { + for addr in endpoint_addr.ip_addresses() { println!("\t{addr}"); } - if let Some(url) = endpoint_addr.relay_url { + if let Some(url) = endpoint_addr.relay_urls().next() { println!("Our home relay server:\t{url}"); } else { println!("No home relay server found"); @@ -311,7 +311,9 @@ async fn provide(endpoint: Endpoint, size: u64) -> Result<()> { println!("Ticket with our home relay and direct addresses:\n{ticket}\n",); let mut endpoint_addr = endpoint.addr(); - endpoint_addr.ip_addresses = Default::default(); + endpoint_addr + .addrs + .retain(|addr| !matches!(addr, AddrType::Ip(_))); let ticket = EndpointTicket::new(endpoint_addr); println!("Ticket with our home relay but no direct addresses:\n{ticket}\n",); diff --git a/iroh/src/discovery.rs b/iroh/src/discovery.rs index 1e31e3d1c53..eb070a57679 100644 --- a/iroh/src/discovery.rs +++ b/iroh/src/discovery.rs @@ -631,13 +631,13 @@ impl DiscoveryTask { #[cfg(test)] mod tests { use std::{ - collections::{BTreeSet, HashMap}, + collections::HashMap, net::SocketAddr, sync::{Arc, Mutex}, time::SystemTime, }; - use iroh_base::{EndpointAddr, SecretKey}; + use iroh_base::{AddrType, EndpointAddr, SecretKey}; use n0_snafu::{Error, Result, ResultExt}; use quinn::{IdleTimeout, TransportConfig}; use rand::{CryptoRng, Rng, SeedableRng}; @@ -707,7 +707,7 @@ mod tests { let port: u16 = rand::rng().random_range(10_000..20_000); // "240.0.0.0/4" is reserved and unreachable let addr: SocketAddr = format!("240.0.0.1:{port}").parse().unwrap(); - let data = EndpointData::new(None, BTreeSet::from([addr])); + let data = EndpointData::new([AddrType::Ip(addr)]); Some((data, ts)) } else { self.shared @@ -889,9 +889,10 @@ mod tests { new_endpoint(&mut rng, |ep| disco_shared.create_discovery(ep.id())).await; let ep1_wrong_addr = EndpointAddr { - endpoint_id: ep1.id(), - relay_url: None, - direct_addresses: BTreeSet::from(["240.0.0.1:1000".parse().unwrap()]), + id: ep1.id(), + addrs: [AddrType::Ip("240.0.0.1:1000".parse().unwrap())] + .into_iter() + .collect(), }; let _conn = ep2.connect(ep1_wrong_addr, TEST_ALPN).await?; Ok(()) @@ -955,7 +956,7 @@ mod tests { /// publish to. The DNS and pkarr servers share their state. #[cfg(test)] mod test_dns_pkarr { - use iroh_base::{EndpointAddr, SecretKey}; + use iroh_base::{AddrType, EndpointAddr, SecretKey}; use iroh_relay::{RelayMap, endpoint_info::UserData}; use n0_future::time::Duration; use n0_snafu::{Error, Result, ResultExt}; @@ -1016,14 +1017,13 @@ mod test_dns_pkarr { let secret_key = SecretKey::generate(&mut rng); let endpoint_id = secret_key.public(); - let relay_url = Some("https://relay.example".parse().unwrap()); + let relay_url = Some(AddrType::Relay("https://relay.example".parse().unwrap())); let resolver = DnsResolver::with_nameserver(dns_pkarr_server.nameserver); let publisher = PkarrPublisher::builder(dns_pkarr_server.pkarr_url.clone()).build(secret_key); let user_data: UserData = "foobar".parse().unwrap(); - let data = EndpointData::new(relay_url.clone(), Default::default()) - .with_user_data(Some(user_data.clone())); + let data = EndpointData::new(relay_url.clone()).with_user_data(Some(user_data.clone())); // does not block, update happens in background task publisher.update_endpoint_data(&data); // wait until our shared state received the update from pkarr publishing @@ -1037,9 +1037,8 @@ mod test_dns_pkarr { println!("resolved {resolved:?}"); let expected_addr = EndpointAddr { - endpoint_id, - relay_url, - direct_addresses: Default::default(), + id: endpoint_id, + addrs: relay_url.into_iter().collect(), }; assert_eq!(resolved.to_endpoint_addr(), expected_addr); diff --git a/iroh/src/discovery/static_provider.rs b/iroh/src/discovery/static_provider.rs index 636b973651c..f8a1ebdbe4f 100644 --- a/iroh/src/discovery/static_provider.rs +++ b/iroh/src/discovery/static_provider.rs @@ -174,12 +174,7 @@ impl StaticProvider { match guard.entry(endpoint_id) { Entry::Occupied(mut entry) => { let existing = entry.get_mut(); - existing - .data - .add_direct_addresses(data.ip_addresses().copied()); - existing - .data - .set_relay_url(data.relay_urls().next().cloned()); + existing.data.add_addrs(data.addrs().cloned()); existing.data.set_user_data(data.user_data().cloned()); existing.last_updated = last_updated; } @@ -236,7 +231,7 @@ impl Discovery for StaticProvider { #[cfg(test)] mod tests { - use iroh_base::{EndpointAddr, SecretKey}; + use iroh_base::{AddrType, EndpointAddr, SecretKey}; use n0_snafu::{Result, ResultExt}; use super::*; @@ -253,9 +248,10 @@ mod tests { let key = SecretKey::from_bytes(&[0u8; 32]); let addr = EndpointAddr { - endpoint_id: key.public(), - relay_url: Some("https://example.com".parse()?), - direct_addresses: Default::default(), + id: key.public(), + addrs: [AddrType::Relay("https://example.com".parse()?)] + .into_iter() + .collect(), }; let user_data = Some("foobar".parse().unwrap()); let endpoint_info = EndpointInfo::from(addr.clone()).with_user_data(user_data.clone()); @@ -284,15 +280,19 @@ mod tests { let discovery = StaticProvider::with_provenance("foo"); let key = SecretKey::from_bytes(&[0u8; 32]); let addr = EndpointAddr { - endpoint_id: key.public(), - relay_url: Some("https://example.com".parse()?), - direct_addresses: Default::default(), + id: key.public(), + addrs: [AddrType::Relay("https://example.com".parse()?)] + .into_iter() + .collect(), }; discovery.add_endpoint_info(addr); let mut stream = discovery.resolve(key.public()).unwrap(); let item = stream.next().await.unwrap()?; assert_eq!(item.provenance(), "foo"); - assert_eq!(item.relay_url(), Some(&("https://example.com".parse()?))); + assert_eq!( + item.relay_urls().next(), + Some(&("https://example.com".parse()?)) + ); Ok(()) } diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 693eb4e06ce..11f6c968b4d 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -2135,7 +2135,7 @@ fn is_cgi() -> bool { mod tests { use std::time::{Duration, Instant}; - use iroh_base::{EndpointAddr, EndpointId, SecretKey}; + use iroh_base::{AddrType, EndpointAddr, EndpointId, SecretKey}; use n0_future::{BufferedStreamExt, StreamExt, stream, task::AbortOnDropHandle}; use n0_snafu::{Error, Result, ResultExt}; use n0_watcher::Watcher; @@ -2460,7 +2460,7 @@ mod tests { println!("round1: {:?}", addr); // remove direct addrs to force relay usage - addr.ip_addresses.clear(); + addr.addrs.retain(|addr| !matches!(addr, AddrType::Ip(_))); let conn = client.connect(addr, TEST_ALPN).await?; let (mut send, mut recv) = conn.open_bi().await.e()?; @@ -2496,7 +2496,7 @@ mod tests { let mut addr = tokio::time::timeout(Duration::from_secs(10), async move { let mut stream = addr_watcher.stream(); while let Some(addr) = stream.next().await { - if addr.relay_url.as_ref() != Some(&relay_url) { + if addr.relay_urls().next() != Some(&relay_url) { return addr; } } @@ -2506,10 +2506,10 @@ mod tests { .e()?; println!("round2: {:?}", addr); - assert_eq!(addr.relay_url, Some(new_relay_url)); + assert_eq!(addr.relay_urls().next(), Some(&new_relay_url)); // remove direct addrs to force relay usage - addr.ip_addresses.clear(); + addr.addrs.retain(|addr| !matches!(addr, AddrType::Ip(_))); let conn = client.connect(addr, TEST_ALPN).await?; let (mut send, mut recv) = conn.open_bi().await.e()?; @@ -2677,7 +2677,7 @@ mod tests { let ep1_endpointaddr = ep1.addr(); tracing::info!( "endpoint id 1 {ep1_endpointid}, relay URL {:?}", - ep1_endpointaddr.relay_url() + ep1_endpointaddr.relay_urls().next() ); tracing::info!("endpoint id 2 {ep2_endpointid}"); @@ -2723,7 +2723,7 @@ mod tests { .bind() .await?; - assert!(!ep.addr().ip_addresses.is_empty()); + assert!(ep.addr().ip_addresses().count() > 0); Ok(()) } diff --git a/iroh/src/lib.rs b/iroh/src/lib.rs index e171e695bd9..5998a4a7186 100644 --- a/iroh/src/lib.rs +++ b/iroh/src/lib.rs @@ -272,8 +272,8 @@ pub mod protocol; pub use endpoint::{Endpoint, RelayMode}; pub use iroh_base::{ - EndpointAddr, EndpointId, KeyParsingError, PublicKey, RelayUrl, RelayUrlParseError, SecretKey, - Signature, SignatureError, + AddrType, EndpointAddr, EndpointId, KeyParsingError, PublicKey, RelayUrl, RelayUrlParseError, + SecretKey, Signature, SignatureError, }; pub use iroh_relay::{RelayConfig, RelayMap, endpoint_info}; pub use n0_watcher::Watcher; diff --git a/iroh/src/magicsock.rs b/iroh/src/magicsock.rs index 72d3653a2df..adf4266526a 100644 --- a/iroh/src/magicsock.rs +++ b/iroh/src/magicsock.rs @@ -30,7 +30,7 @@ use std::{ use bytes::Bytes; use data_encoding::HEXLOWER; -use iroh_base::{EndpointAddr, EndpointId, PublicKey, RelayUrl, SecretKey}; +use iroh_base::{AddrType, EndpointAddr, EndpointId, PublicKey, RelayUrl, SecretKey}; use iroh_relay::{RelayConfig, RelayMap}; use n0_future::{ task::{self, AbortOnDropHandle}, @@ -410,7 +410,7 @@ impl MagicSock { ) -> Result<(), AddEndpointAddrError> { let mut pruned: usize = 0; for my_addr in self.direct_addrs.sockaddrs() { - if addr.ip_addresses.remove(&my_addr) { + if addr.addrs.remove(&AddrType::Ip(my_addr)) { warn!( endpoint_id=%addr.id.fmt_short(), %my_addr, %source, "not adding our addr for endpoint"); pruned += 1; } @@ -435,7 +435,7 @@ impl MagicSock { let updated = self.direct_addrs.update(addrs); if updated { self.endpoint_map - .on_direct_addr_discovered(self.direct_addrs.sockaddrs()); + .on_direct_addr_discovered(self.direct_addrs.sockaddrs().collect()); self.publish_my_addr(); } } @@ -1157,19 +1157,22 @@ impl MagicSock { /// Called whenever our addresses or home relay endpoint changes. fn publish_my_addr(&self) { let relay_url = self.my_relay(); - let direct_addrs = self.direct_addrs.sockaddrs(); + let mut addrs: BTreeSet<_> = self.direct_addrs.sockaddrs().map(AddrType::Ip).collect(); let user_data = self .discovery_user_data .read() .expect("lock poisened") .clone(); - if relay_url.is_none() && direct_addrs.is_empty() && user_data.is_none() { + if relay_url.is_none() && addrs.is_empty() && user_data.is_none() { // do not bother publishing if we don't have any information return; } + if let Some(url) = relay_url { + addrs.insert(AddrType::Relay(url)); + } - let data = EndpointData::new(relay_url, direct_addrs).with_user_data(user_data); + let data = EndpointData::new(addrs).with_user_data(user_data); self.discovery.publish(&data); } } @@ -2351,8 +2354,8 @@ impl DiscoveredDirectAddrs { updated } - fn sockaddrs(&self) -> BTreeSet { - self.addrs.get().into_iter().map(|da| da.addr).collect() + fn sockaddrs(&self) -> impl Iterator { + self.addrs.get().into_iter().map(|da| da.addr) } /// Whether the direct addr information is considered "fresh". @@ -2539,7 +2542,7 @@ mod tests { use std::{collections::BTreeSet, net::SocketAddr, sync::Arc, time::Duration}; use data_encoding::HEXLOWER; - use iroh_base::{EndpointAddr, EndpointId, PublicKey}; + use iroh_base::{AddrType, EndpointAddr, EndpointId, PublicKey}; use n0_future::{StreamExt, time}; use n0_snafu::{Result, ResultExt}; use n0_watcher::Watcher; @@ -2669,9 +2672,8 @@ mod tests { } let addr = EndpointAddr { - endpoint_id: me.public(), - relay_url: None, - direct_addresses: new_addrs.clone(), + id: me.public(), + addrs: new_addrs.iter().copied().map(AddrType::Ip).collect(), }; m.endpoint.magic_sock().add_test_addr(addr); } @@ -3230,15 +3232,15 @@ mod tests { }); let _accept_task = AbortOnDropHandle::new(accept_task); + let addrs = msock_2 + .direct_addresses() + .get() + .into_iter() + .map(|x| AddrType::Ip(x.addr)) + .collect(); let endpoint_addr_2 = EndpointAddr { - endpoint_id: endpoint_id_2, - relay_url: None, - direct_addresses: msock_2 - .direct_addresses() - .get() - .into_iter() - .map(|x| x.addr) - .collect(), + id: endpoint_id_2, + addrs, }; msock_1 .add_endpoint_addr( @@ -3308,9 +3310,8 @@ mod tests { // Add an empty entry in the EndpointMap of ep_1 msock_1.endpoint_map.add_endpoint_addr( EndpointAddr { - endpoint_id: endpoint_id_2, - relay_url: None, - direct_addresses: Default::default(), + id: endpoint_id_2, + addrs: Default::default(), }, Source::NamedApp { name: "test".into(), @@ -3344,16 +3345,16 @@ mod tests { info!("first connect timed out as expected"); // Provide correct addressing information + let addrs = msock_2 + .direct_addresses() + .get() + .into_iter() + .map(|x| AddrType::Ip(x.addr)) + .collect(); msock_1.endpoint_map.add_endpoint_addr( EndpointAddr { - endpoint_id: endpoint_id_2, - relay_url: None, - direct_addresses: msock_2 - .direct_addresses() - .get() - .into_iter() - .map(|x| x.addr) - .collect(), + id: endpoint_id_2, + addrs, }, Source::NamedApp { name: "test".into(), @@ -3395,11 +3396,8 @@ mod tests { assert_eq!(stack.endpoint.magic_sock().endpoint_map.endpoint_count(), 0); // Empty - let empty_addr = EndpointAddr { - endpoint_id: SecretKey::generate(&mut rng).public(), - relay_url: None, - direct_addresses: Default::default(), - }; + let empty_addr = EndpointAddr::new(SecretKey::generate(&mut rng).public()); + let err = stack .endpoint .magic_sock() @@ -3413,9 +3411,10 @@ mod tests { // relay url only let addr = EndpointAddr { - endpoint_id: SecretKey::generate(&mut rng).public(), - relay_url: Some("http://my-relay.com".parse().unwrap()), - direct_addresses: Default::default(), + id: SecretKey::generate(&mut rng).public(), + addrs: [AddrType::Relay("http://my-relay.com".parse().unwrap())] + .into_iter() + .collect(), }; stack .endpoint @@ -3425,9 +3424,10 @@ mod tests { // addrs only let addr = EndpointAddr { - endpoint_id: SecretKey::generate(&mut rng).public(), - relay_url: None, - direct_addresses: ["127.0.0.1:1234".parse().unwrap()].into_iter().collect(), + id: SecretKey::generate(&mut rng).public(), + addrs: [AddrType::Ip("127.0.0.1:1234".parse().unwrap())] + .into_iter() + .collect(), }; stack .endpoint @@ -3437,9 +3437,13 @@ mod tests { // both let addr = EndpointAddr { - endpoint_id: SecretKey::generate(&mut rng).public(), - relay_url: Some("http://my-relay.com".parse().unwrap()), - direct_addresses: ["127.0.0.1:1234".parse().unwrap()].into_iter().collect(), + id: SecretKey::generate(&mut rng).public(), + addrs: [ + AddrType::Relay("http://my-relay.com".parse().unwrap()), + AddrType::Ip("127.0.0.1:1234".parse().unwrap()), + ] + .into_iter() + .collect(), }; stack .endpoint diff --git a/iroh/src/magicsock/endpoint_map.rs b/iroh/src/magicsock/endpoint_map.rs index c56a7553db1..c97dcd3eac4 100644 --- a/iroh/src/magicsock/endpoint_map.rs +++ b/iroh/src/magicsock/endpoint_map.rs @@ -390,8 +390,8 @@ impl EndpointMapInner { path_selection, }); endpoint_state.update_from_endpoint_addr( - endpoint_addr.relay_url.as_ref(), - &endpoint_addr.ip_addresses, + endpoint_addr.relay_urls().next(), + endpoint_addr.ip_addresses().copied(), source0, have_ipv6, metrics, diff --git a/iroh/src/magicsock/endpoint_map/endpoint_state.rs b/iroh/src/magicsock/endpoint_map/endpoint_state.rs index ad611461b81..5c50ced5ac3 100644 --- a/iroh/src/magicsock/endpoint_map/endpoint_state.rs +++ b/iroh/src/magicsock/endpoint_map/endpoint_state.rs @@ -678,7 +678,7 @@ impl EndpointState { pub(super) fn update_from_endpoint_addr( &mut self, new_relay_url: Option<&RelayUrl>, - new_addrs: &BTreeSet, + new_addrs: impl Iterator, source: super::Source, have_ipv6: bool, metrics: &MagicsockMetrics, @@ -714,7 +714,8 @@ impl EndpointState { } let mut access = self.udp_paths.access_mut(now); - for &addr in new_addrs.iter() { + let mut new_addrs_list = Vec::new(); + for addr in new_addrs { access .paths() .entry(addr.into()) @@ -724,10 +725,11 @@ impl EndpointState { .or_insert_with(|| { PathState::new(self.endpoint_id, SendAddr::from(addr), source.clone(), now) }); + new_addrs_list.push(addr); } drop(access); let paths = summarize_endpoint_paths(self.udp_paths.paths()); - debug!(new = ?new_addrs , %paths, "added new direct paths for endpoint"); + debug!(new = ?new_addrs_list , %paths, "added new direct paths for endpoint"); } /// Handle a received Disco Ping. diff --git a/iroh/tests/integration.rs b/iroh/tests/integration.rs index 99121088ebb..b2871157dfe 100644 --- a/iroh/tests/integration.rs +++ b/iroh/tests/integration.rs @@ -103,7 +103,7 @@ async fn simple_endpoint_id_based_connection_transfer() -> Result { tracing::info!("no items on stream when resolving, looping"); continue; }; - if item.relay_url().is_some() { + if item.relay_urls().next().is_some() { tracing::info!("home relay found"); break; } From d34f804a54f6a8dd2bbee274763dd507af43b424 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 17 Oct 2025 17:14:56 +0200 Subject: [PATCH 5/9] rename to TransportAddr --- iroh-base/src/endpoint_addr.rs | 24 +++++------ iroh-base/src/lib.rs | 2 +- iroh-relay/src/endpoint_info.rs | 43 ++++++++++--------- iroh/examples/connect-unreliable.rs | 6 +-- iroh/examples/connect.rs | 6 +-- iroh/examples/transfer.rs | 4 +- iroh/src/discovery.rs | 12 +++--- iroh/src/discovery/static_provider.rs | 6 +-- iroh/src/endpoint.rs | 14 +++--- iroh/src/lib.rs | 4 +- iroh/src/magicsock.rs | 28 ++++++------ .../magicsock/endpoint_map/endpoint_state.rs | 6 +-- 12 files changed, 83 insertions(+), 72 deletions(-) diff --git a/iroh-base/src/endpoint_addr.rs b/iroh-base/src/endpoint_addr.rs index 6631acaf5e0..25ec26b68f2 100644 --- a/iroh-base/src/endpoint_addr.rs +++ b/iroh-base/src/endpoint_addr.rs @@ -41,13 +41,13 @@ pub struct EndpointAddr { /// The endpoint's identifier. pub id: EndpointId, /// The endpoint's addresses - pub addrs: BTreeSet, + pub addrs: BTreeSet, } /// Available address types. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] #[non_exhaustive] -pub enum AddrType { +pub enum TransportAddr { /// IP based addresses Ip(SocketAddr), /// Relays @@ -65,7 +65,7 @@ impl EndpointAddr { /// Adds a relay url. pub fn with_relay_url(mut self, relay_url: RelayUrl) -> Self { - self.addrs.insert(AddrType::Relay(relay_url)); + self.addrs.insert(TransportAddr::Relay(relay_url)); self } @@ -75,13 +75,13 @@ impl EndpointAddr { addresses: impl IntoIterator, ) -> Self { for addr in addresses.into_iter() { - self.addrs.insert(AddrType::Ip(addr)); + self.addrs.insert(TransportAddr::Ip(addr)); } self } /// Creates a new [`EndpointAddr`] from its parts. - pub fn from_parts(id: PublicKey, addrs: impl IntoIterator) -> Self { + pub fn from_parts(id: PublicKey, addrs: impl IntoIterator) -> Self { Self { id, addrs: addrs.into_iter().collect(), @@ -96,7 +96,7 @@ impl EndpointAddr { /// Returns the direct addresses of this peer. pub fn ip_addresses(&self) -> impl Iterator { self.addrs.iter().filter_map(|addr| match addr { - AddrType::Ip(addr) => Some(addr), + TransportAddr::Ip(addr) => Some(addr), _ => None, }) } @@ -104,7 +104,7 @@ impl EndpointAddr { /// Returns the relay url of this peer. pub fn relay_urls(&self) -> impl Iterator { self.addrs.iter().filter_map(|addr| match addr { - AddrType::Relay(url) => Some(url), + TransportAddr::Relay(url) => Some(url), _ => None, }) } @@ -115,10 +115,10 @@ impl From<(PublicKey, Option, &[SocketAddr])> for EndpointAddr { let (id, relay_url, direct_addresses_iter) = value; let mut addrs = BTreeSet::new(); if let Some(url) = relay_url { - addrs.insert(AddrType::Relay(url)); + addrs.insert(TransportAddr::Relay(url)); } for addr in direct_addresses_iter { - addrs.insert(AddrType::Ip(*addr)); + addrs.insert(TransportAddr::Ip(*addr)); } EndpointAddr { id, addrs } } @@ -148,11 +148,11 @@ mod tests { #[test] fn test_roundtrip_new_addr_type() { let old = vec![ - AddrType::Ip("127.0.0.1:9".parse().unwrap()), - AddrType::Relay("https://example.com".parse().unwrap()), + TransportAddr::Ip("127.0.0.1:9".parse().unwrap()), + TransportAddr::Relay("https://example.com".parse().unwrap()), ]; let old_ser = postcard::to_stdvec(&old).unwrap(); - let old_back: Vec = postcard::from_bytes(&old_ser).unwrap(); + let old_back: Vec = postcard::from_bytes(&old_ser).unwrap(); assert_eq!(old, old_back); let new = vec![ diff --git a/iroh-base/src/lib.rs b/iroh-base/src/lib.rs index 63a8f5b4ea9..d1b22d55545 100644 --- a/iroh-base/src/lib.rs +++ b/iroh-base/src/lib.rs @@ -15,7 +15,7 @@ mod key; mod relay_url; #[cfg(feature = "key")] -pub use self::endpoint_addr::{AddrType, EndpointAddr}; +pub use self::endpoint_addr::{EndpointAddr, TransportAddr}; #[cfg(feature = "key")] pub use self::key::{EndpointId, KeyParsingError, PublicKey, SecretKey, Signature, SignatureError}; #[cfg(feature = "relay")] diff --git a/iroh-relay/src/endpoint_info.rs b/iroh-relay/src/endpoint_info.rs index ba9a45d19ea..cc9994439e4 100644 --- a/iroh-relay/src/endpoint_info.rs +++ b/iroh-relay/src/endpoint_info.rs @@ -40,7 +40,7 @@ use std::{ str::{FromStr, Utf8Error}, }; -use iroh_base::{AddrType, EndpointAddr, EndpointId, KeyParsingError, RelayUrl, SecretKey}; +use iroh_base::{EndpointAddr, EndpointId, KeyParsingError, RelayUrl, SecretKey, TransportAddr}; use nested_enum_utils::common_fields; use snafu::{Backtrace, ResultExt, Snafu}; use url::Url; @@ -127,14 +127,14 @@ impl EndpointIdExt for EndpointId { #[derive(Debug, Clone, Default, Eq, PartialEq)] pub struct EndpointData { /// addresses where this endpoint can be reached. - addrs: BTreeSet, + addrs: BTreeSet, /// Optional user-defined [`UserData`] for this endpoint. user_data: Option, } impl EndpointData { /// Creates a new [`EndpointData`] with a relay URL and a set of direct addresses. - pub fn new(addrs: impl IntoIterator) -> Self { + pub fn new(addrs: impl IntoIterator) -> Self { Self { addrs: addrs.into_iter().collect(), user_data: None, @@ -144,7 +144,7 @@ impl EndpointData { /// Sets the relay URL and returns the updated endpoint data. pub fn with_relay_url(mut self, relay_url: Option) -> Self { if let Some(url) = relay_url { - self.addrs.insert(AddrType::Relay(url)); + self.addrs.insert(TransportAddr::Relay(url)); } self } @@ -152,7 +152,7 @@ impl EndpointData { /// Sets the direct addresses and returns the updated endpoint data. pub fn with_ip_addresses(mut self, addresses: BTreeSet) -> Self { for addr in addresses.into_iter() { - self.addrs.insert(AddrType::Ip(addr)); + self.addrs.insert(TransportAddr::Ip(addr)); } self } @@ -166,7 +166,7 @@ impl EndpointData { /// Returns the relay URL of the endpoint. pub fn relay_urls(&self) -> impl Iterator { self.addrs.iter().filter_map(|addr| match addr { - AddrType::Relay(url) => Some(url), + TransportAddr::Relay(url) => Some(url), _ => None, }) } @@ -179,24 +179,25 @@ impl EndpointData { /// Returns the direct addresses of the endpoint. pub fn ip_addresses(&self) -> impl Iterator { self.addrs.iter().filter_map(|addr| match addr { - AddrType::Ip(addr) => Some(addr), + TransportAddr::Ip(addr) => Some(addr), _ => None, }) } /// Removes all direct addresses from the endpoint data. pub fn clear_direct_addresses(&mut self) { - self.addrs.retain(|addr| !matches!(addr, AddrType::Ip(_))); + self.addrs + .retain(|addr| !matches!(addr, TransportAddr::Ip(_))); } /// Removes all direct addresses from the endpoint data. pub fn clear_relay_urls(&mut self) { self.addrs - .retain(|addr| !matches!(addr, AddrType::Relay(_))); + .retain(|addr| !matches!(addr, TransportAddr::Relay(_))); } /// Add addresses to the endpoint data. - pub fn add_addrs(&mut self, addrs: impl IntoIterator) { + pub fn add_addrs(&mut self, addrs: impl IntoIterator) { for addr in addrs.into_iter() { self.addrs.insert(addr); } @@ -208,7 +209,7 @@ impl EndpointData { } /// Returns the full list of all known addresses - pub fn addrs(&self) -> impl Iterator { + pub fn addrs(&self) -> impl Iterator { self.addrs.iter() } } @@ -307,13 +308,13 @@ impl From<&TxtAttrs> for EndpointInfo { .into_iter() .flatten() .filter_map(|s| Url::parse(s).ok()) - .map(|url| AddrType::Relay(url.into())); + .map(|url| TransportAddr::Relay(url.into())); let direct_addresses = attrs .get(&IrohAttr::Addr) .into_iter() .flatten() .filter_map(|s| SocketAddr::from_str(s).ok()) - .map(AddrType::Ip); + .map(TransportAddr::Ip); let user_data = attrs .get(&IrohAttr::UserData) @@ -519,8 +520,10 @@ impl From<&EndpointInfo> for TxtAttrs { let mut attrs = vec![]; for addr in &info.data.addrs { match addr { - AddrType::Relay(relay_url) => attrs.push((IrohAttr::Relay, relay_url.to_string())), - AddrType::Ip(addr) => attrs.push((IrohAttr::Addr, addr.to_string())), + TransportAddr::Relay(relay_url) => { + attrs.push((IrohAttr::Relay, relay_url.to_string())) + } + TransportAddr::Ip(addr) => attrs.push((IrohAttr::Addr, addr.to_string())), _ => {} } } @@ -670,7 +673,7 @@ mod tests { }, }, }; - use iroh_base::{AddrType, EndpointId, SecretKey}; + use iroh_base::{EndpointId, SecretKey, TransportAddr}; use n0_snafu::{Result, ResultExt}; use super::{EndpointData, EndpointIdExt, EndpointInfo}; @@ -679,8 +682,8 @@ mod tests { #[test] fn txt_attr_roundtrip() { let endpoint_data = EndpointData::new([ - AddrType::Relay("https://example.com".parse().unwrap()), - AddrType::Ip("127.0.0.1:1234".parse().unwrap()), + TransportAddr::Relay("https://example.com".parse().unwrap()), + TransportAddr::Ip("127.0.0.1:1234".parse().unwrap()), ]) .with_user_data(Some("foobar".parse().unwrap())); let endpoint_id = "vpnk377obfvzlipnsfbqba7ywkkenc4xlpmovt5tsfujoa75zqia" @@ -697,8 +700,8 @@ mod tests { let secret_key = SecretKey::from_str("vpnk377obfvzlipnsfbqba7ywkkenc4xlpmovt5tsfujoa75zqia").unwrap(); let endpoint_data = EndpointData::new([ - AddrType::Relay("https://example.com".parse().unwrap()), - AddrType::Ip("127.0.0.1:1234".parse().unwrap()), + TransportAddr::Relay("https://example.com".parse().unwrap()), + TransportAddr::Ip("127.0.0.1:1234".parse().unwrap()), ]) .with_user_data(Some("foobar".parse().unwrap())); let expected = EndpointInfo::from_parts(secret_key.public(), endpoint_data); diff --git a/iroh/examples/connect-unreliable.rs b/iroh/examples/connect-unreliable.rs index fc26bdac509..61c2fae6cfd 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 iroh_base::AddrType; +use iroh_base::TransportAddr; use n0_snafu::ResultExt; use tracing::info; @@ -71,8 +71,8 @@ async fn main() -> n0_snafu::Result<()> { let addrs = args .addrs .into_iter() - .map(AddrType::Ip) - .chain(std::iter::once(AddrType::Relay(args.relay_url))); + .map(TransportAddr::Ip) + .chain(std::iter::once(TransportAddr::Relay(args.relay_url))); let addr = EndpointAddr::from_parts(args.endpoint_id, addrs); diff --git a/iroh/examples/connect.rs b/iroh/examples/connect.rs index ecb8376d97d..fbae03cfe8f 100644 --- a/iroh/examples/connect.rs +++ b/iroh/examples/connect.rs @@ -8,7 +8,7 @@ use std::net::SocketAddr; use clap::Parser; -use iroh::{AddrType, Endpoint, EndpointAddr, RelayMode, RelayUrl, SecretKey}; +use iroh::{Endpoint, EndpointAddr, RelayMode, RelayUrl, SecretKey, TransportAddr}; use n0_snafu::{Result, ResultExt}; use tracing::info; @@ -71,8 +71,8 @@ async fn main() -> Result<()> { let addrs = args .addrs .into_iter() - .map(AddrType::Ip) - .chain(std::iter::once(AddrType::Relay(args.relay_url))); + .map(TransportAddr::Ip) + .chain(std::iter::once(TransportAddr::Relay(args.relay_url))); let addr = EndpointAddr::from_parts(args.endpoint_id, addrs); // Attempt to connect, over the given ALPN. diff --git a/iroh/examples/transfer.rs b/iroh/examples/transfer.rs index e163c183453..35fa8c1105a 100644 --- a/iroh/examples/transfer.rs +++ b/iroh/examples/transfer.rs @@ -8,7 +8,7 @@ use clap::{Parser, Subcommand}; use data_encoding::HEXLOWER; use indicatif::HumanBytes; use iroh::{ - AddrType, Endpoint, EndpointAddr, EndpointId, RelayMap, RelayMode, RelayUrl, SecretKey, + Endpoint, EndpointAddr, EndpointId, RelayMap, RelayMode, RelayUrl, SecretKey, TransportAddr, discovery::{ dns::DnsDiscovery, pkarr::{N0_DNS_PKARR_RELAY_PROD, N0_DNS_PKARR_RELAY_STAGING, PkarrPublisher}, @@ -313,7 +313,7 @@ async fn provide(endpoint: Endpoint, size: u64) -> Result<()> { let mut endpoint_addr = endpoint.addr(); endpoint_addr .addrs - .retain(|addr| !matches!(addr, AddrType::Ip(_))); + .retain(|addr| !matches!(addr, TransportAddr::Ip(_))); let ticket = EndpointTicket::new(endpoint_addr); println!("Ticket with our home relay but no direct addresses:\n{ticket}\n",); diff --git a/iroh/src/discovery.rs b/iroh/src/discovery.rs index eb070a57679..d2a27c7caac 100644 --- a/iroh/src/discovery.rs +++ b/iroh/src/discovery.rs @@ -637,7 +637,7 @@ mod tests { time::SystemTime, }; - use iroh_base::{AddrType, EndpointAddr, SecretKey}; + use iroh_base::{EndpointAddr, SecretKey, TransportAddr}; use n0_snafu::{Error, Result, ResultExt}; use quinn::{IdleTimeout, TransportConfig}; use rand::{CryptoRng, Rng, SeedableRng}; @@ -707,7 +707,7 @@ mod tests { let port: u16 = rand::rng().random_range(10_000..20_000); // "240.0.0.0/4" is reserved and unreachable let addr: SocketAddr = format!("240.0.0.1:{port}").parse().unwrap(); - let data = EndpointData::new([AddrType::Ip(addr)]); + let data = EndpointData::new([TransportAddr::Ip(addr)]); Some((data, ts)) } else { self.shared @@ -890,7 +890,7 @@ mod tests { let ep1_wrong_addr = EndpointAddr { id: ep1.id(), - addrs: [AddrType::Ip("240.0.0.1:1000".parse().unwrap())] + addrs: [TransportAddr::Ip("240.0.0.1:1000".parse().unwrap())] .into_iter() .collect(), }; @@ -956,7 +956,7 @@ mod tests { /// publish to. The DNS and pkarr servers share their state. #[cfg(test)] mod test_dns_pkarr { - use iroh_base::{AddrType, EndpointAddr, SecretKey}; + use iroh_base::{EndpointAddr, SecretKey, TransportAddr}; use iroh_relay::{RelayMap, endpoint_info::UserData}; use n0_future::time::Duration; use n0_snafu::{Error, Result, ResultExt}; @@ -1017,7 +1017,9 @@ mod test_dns_pkarr { let secret_key = SecretKey::generate(&mut rng); let endpoint_id = secret_key.public(); - let relay_url = Some(AddrType::Relay("https://relay.example".parse().unwrap())); + let relay_url = Some(TransportAddr::Relay( + "https://relay.example".parse().unwrap(), + )); let resolver = DnsResolver::with_nameserver(dns_pkarr_server.nameserver); let publisher = diff --git a/iroh/src/discovery/static_provider.rs b/iroh/src/discovery/static_provider.rs index f8a1ebdbe4f..4b299dce088 100644 --- a/iroh/src/discovery/static_provider.rs +++ b/iroh/src/discovery/static_provider.rs @@ -231,7 +231,7 @@ impl Discovery for StaticProvider { #[cfg(test)] mod tests { - use iroh_base::{AddrType, EndpointAddr, SecretKey}; + use iroh_base::{EndpointAddr, SecretKey, TransportAddr}; use n0_snafu::{Result, ResultExt}; use super::*; @@ -249,7 +249,7 @@ mod tests { let key = SecretKey::from_bytes(&[0u8; 32]); let addr = EndpointAddr { id: key.public(), - addrs: [AddrType::Relay("https://example.com".parse()?)] + addrs: [TransportAddr::Relay("https://example.com".parse()?)] .into_iter() .collect(), }; @@ -281,7 +281,7 @@ mod tests { let key = SecretKey::from_bytes(&[0u8; 32]); let addr = EndpointAddr { id: key.public(), - addrs: [AddrType::Relay("https://example.com".parse()?)] + addrs: [TransportAddr::Relay("https://example.com".parse()?)] .into_iter() .collect(), }; diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 11f6c968b4d..7053a51d7e3 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -877,7 +877,7 @@ impl Endpoint { watch_addrs .or(watch_relay) .map(move |(addrs, relays)| { - use iroh_base::AddrType; + use iroh_base::TransportAddr; debug_assert!(!addrs.is_empty(), "direct addresses must never be empty"); @@ -885,8 +885,8 @@ impl Endpoint { endpoint_id, relays .into_iter() - .map(AddrType::Relay) - .chain(addrs.into_iter().map(|x| AddrType::Ip(x.addr))), + .map(TransportAddr::Relay) + .chain(addrs.into_iter().map(|x| TransportAddr::Ip(x.addr))), ) }) .expect("watchable is alive - cannot be disconnected yet") @@ -2135,7 +2135,7 @@ fn is_cgi() -> bool { mod tests { use std::time::{Duration, Instant}; - use iroh_base::{AddrType, EndpointAddr, EndpointId, SecretKey}; + use iroh_base::{EndpointAddr, EndpointId, SecretKey, TransportAddr}; use n0_future::{BufferedStreamExt, StreamExt, stream, task::AbortOnDropHandle}; use n0_snafu::{Error, Result, ResultExt}; use n0_watcher::Watcher; @@ -2460,7 +2460,8 @@ mod tests { println!("round1: {:?}", addr); // remove direct addrs to force relay usage - addr.addrs.retain(|addr| !matches!(addr, AddrType::Ip(_))); + addr.addrs + .retain(|addr| !matches!(addr, TransportAddr::Ip(_))); let conn = client.connect(addr, TEST_ALPN).await?; let (mut send, mut recv) = conn.open_bi().await.e()?; @@ -2509,7 +2510,8 @@ mod tests { assert_eq!(addr.relay_urls().next(), Some(&new_relay_url)); // remove direct addrs to force relay usage - addr.addrs.retain(|addr| !matches!(addr, AddrType::Ip(_))); + addr.addrs + .retain(|addr| !matches!(addr, TransportAddr::Ip(_))); let conn = client.connect(addr, TEST_ALPN).await?; let (mut send, mut recv) = conn.open_bi().await.e()?; diff --git a/iroh/src/lib.rs b/iroh/src/lib.rs index 5998a4a7186..eb109682d1b 100644 --- a/iroh/src/lib.rs +++ b/iroh/src/lib.rs @@ -272,8 +272,8 @@ pub mod protocol; pub use endpoint::{Endpoint, RelayMode}; pub use iroh_base::{ - AddrType, EndpointAddr, EndpointId, KeyParsingError, PublicKey, RelayUrl, RelayUrlParseError, - SecretKey, Signature, SignatureError, + EndpointAddr, EndpointId, KeyParsingError, PublicKey, RelayUrl, RelayUrlParseError, SecretKey, + Signature, SignatureError, TransportAddr, }; pub use iroh_relay::{RelayConfig, RelayMap, endpoint_info}; pub use n0_watcher::Watcher; diff --git a/iroh/src/magicsock.rs b/iroh/src/magicsock.rs index adf4266526a..52f3fdfac78 100644 --- a/iroh/src/magicsock.rs +++ b/iroh/src/magicsock.rs @@ -30,7 +30,7 @@ use std::{ use bytes::Bytes; use data_encoding::HEXLOWER; -use iroh_base::{AddrType, EndpointAddr, EndpointId, PublicKey, RelayUrl, SecretKey}; +use iroh_base::{EndpointAddr, EndpointId, PublicKey, RelayUrl, SecretKey, TransportAddr}; use iroh_relay::{RelayConfig, RelayMap}; use n0_future::{ task::{self, AbortOnDropHandle}, @@ -410,7 +410,7 @@ impl MagicSock { ) -> Result<(), AddEndpointAddrError> { let mut pruned: usize = 0; for my_addr in self.direct_addrs.sockaddrs() { - if addr.addrs.remove(&AddrType::Ip(my_addr)) { + if addr.addrs.remove(&TransportAddr::Ip(my_addr)) { warn!( endpoint_id=%addr.id.fmt_short(), %my_addr, %source, "not adding our addr for endpoint"); pruned += 1; } @@ -1157,7 +1157,11 @@ impl MagicSock { /// Called whenever our addresses or home relay endpoint changes. fn publish_my_addr(&self) { let relay_url = self.my_relay(); - let mut addrs: BTreeSet<_> = self.direct_addrs.sockaddrs().map(AddrType::Ip).collect(); + let mut addrs: BTreeSet<_> = self + .direct_addrs + .sockaddrs() + .map(TransportAddr::Ip) + .collect(); let user_data = self .discovery_user_data @@ -1169,7 +1173,7 @@ impl MagicSock { return; } if let Some(url) = relay_url { - addrs.insert(AddrType::Relay(url)); + addrs.insert(TransportAddr::Relay(url)); } let data = EndpointData::new(addrs).with_user_data(user_data); @@ -2542,7 +2546,7 @@ mod tests { use std::{collections::BTreeSet, net::SocketAddr, sync::Arc, time::Duration}; use data_encoding::HEXLOWER; - use iroh_base::{AddrType, EndpointAddr, EndpointId, PublicKey}; + use iroh_base::{EndpointAddr, EndpointId, PublicKey, TransportAddr}; use n0_future::{StreamExt, time}; use n0_snafu::{Result, ResultExt}; use n0_watcher::Watcher; @@ -2673,7 +2677,7 @@ mod tests { let addr = EndpointAddr { id: me.public(), - addrs: new_addrs.iter().copied().map(AddrType::Ip).collect(), + addrs: new_addrs.iter().copied().map(TransportAddr::Ip).collect(), }; m.endpoint.magic_sock().add_test_addr(addr); } @@ -3236,7 +3240,7 @@ mod tests { .direct_addresses() .get() .into_iter() - .map(|x| AddrType::Ip(x.addr)) + .map(|x| TransportAddr::Ip(x.addr)) .collect(); let endpoint_addr_2 = EndpointAddr { id: endpoint_id_2, @@ -3349,7 +3353,7 @@ mod tests { .direct_addresses() .get() .into_iter() - .map(|x| AddrType::Ip(x.addr)) + .map(|x| TransportAddr::Ip(x.addr)) .collect(); msock_1.endpoint_map.add_endpoint_addr( EndpointAddr { @@ -3412,7 +3416,7 @@ mod tests { // relay url only let addr = EndpointAddr { id: SecretKey::generate(&mut rng).public(), - addrs: [AddrType::Relay("http://my-relay.com".parse().unwrap())] + addrs: [TransportAddr::Relay("http://my-relay.com".parse().unwrap())] .into_iter() .collect(), }; @@ -3425,7 +3429,7 @@ mod tests { // addrs only let addr = EndpointAddr { id: SecretKey::generate(&mut rng).public(), - addrs: [AddrType::Ip("127.0.0.1:1234".parse().unwrap())] + addrs: [TransportAddr::Ip("127.0.0.1:1234".parse().unwrap())] .into_iter() .collect(), }; @@ -3439,8 +3443,8 @@ mod tests { let addr = EndpointAddr { id: SecretKey::generate(&mut rng).public(), addrs: [ - AddrType::Relay("http://my-relay.com".parse().unwrap()), - AddrType::Ip("127.0.0.1:1234".parse().unwrap()), + TransportAddr::Relay("http://my-relay.com".parse().unwrap()), + TransportAddr::Ip("127.0.0.1:1234".parse().unwrap()), ] .into_iter() .collect(), diff --git a/iroh/src/magicsock/endpoint_map/endpoint_state.rs b/iroh/src/magicsock/endpoint_map/endpoint_state.rs index 5c50ced5ac3..7b21d5c28b7 100644 --- a/iroh/src/magicsock/endpoint_map/endpoint_state.rs +++ b/iroh/src/magicsock/endpoint_map/endpoint_state.rs @@ -6,7 +6,7 @@ use std::{ }; use data_encoding::HEXLOWER; -use iroh_base::{AddrType, EndpointAddr, EndpointId, PublicKey, RelayUrl}; +use iroh_base::{EndpointAddr, EndpointId, PublicKey, RelayUrl, TransportAddr}; use n0_future::{ task::{self, AbortOnDropHandle}, time::{self, Duration, Instant}, @@ -1225,11 +1225,11 @@ impl From for EndpointAddr { let mut addrs = info .addrs .into_iter() - .map(|info| AddrType::Ip(info.addr)) + .map(|info| TransportAddr::Ip(info.addr)) .collect::>(); if let Some(url) = info.relay_url { - addrs.insert(AddrType::Relay(url.into())); + addrs.insert(TransportAddr::Relay(url.into())); } EndpointAddr { From a984906ede3527b1d6f586599c92893583b93b2b Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 18 Oct 2025 14:55:23 +0200 Subject: [PATCH 6/9] more cleanup and fixes --- iroh-base/src/endpoint_addr.rs | 15 ++++------ iroh-dns-server/examples/publish.rs | 2 +- iroh-relay/src/endpoint_info.rs | 17 +++++++---- iroh/bench/src/iroh.rs | 2 +- iroh/src/discovery/mdns.rs | 28 ++++++++++--------- iroh/src/discovery/pkarr.rs | 4 +-- iroh/src/discovery/pkarr/dht.rs | 6 ++-- iroh/src/discovery/static_provider.rs | 7 +++-- iroh/src/endpoint.rs | 6 ++-- iroh/src/magicsock.rs | 10 +++---- iroh/src/magicsock/endpoint_map.rs | 20 ++++++------- .../magicsock/endpoint_map/endpoint_state.rs | 6 ++-- 12 files changed, 63 insertions(+), 60 deletions(-) diff --git a/iroh-base/src/endpoint_addr.rs b/iroh-base/src/endpoint_addr.rs index 25ec26b68f2..e78aae13acd 100644 --- a/iroh-base/src/endpoint_addr.rs +++ b/iroh-base/src/endpoint_addr.rs @@ -55,7 +55,7 @@ pub enum TransportAddr { } impl EndpointAddr { - /// Creates a new [`EndpointAddr`] with no `relay_url` and no `direct_addresses`. + /// Creates a new [`EndpointAddr`] with no addresses. pub fn new(id: PublicKey) -> Self { EndpointAddr { id, @@ -69,11 +69,8 @@ impl EndpointAddr { self } - /// Adds the given direct addresses. - pub fn with_direct_addresses( - mut self, - addresses: impl IntoIterator, - ) -> Self { + /// Adds the given IP addresses. + pub fn with_ip_addresses(mut self, addresses: impl IntoIterator) -> Self { for addr in addresses.into_iter() { self.addrs.insert(TransportAddr::Ip(addr)); } @@ -93,7 +90,7 @@ impl EndpointAddr { self.addrs.is_empty() } - /// Returns the direct addresses of this peer. + /// Returns the IP addresses of this peer. pub fn ip_addresses(&self) -> impl Iterator { self.addrs.iter().filter_map(|addr| match addr { TransportAddr::Ip(addr) => Some(addr), @@ -112,12 +109,12 @@ impl EndpointAddr { impl From<(PublicKey, Option, &[SocketAddr])> for EndpointAddr { fn from(value: (PublicKey, Option, &[SocketAddr])) -> Self { - let (id, relay_url, direct_addresses_iter) = value; + let (id, relay_url, ip_addrs_iter) = value; let mut addrs = BTreeSet::new(); if let Some(url) = relay_url { addrs.insert(TransportAddr::Relay(url)); } - for addr in direct_addresses_iter { + for addr in ip_addrs_iter { addrs.insert(TransportAddr::Ip(*addr)); } EndpointAddr { id, addrs } diff --git a/iroh-dns-server/examples/publish.rs b/iroh-dns-server/examples/publish.rs index a5dc9e4ee6e..74ab74aad2e 100644 --- a/iroh-dns-server/examples/publish.rs +++ b/iroh-dns-server/examples/publish.rs @@ -105,7 +105,7 @@ async fn main() -> Result<()> { let pkarr = PkarrRelayClient::new(pkarr_relay_url); let endpoint_info = EndpointInfo::new(endpoint_id) .with_relay_url(relay_url.map(Into::into)) - .with_direct_addresses(args.addr.into_iter().collect()) + .with_ip_addresses(args.addr.into_iter().collect()) .with_user_data(args.user_data); let signed_packet = endpoint_info.to_pkarr_signed_packet(&secret_key, 30)?; tracing::debug!("signed packet: {signed_packet:?}"); diff --git a/iroh-relay/src/endpoint_info.rs b/iroh-relay/src/endpoint_info.rs index cc9994439e4..f232989ef34 100644 --- a/iroh-relay/src/endpoint_info.rs +++ b/iroh-relay/src/endpoint_info.rs @@ -185,7 +185,7 @@ impl EndpointData { } /// Removes all direct addresses from the endpoint data. - pub fn clear_direct_addresses(&mut self) { + pub fn clear_ip_addresses(&mut self) { self.addrs .retain(|addr| !matches!(addr, TransportAddr::Ip(_))); } @@ -212,6 +212,11 @@ impl EndpointData { pub fn addrs(&self) -> impl Iterator { self.addrs.iter() } + + /// Does this have any addresses? + pub fn has_addrs(&self) -> bool { + !self.addrs.is_empty() + } } impl From for EndpointData { @@ -309,7 +314,7 @@ impl From<&TxtAttrs> for EndpointInfo { .flatten() .filter_map(|s| Url::parse(s).ok()) .map(|url| TransportAddr::Relay(url.into())); - let direct_addresses = attrs + let ip_addrs = attrs .get(&IrohAttr::Addr) .into_iter() .flatten() @@ -324,7 +329,7 @@ impl From<&TxtAttrs> for EndpointInfo { .and_then(|s| UserData::from_str(s).ok()); let mut data = EndpointData::default(); data.set_user_data(user_data); - data.add_addrs(relay_urls.chain(direct_addresses)); + data.add_addrs(relay_urls.chain(ip_addrs)); Self { endpoint_id, data } } @@ -362,8 +367,8 @@ impl EndpointInfo { } /// Sets the direct addresses and returns the updated endpoint info. - pub fn with_direct_addresses(mut self, direct_addresses: BTreeSet) -> Self { - self.data = self.data.with_ip_addresses(direct_addresses); + pub fn with_ip_addresses(mut self, addrs: BTreeSet) -> Self { + self.data = self.data.with_ip_addresses(addrs); self } @@ -780,7 +785,7 @@ mod tests { "1992d53c02cdc04566e5c0edb1ce83305cd550297953a047a445ea3264b54b18", )?) .with_relay_url(Some("https://euw1-1.relay.iroh.network./".parse()?)) - .with_direct_addresses(BTreeSet::from([ + .with_ip_addresses(BTreeSet::from([ "192.168.96.145:60165".parse().unwrap(), "213.208.157.87:60165".parse().unwrap(), ])); diff --git a/iroh/bench/src/iroh.rs b/iroh/bench/src/iroh.rs index d43d5314c07..25ae818f215 100644 --- a/iroh/bench/src/iroh.rs +++ b/iroh/bench/src/iroh.rs @@ -54,7 +54,7 @@ pub fn server_endpoint( let addr = ep.bound_sockets(); let addr = SocketAddr::new("127.0.0.1".parse().unwrap(), addr[0].port()); - let mut addr = EndpointAddr::new(ep.id()).with_direct_addresses([addr]); + let mut addr = EndpointAddr::new(ep.id()).with_ip_addresses([addr]); if let Some(relay_url) = relay_url { addr = addr.with_relay_url(relay_url.clone()); } diff --git a/iroh/src/discovery/mdns.rs b/iroh/src/discovery/mdns.rs index ff052ab8ad0..3ba0fbdc050 100644 --- a/iroh/src/discovery/mdns.rs +++ b/iroh/src/discovery/mdns.rs @@ -464,7 +464,7 @@ impl MdnsDiscovery { .with_callback(callback) .with_ip_class(IpClass::Auto); if advertise { - let addrs = MdnsDiscovery::socketaddrs_to_addrs(&socketaddrs); + let addrs = MdnsDiscovery::socketaddrs_to_addrs(socketaddrs.iter()); for addr in addrs { discoverer = discoverer.with_addrs(addr.0, addr.1); } @@ -474,7 +474,9 @@ impl MdnsDiscovery { .map_err(|e| IntoDiscoveryError::from_err("mdns", e)) } - fn socketaddrs_to_addrs(socketaddrs: &BTreeSet) -> HashMap> { + fn socketaddrs_to_addrs<'a>( + socketaddrs: impl Iterator, + ) -> HashMap> { let mut addrs: HashMap> = HashMap::default(); for socketaddr in socketaddrs { addrs @@ -487,7 +489,7 @@ impl MdnsDiscovery { } fn peer_to_discovery_item(peer: &Peer, endpoint_id: &EndpointId) -> DiscoveryItem { - let direct_addresses: BTreeSet = peer + let ip_addrs: BTreeSet = peer .addrs() .iter() .map(|(ip, port)| SocketAddr::new(*ip, *port)) @@ -506,7 +508,7 @@ fn peer_to_discovery_item(peer: &Peer, endpoint_id: &EndpointId) -> DiscoveryIte None }; let endpoint_info = EndpointInfo::new(*endpoint_id) - .with_direct_addresses(direct_addresses) + .with_ip_addresses(ip_addrs) .with_user_data(user_data); DiscoveryItem::new(endpoint_info, NAME, None) } @@ -543,7 +545,7 @@ mod tests { /// This module's name signals nextest to run test in a single thread (no other concurrent /// tests) mod run_in_isolation { - use iroh_base::SecretKey; + use iroh_base::{SecretKey, TransportAddr}; use n0_future::StreamExt; use n0_snafu::{Error, Result, ResultExt}; use rand::{CryptoRng, SeedableRng}; @@ -566,7 +568,7 @@ mod tests { // make addr info for discoverer b let user_data: UserData = "foobar".parse()?; let endpoint_data = - EndpointData::new(None, BTreeSet::from(["0.0.0.0:11111".parse().unwrap()])) + EndpointData::new([TransportAddr::Ip("0.0.0.0:11111".parse().unwrap())]) .with_user_data(Some(user_data.clone())); // resolve twice to ensure we can create separate streams for the same endpoint_id @@ -621,7 +623,7 @@ mod tests { // publish discovery_b's address let endpoint_data = - EndpointData::new(None, BTreeSet::from(["0.0.0.0:11111".parse().unwrap()])) + EndpointData::new([TransportAddr::Ip("0.0.0.0:11111".parse().unwrap())]) .with_user_data(Some("".parse()?)); discovery_b.publish(&endpoint_data); @@ -680,7 +682,7 @@ mod tests { let (_, discovery) = make_discoverer(&mut rng, false)?; let endpoint_data = - EndpointData::new(None, BTreeSet::from(["0.0.0.0:11111".parse().unwrap()])); + EndpointData::new([TransportAddr::Ip("0.0.0.0:11111".parse().unwrap())]); for i in 0..num_endpoints { let (endpoint_id, discovery) = make_discoverer(&mut rng, true)?; @@ -730,11 +732,11 @@ mod tests { let (endpoint_id_c, discovery_c) = make_discoverer(&mut rng, true)?; let endpoint_data_c = - EndpointData::new(None, BTreeSet::from(["0.0.0.0:22222".parse().unwrap()])); + EndpointData::new([TransportAddr::Ip("0.0.0.0:22222".parse().unwrap())]); discovery_c.publish(&endpoint_data_c); let endpoint_data_b = - EndpointData::new(None, BTreeSet::from(["0.0.0.0:11111".parse().unwrap()])); + EndpointData::new([TransportAddr::Ip("0.0.0.0:11111".parse().unwrap())]); discovery_b.publish(&endpoint_data_b); let mut stream_c = discovery_a.resolve(endpoint_id_c).unwrap(); @@ -779,15 +781,15 @@ mod tests { .build(id_c)?; let endpoint_data_a = - EndpointData::new(None, BTreeSet::from(["0.0.0.0:11111".parse().unwrap()])); + EndpointData::new([TransportAddr::Ip("0.0.0.0:11111".parse().unwrap())]); discovery_a.publish(&endpoint_data_a); let endpoint_data_b = - EndpointData::new(None, BTreeSet::from(["0.0.0.0:22222".parse().unwrap()])); + EndpointData::new([TransportAddr::Ip("0.0.0.0:22222".parse().unwrap())]); discovery_b.publish(&endpoint_data_b); let endpoint_data_c = - EndpointData::new(None, BTreeSet::from(["0.0.0.0:33333".parse().unwrap()])); + EndpointData::new([TransportAddr::Ip("0.0.0.0:33333".parse().unwrap())]); discovery_c.publish(&endpoint_data_c); let mut stream_a = discovery_a.resolve(id_b).unwrap(); diff --git a/iroh/src/discovery/pkarr.rs b/iroh/src/discovery/pkarr.rs index ba6568e7645..97467c7ad1a 100644 --- a/iroh/src/discovery/pkarr.rs +++ b/iroh/src/discovery/pkarr.rs @@ -316,8 +316,8 @@ impl PkarrPublisher { pub fn update_endpoint_data(&self, data: &EndpointData) { let mut data = data.clone(); if data.relay_urls().next().is_some() { - // If relay url is set: only publish relay url, and no direct addrs. - data.clear_direct_addresses(); + // If relay url is set: only publish relay url, and no addrs. + data.clear_ip_addresses(); } let info = EndpointInfo::from_parts(self.endpoint_id, data); self.watchable.set(Some(info)).ok(); diff --git a/iroh/src/discovery/pkarr/dht.rs b/iroh/src/discovery/pkarr/dht.rs index 8080071444a..42eb80f89c1 100644 --- a/iroh/src/discovery/pkarr/dht.rs +++ b/iroh/src/discovery/pkarr/dht.rs @@ -292,14 +292,14 @@ impl Discovery for DhtDiscovery { tracing::debug!("no keypair set, not publishing"); return; }; - if data.relay_url().is_none() && data.ip_addresses().is_empty() { + if !data.has_addrs() { tracing::debug!("no relay url or direct addresses in endpoint data, not publishing"); return; } tracing::debug!("publishing {data:?}"); let mut info = EndpointInfo::from_parts(keypair.public(), data.clone()); if !self.0.include_direct_addresses { - info.clear_direct_addresses(); + info.clear_ip_addresses(); } let Ok(signed_packet) = info.to_pkarr_signed_packet(keypair, self.0.ttl) else { tracing::warn!("failed to create signed packet"); @@ -369,7 +369,7 @@ mod tests { .collect::>() .await; for item in items.into_iter().flatten() { - if let Some(url) = item.relay_url() { + for url in item.relay_urls() { found_relay_urls.insert(url.clone()); } } diff --git a/iroh/src/discovery/static_provider.rs b/iroh/src/discovery/static_provider.rs index 4b299dce088..d956210d399 100644 --- a/iroh/src/discovery/static_provider.rs +++ b/iroh/src/discovery/static_provider.rs @@ -37,7 +37,7 @@ use super::{Discovery, DiscoveryError, DiscoveryItem, EndpointData, EndpointInfo /// # Examples /// /// ```rust -/// use iroh::{Endpoint, EndpointAddr, discovery::static_provider::StaticProvider}; +/// use iroh::{Endpoint, EndpointAddr, TransportAddr, discovery::static_provider::StaticProvider}; /// use iroh_base::SecretKey; /// /// # #[tokio::main] @@ -55,8 +55,9 @@ use super::{Discovery, DiscoveryError, DiscoveryItem, EndpointData, EndpointInfo /// // You can pass either `EndpointInfo` or `EndpointAddr` to `add_endpoint_info`. /// discovery.add_endpoint_info(EndpointAddr { /// endpoint_id, -/// relay_url: Some("https://example.com".parse()?), -/// direct_addresses: Default::default(), +/// addrs: [TransportAddr::Relay("https://example.com".parse()?)] +/// .into_iter() +/// .collect(), /// }); /// /// # Ok(()) diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 7053a51d7e3..a311374e0d6 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -857,8 +857,8 @@ impl Endpoint { /// that initial call to [`Endpoint::online`], to understand if your /// endpoint is no longer able to be connected to by endpoints outside /// of the private or local network, watch for changes in it's [`EndpointAddr`]. - /// If the `relay_url` is `None` or if there are no `direct_addresses` in - /// the [`EndpointAddr`], you may not be dialable by other endpoints on the internet. + /// If there are no `addrs`in the [`EndpointAddr`], you may not be dialable by other endpoints + /// on the internet. /// /// /// The `EndpointAddr` will change as: @@ -870,7 +870,7 @@ impl Endpoint { /// [`RelayUrl`]: crate::RelayUrl #[cfg(not(wasm_browser))] pub fn watch_addr(&self) -> impl n0_watcher::Watcher + use<> { - let watch_addrs = self.msock.direct_addresses(); + let watch_addrs = self.msock.ip_addresses(); let watch_relay = self.msock.home_relay(); let endpoint_id = self.id(); diff --git a/iroh/src/magicsock.rs b/iroh/src/magicsock.rs index 52f3fdfac78..e565910e276 100644 --- a/iroh/src/magicsock.rs +++ b/iroh/src/magicsock.rs @@ -329,7 +329,7 @@ impl MagicSock { /// /// [`Watcher`]: n0_watcher::Watcher /// [`Watcher::initialized`]: n0_watcher::Watcher::initialized - pub(crate) fn direct_addresses(&self) -> n0_watcher::Direct> { + pub(crate) fn ip_addresses(&self) -> n0_watcher::Direct> { self.direct_addrs.addrs.watch() } @@ -3080,12 +3080,12 @@ mod tests { let ms = Handle::new(default_options(&mut rng)).await.unwrap(); // See if we can get endpoints. - let eps0 = ms.direct_addresses().get(); + let eps0 = ms.ip_addresses().get(); println!("{eps0:?}"); assert!(!eps0.is_empty()); // Getting the endpoints again immediately should give the same results. - let eps1 = ms.direct_addresses().get(); + let eps1 = ms.ip_addresses().get(); println!("{eps1:?}"); assert_eq!(eps0, eps1); } @@ -3237,7 +3237,7 @@ mod tests { let _accept_task = AbortOnDropHandle::new(accept_task); let addrs = msock_2 - .direct_addresses() + .ip_addresses() .get() .into_iter() .map(|x| TransportAddr::Ip(x.addr)) @@ -3350,7 +3350,7 @@ mod tests { // Provide correct addressing information let addrs = msock_2 - .direct_addresses() + .ip_addresses() .get() .into_iter() .map(|x| TransportAddr::Ip(x.addr)) diff --git a/iroh/src/magicsock/endpoint_map.rs b/iroh/src/magicsock/endpoint_map.rs index c97dcd3eac4..2d6e8e30ce7 100644 --- a/iroh/src/magicsock/endpoint_map.rs +++ b/iroh/src/magicsock/endpoint_map.rs @@ -419,7 +419,7 @@ impl EndpointMapInner { if let Entry::Occupied(mut entry) = self.by_id.entry(id) { let endpoint = entry.get_mut(); endpoint.remove_direct_addr(&ipp, now, why); - if endpoint.direct_addresses().count() == 0 { + if endpoint.ip_addresses().count() == 0 { let endpoint_id = endpoint.public_key(); let mapped_addr = endpoint.quic_mapped_addr(); self.by_endpoint_key.remove(endpoint_id); @@ -707,7 +707,7 @@ impl EndpointMapInner { continue; }; - for ip_port in ep.direct_addresses() { + for ip_port in ep.ip_addresses() { self.by_ip_port.remove(&ip_port); } @@ -797,10 +797,9 @@ mod tests { let endpoint_addr_a = EndpointAddr::new(endpoint_a) .with_relay_url(relay_x) - .with_direct_addresses(direct_addresses_a); + .with_ip_addresses(direct_addresses_a); let endpoint_addr_b = EndpointAddr::new(endpoint_b).with_relay_url(relay_y); - let endpoint_addr_c = - EndpointAddr::new(endpoint_c).with_direct_addresses(direct_addresses_c); + let endpoint_addr_c = EndpointAddr::new(endpoint_c).with_ip_addresses(direct_addresses_c); let endpoint_addr_d = EndpointAddr::new(endpoint_d); endpoint_map.add_test_addr(endpoint_addr_a); @@ -878,7 +877,7 @@ mod tests { info!("Adding active addresses"); for i in 0..MAX_INACTIVE_DIRECT_ADDRESSES { let addr = SocketAddr::new(LOCALHOST, 5000 + i as u16); - let endpoint_addr = EndpointAddr::new(public_key).with_direct_addresses([addr]); + let endpoint_addr = EndpointAddr::new(public_key).with_ip_addresses([addr]); // add address endpoint_map.add_test_addr(endpoint_addr); // make it active @@ -888,7 +887,7 @@ mod tests { info!("Adding offline/inactive addresses"); for i in 0..MAX_INACTIVE_DIRECT_ADDRESSES * 2 { let addr = SocketAddr::new(LOCALHOST, 6000 + i as u16); - let endpoint_addr = EndpointAddr::new(public_key).with_direct_addresses([addr]); + let endpoint_addr = EndpointAddr::new(public_key).with_ip_addresses([addr]); endpoint_map.add_test_addr(endpoint_addr); } @@ -910,14 +909,14 @@ mod tests { // Half the offline addresses should have been pruned. All the active and alive // addresses should have been kept. assert_eq!( - endpoint.direct_addresses().count(), + endpoint.ip_addresses().count(), MAX_INACTIVE_DIRECT_ADDRESSES * 3 ); // We should have both offline and alive addresses which are not active. assert_eq!( endpoint - .direct_address_states() + .ip_address_states() .filter(|(_addr, state)| !state.is_active()) .count(), MAX_INACTIVE_DIRECT_ADDRESSES * 2 @@ -932,8 +931,7 @@ mod tests { // add one active endpoint and more than MAX_INACTIVE_ENDPOINTS inactive endpoints let active_endpoint = SecretKey::generate(&mut rng).public(); let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 167); - endpoint_map - .add_test_addr(EndpointAddr::new(active_endpoint).with_direct_addresses([addr])); + endpoint_map.add_test_addr(EndpointAddr::new(active_endpoint).with_ip_addresses([addr])); endpoint_map .inner .lock() diff --git a/iroh/src/magicsock/endpoint_map/endpoint_state.rs b/iroh/src/magicsock/endpoint_map/endpoint_state.rs index 7b21d5c28b7..e636c40ec25 100644 --- a/iroh/src/magicsock/endpoint_map/endpoint_state.rs +++ b/iroh/src/magicsock/endpoint_map/endpoint_state.rs @@ -1205,13 +1205,13 @@ impl EndpointState { (udp_addr, relay_url, ping_msgs) } - /// Get the direct addresses for this endpoint. - pub(super) fn direct_addresses(&self) -> impl Iterator + '_ { + /// Get the IP addresses for this endpoint. + pub(super) fn ip_addresses(&self) -> impl Iterator + '_ { self.udp_paths.paths().keys().copied() } #[cfg(test)] - pub(super) fn direct_address_states(&self) -> impl Iterator + '_ { + pub(super) fn ip_address_states(&self) -> impl Iterator + '_ { self.udp_paths.paths().iter() } From 8eb17e3f8d4872dac06d7b68d684430b72ac931b Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Mon, 20 Oct 2025 10:45:46 +0200 Subject: [PATCH 7/9] update tickets and more cleanup --- iroh-base/src/endpoint_addr.rs | 8 +-- iroh-base/src/lib.rs | 5 +- iroh-base/src/ticket.rs | 15 ++--- iroh-base/src/ticket/endpoint.rs | 95 ++++++++++++++++----------- iroh-dns-server/examples/resolve.rs | 2 +- iroh-dns-server/src/lib.rs | 4 +- iroh/examples/transfer.rs | 2 +- iroh/src/discovery/static_provider.rs | 6 +- 8 files changed, 75 insertions(+), 62 deletions(-) diff --git a/iroh-base/src/endpoint_addr.rs b/iroh-base/src/endpoint_addr.rs index e78aae13acd..2218799c13f 100644 --- a/iroh-base/src/endpoint_addr.rs +++ b/iroh-base/src/endpoint_addr.rs @@ -48,10 +48,10 @@ pub struct EndpointAddr { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] #[non_exhaustive] pub enum TransportAddr { - /// IP based addresses - Ip(SocketAddr), /// Relays Relay(RelayUrl), + /// IP based addresses + Ip(SocketAddr), } impl EndpointAddr { @@ -134,10 +134,10 @@ mod tests { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] #[non_exhaustive] enum NewAddrType { - /// IP based addresses - Ip(SocketAddr), /// Relays Relay(RelayUrl), + /// IP based addresses + Ip(SocketAddr), /// New addr type for testing Cool(u16), } diff --git a/iroh-base/src/lib.rs b/iroh-base/src/lib.rs index d1b22d55545..82320ca15fc 100644 --- a/iroh-base/src/lib.rs +++ b/iroh-base/src/lib.rs @@ -3,9 +3,8 @@ #![deny(missing_docs, rustdoc::broken_intra_doc_links)] #![cfg_attr(not(test), deny(clippy::unwrap_used))] -// TODO: move to own crate -//#[cfg(feature = "ticket")] -// b mod ticket; +#[cfg(feature = "ticket")] +pub mod ticket; #[cfg(feature = "key")] mod endpoint_addr; diff --git a/iroh-base/src/ticket.rs b/iroh-base/src/ticket.rs index 58cc3571f75..dcf5dd1bc83 100644 --- a/iroh-base/src/ticket.rs +++ b/iroh-base/src/ticket.rs @@ -3,13 +3,13 @@ //! ticket would contain the hash of the data as well as information about how to reach the //! provider. -use std::{collections::BTreeSet, net::SocketAddr}; +use std::collections::BTreeSet; use nested_enum_utils::common_fields; use serde::{Deserialize, Serialize}; use snafu::{Backtrace, Snafu}; -use crate::{key::EndpointId, relay_url::RelayUrl}; +use crate::{TransportAddr, key::EndpointId}; mod endpoint; @@ -103,13 +103,12 @@ impl ParseError { } #[derive(Serialize, Deserialize)] -struct Variant0NodeAddr { - node_id: EndpointId, - info: Variant0AddrInfo, +struct Variant1EndpointAddr { + id: EndpointId, + info: Variant1AddrInfo, } #[derive(Serialize, Deserialize)] -struct Variant0AddrInfo { - relay_url: Option, - direct_addresses: BTreeSet, +struct Variant1AddrInfo { + addrs: BTreeSet, } diff --git a/iroh-base/src/ticket/endpoint.rs b/iroh-base/src/ticket/endpoint.rs index 4ab285c663f..9883c398c9d 100644 --- a/iroh-base/src/ticket/endpoint.rs +++ b/iroh-base/src/ticket/endpoint.rs @@ -4,7 +4,7 @@ use std::str::FromStr; use serde::{Deserialize, Serialize}; -use super::{Variant0AddrInfo, Variant0NodeAddr}; +use super::{Variant1AddrInfo, Variant1EndpointAddr}; use crate::{ endpoint_addr::EndpointAddr, ticket::{self, ParseError, Ticket}, @@ -14,8 +14,7 @@ use crate::{ /// /// Contains /// - The [`EndpointId`] of the endpoint to connect to (a 32-byte ed25519 public key). -/// - If used, the ['RelayUrl`] of on which the endpoint can be reached. -/// - Any *direct addresses* on which the endpoint might be reachable. +/// - Any known [`TransportAddr`]s on which the endpoint can be reached. /// /// This allows establishing a connection to the endpoint in most circumstances where it is /// possible to do so. @@ -27,35 +26,34 @@ use crate::{ /// [`EndpointId`]: crate::key::EndpointId /// [`Display`]: std::fmt::Display /// [`FromStr`]: std::str::FromStr -/// ['RelayUrl`]: crate::relay_url::RelayUrl +/// [`TransportAddr`]: crate::TransportAddr #[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)] #[display("{}", Ticket::serialize(self))] pub struct EndpointTicket { - node: EndpointAddr, + addr: EndpointAddr, } /// Wire format for [`EndpointTicket`]. #[derive(Serialize, Deserialize)] enum TicketWireFormat { - Variant0(Variant0NodeTicket), + Variant0(Variant1EndpointTicket), } // Legacy #[derive(Serialize, Deserialize)] -struct Variant0NodeTicket { - node: Variant0NodeAddr, +struct Variant1EndpointTicket { + addr: Variant1EndpointAddr, } impl Ticket for EndpointTicket { - const KIND: &'static str = "node"; + const KIND: &'static str = "endpoint"; fn to_bytes(&self) -> Vec { - let data = TicketWireFormat::Variant0(Variant0NodeTicket { - node: Variant0NodeAddr { - node_id: self.node.id, - info: Variant0AddrInfo { - relay_url: self.node.relay_url.clone(), - direct_addresses: self.node.direct_addresses.clone(), + let data = TicketWireFormat::Variant0(Variant1EndpointTicket { + addr: Variant1EndpointAddr { + id: self.addr.id, + info: Variant1AddrInfo { + addrs: self.addr.addrs.clone(), }, }, }); @@ -64,12 +62,11 @@ impl Ticket for EndpointTicket { fn from_bytes(bytes: &[u8]) -> Result { let res: TicketWireFormat = postcard::from_bytes(bytes)?; - let TicketWireFormat::Variant0(Variant0NodeTicket { node }) = res; + let TicketWireFormat::Variant0(Variant1EndpointTicket { addr }) = res; Ok(Self { - node: EndpointAddr { - endpoint_id: node.node_id, - relay_url: node.info.relay_url, - direct_addresses: node.info.direct_addresses, + addr: EndpointAddr { + id: addr.id, + addrs: addr.info.addrs, }, }) } @@ -85,27 +82,27 @@ impl FromStr for EndpointTicket { impl EndpointTicket { /// Creates a new ticket. - pub fn new(node: EndpointAddr) -> Self { - Self { node } + pub fn new(addr: EndpointAddr) -> Self { + Self { addr } } /// The [`EndpointAddr`] of the provider for this ticket. pub fn endpoint_addr(&self) -> &EndpointAddr { - &self.node + &self.addr } } impl From for EndpointTicket { /// Creates a ticket from given addressing info. fn from(addr: EndpointAddr) -> Self { - Self { node: addr } + Self { addr } } } impl From for EndpointAddr { /// Returns the addressing info from given ticket. fn from(ticket: EndpointTicket) -> Self { - ticket.node + ticket.addr } } @@ -114,8 +111,8 @@ impl Serialize for EndpointTicket { if serializer.is_human_readable() { serializer.serialize_str(&self.to_string()) } else { - let EndpointTicket { node } = self; - (node).serialize(serializer) + let EndpointTicket { addr } = self; + (addr).serialize(serializer) } } } @@ -140,15 +137,17 @@ mod tests { use rand::SeedableRng; use super::*; - use crate::key::{PublicKey, SecretKey}; + use crate::{ + TransportAddr, + key::{PublicKey, SecretKey}, + }; fn make_ticket() -> EndpointTicket { let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(0u64); let peer = SecretKey::generate(&mut rng).public(); let addr = SocketAddr::from((Ipv4Addr::LOCALHOST, 1234)); - let relay_url = None; EndpointTicket { - node: EndpointAddr::from_parts(peer, relay_url, [addr]), + addr: EndpointAddr::from_parts(peer, [TransportAddr::Ip(addr)]), } } @@ -175,17 +174,19 @@ mod tests { .unwrap(); let ticket = EndpointTicket { - node: EndpointAddr::from_parts( + addr: EndpointAddr::from_parts( endpoint_id, - Some("http://derp.me./".parse().unwrap()), - ["127.0.0.1:1024".parse().unwrap()], + [ + TransportAddr::Relay("http://derp.me./".parse().unwrap()), + TransportAddr::Ip("127.0.0.1:1024".parse().unwrap()), + ], ), }; let base32 = data_encoding::BASE32_NOPAD .decode( ticket .to_string() - .strip_prefix("node") + .strip_prefix("endpoint") .unwrap() .to_ascii_uppercase() .as_bytes(), @@ -194,20 +195,34 @@ mod tests { let expected = [ // variant "00", - // node id, 32 bytes, see above + // endpoint id, 32 bytes, see above "ae58ff8833241ac82d6ff7611046ed67b5072d142c588d0063e942d9a75502b6", - // relay url present - "01", - // relay url, 16 bytes, see above + // two addrs + "02", + // TransportAddr: Relay + "00", + // 16 bytes "10", + // RelayUrl "687474703a2f2f646572702e6d652e2f", - // one direct address + // TransportAddr: IP "01", - // ipv4 + // IPv4 "00", // address, see above "7f0000018008", ]; + + // 00ae58ff8833241ac82d6ff7611046ed67b5072d142c588d0063e942d9a75502b6 + // 02 + // 00 + // 10 + // 687474703a2f2f646572702e6d652e2f + // 01 + // 00 + // 7f0000018008 + dbg!(&expected); + dbg!(HEXLOWER.encode(&base32)); let expected = HEXLOWER.decode(expected.concat().as_bytes()).unwrap(); assert_eq!(base32, expected); } diff --git a/iroh-dns-server/examples/resolve.rs b/iroh-dns-server/examples/resolve.rs index 18b622f3cef..1b7e1219df5 100644 --- a/iroh-dns-server/examples/resolve.rs +++ b/iroh-dns-server/examples/resolve.rs @@ -79,7 +79,7 @@ async fn main() -> Result<()> { Command::Domain { domain } => resolver.lookup_endpoint_by_domain_name(&domain).await?, }; println!("resolved endpoint {}", resolved.endpoint_id); - if let Some(url) = resolved.relay_url() { + for url in resolved.relay_urls() { println!(" relay={url}") } for addr in resolved.ip_addresses() { diff --git a/iroh-dns-server/src/lib.rs b/iroh-dns-server/src/lib.rs index c381a1774f2..17597273ee0 100644 --- a/iroh-dns-server/src/lib.rs +++ b/iroh-dns-server/src/lib.rs @@ -183,7 +183,7 @@ mod tests { 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)); + assert_eq!(res.relay_urls().next(), Some(&relay_url)); server.shutdown().await?; Ok(()) @@ -257,7 +257,7 @@ mod tests { 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)); + assert_eq!(res.relay_urls().next(), Some(&relay_url)); server.shutdown().await?; Ok(()) diff --git a/iroh/examples/transfer.rs b/iroh/examples/transfer.rs index 35fa8c1105a..6d2839df6dd 100644 --- a/iroh/examples/transfer.rs +++ b/iroh/examples/transfer.rs @@ -392,7 +392,7 @@ async fn provide(endpoint: Endpoint, size: u64) -> Result<()> { async fn fetch(endpoint: Endpoint, ticket: &str) -> Result<()> { let me = endpoint.id().fmt_short(); let ticket: EndpointTicket = ticket.parse()?; - let remote_endpoint_id = ticket.endpoint_addr().endpoint_id; + let remote_endpoint_id = ticket.endpoint_addr().id; let start = Instant::now(); // Attempt to connect, over the given ALPN. diff --git a/iroh/src/discovery/static_provider.rs b/iroh/src/discovery/static_provider.rs index d956210d399..a1764026039 100644 --- a/iroh/src/discovery/static_provider.rs +++ b/iroh/src/discovery/static_provider.rs @@ -50,11 +50,11 @@ use super::{Discovery, DiscoveryError, DiscoveryItem, EndpointData, EndpointInfo /// .bind() /// .await?; /// -/// // Sometime later add a RelayUrl for a fake EndpointId. -/// let endpoint_id = SecretKey::from_bytes(&[0u8; 32]).public(); // Do not use fake secret keys! +/// // Sometime later add a RelayUrl for our endpoint. +/// let id = SecretKey::generate(&mut rand::rng()).public(); /// // You can pass either `EndpointInfo` or `EndpointAddr` to `add_endpoint_info`. /// discovery.add_endpoint_info(EndpointAddr { -/// endpoint_id, +/// id, /// addrs: [TransportAddr::Relay("https://example.com".parse()?)] /// .into_iter() /// .collect(), From 5a6b450285ee4d2bae6cc5314b6ee9c1ddad7869 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Mon, 20 Oct 2025 10:51:59 +0200 Subject: [PATCH 8/9] fixup wasm --- iroh/src/endpoint.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index a311374e0d6..72d76f237fe 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -21,7 +21,7 @@ use std::{ }; use ed25519_dalek::{VerifyingKey, pkcs8::DecodePublicKey}; -use iroh_base::{EndpointAddr, EndpointId, RelayUrl, SecretKey}; +use iroh_base::{EndpointAddr, EndpointId, RelayUrl, SecretKey, TransportAddr}; use iroh_relay::{RelayConfig, RelayMap}; use n0_future::time::Duration; use n0_watcher::Watcher; @@ -877,8 +877,6 @@ impl Endpoint { watch_addrs .or(watch_relay) .map(move |(addrs, relays)| { - use iroh_base::TransportAddr; - debug_assert!(!addrs.is_empty(), "direct addresses must never be empty"); EndpointAddr::from_parts( @@ -906,7 +904,7 @@ impl Endpoint { let endpoint_id = self.id(); watch_relay .map(move |mut relays| { - EndpointAddr::from_parts(endpoint_id, relays.pop(), std::iter::empty()) + EndpointAddr::from_parts(endpoint_id, relays.into_iter().map(TransportAddr::Relay)) }) .expect("watchable is alive - cannot be disconnected yet") } From 6aa21d3c686e3c7d91159ee1c8b70afe66fc359d Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Mon, 20 Oct 2025 15:22:45 +0200 Subject: [PATCH 9/9] apply some feedback and normalize to _addrs --- iroh-base/src/endpoint_addr.rs | 63 +++++++++---------- iroh-base/src/ticket/endpoint.rs | 6 +- iroh-dns-server/examples/publish.rs | 2 +- iroh-dns-server/examples/resolve.rs | 2 +- iroh-relay/src/endpoint_info.rs | 14 ++--- iroh/bench/src/iroh.rs | 2 +- iroh/examples/0rtt.rs | 2 +- iroh/examples/connect-unreliable.rs | 2 +- iroh/examples/connect.rs | 2 +- iroh/examples/listen-unreliable.rs | 2 +- iroh/examples/listen.rs | 2 +- iroh/examples/transfer.rs | 2 +- iroh/src/discovery/mdns.rs | 4 +- iroh/src/discovery/pkarr.rs | 2 +- iroh/src/discovery/pkarr/dht.rs | 2 +- iroh/src/endpoint.rs | 6 +- iroh/src/magicsock.rs | 14 ++--- iroh/src/magicsock/endpoint_map.rs | 31 +++++---- .../magicsock/endpoint_map/endpoint_state.rs | 4 +- 19 files changed, 80 insertions(+), 84 deletions(-) diff --git a/iroh-base/src/endpoint_addr.rs b/iroh-base/src/endpoint_addr.rs index 2218799c13f..342f472ec41 100644 --- a/iroh-base/src/endpoint_addr.rs +++ b/iroh-base/src/endpoint_addr.rs @@ -18,20 +18,20 @@ use crate::{EndpointId, PublicKey, RelayUrl}; /// contact the endpoint. /// /// To establish a network connection to an endpoint both the [`EndpointId`] and one or more network -/// paths are needed. The network paths can come from various sources: +/// paths are needed. The network paths can come from various sources, current sources can come from /// /// - A [discovery] service which can provide routing information for a given [`EndpointId`]. /// /// - A [`RelayUrl`] of the endpoint's [home relay], this allows establishing the connection via /// the Relay server and is very reliable. /// -/// - One or more *direct addresses* on which the endpoint might be reachable. Depending on the +/// - One or more *IP based addresses* on which the endpoint might be reachable. Depending on the /// network location of both endpoints it might not be possible to establish a direct /// connection without the help of a [Relay server]. /// /// This structure will always contain the required [`EndpointId`] and will contain an optional -/// number of network-level addressing information. It is a generic addressing type used -/// whenever a connection to other endpoints needs to be established. +/// number of other addressing information. It is a generic addressing type used whenever a connection +/// to other endpoints needs to be established. /// /// [discovery]: https://docs.rs/iroh/*/iroh/index.html#endpoint-discovery /// [home relay]: https://docs.rs/iroh/*/iroh/relay/index.html @@ -55,7 +55,10 @@ pub enum TransportAddr { } impl EndpointAddr { - /// Creates a new [`EndpointAddr`] with no addresses. + /// Creates a new [`EndpointAddr`] with no network level addresses. + /// + /// This still is usable with e.g. a discovery service to establish a connection, + /// depending on the situation. pub fn new(id: PublicKey) -> Self { EndpointAddr { id, @@ -63,26 +66,32 @@ impl EndpointAddr { } } - /// Adds a relay url. + /// Creates a new [`EndpointAddr`] from its parts. + pub fn from_parts(id: PublicKey, addrs: impl IntoIterator) -> Self { + Self { + id, + addrs: addrs.into_iter().collect(), + } + } + + /// Adds a [`RelayUrl`] address. pub fn with_relay_url(mut self, relay_url: RelayUrl) -> Self { self.addrs.insert(TransportAddr::Relay(relay_url)); self } - /// Adds the given IP addresses. - pub fn with_ip_addresses(mut self, addresses: impl IntoIterator) -> Self { - for addr in addresses.into_iter() { - self.addrs.insert(TransportAddr::Ip(addr)); - } + /// Adds an IP based address. + pub fn with_ip_addr(mut self, addr: SocketAddr) -> Self { + self.addrs.insert(TransportAddr::Ip(addr)); self } - /// Creates a new [`EndpointAddr`] from its parts. - pub fn from_parts(id: PublicKey, addrs: impl IntoIterator) -> Self { - Self { - id, - addrs: addrs.into_iter().collect(), + /// Adds a list of addresses. + pub fn with_addrs(mut self, addrs: impl IntoIterator) -> Self { + for addr in addrs.into_iter() { + self.addrs.insert(addr); } + self } /// Returns true, if only a [`EndpointId`] is present. @@ -90,15 +99,17 @@ impl EndpointAddr { self.addrs.is_empty() } - /// Returns the IP addresses of this peer. - pub fn ip_addresses(&self) -> impl Iterator { + /// Returns a list of IP addresses of this peer. + pub fn ip_addrs(&self) -> impl Iterator { self.addrs.iter().filter_map(|addr| match addr { TransportAddr::Ip(addr) => Some(addr), _ => None, }) } - /// Returns the relay url of this peer. + /// Returns a list of relay urls of this peer. + /// + /// In practice this is expected to be zero or one home relay for all known cases currently. pub fn relay_urls(&self) -> impl Iterator { self.addrs.iter().filter_map(|addr| match addr { TransportAddr::Relay(url) => Some(url), @@ -107,20 +118,6 @@ impl EndpointAddr { } } -impl From<(PublicKey, Option, &[SocketAddr])> for EndpointAddr { - fn from(value: (PublicKey, Option, &[SocketAddr])) -> Self { - let (id, relay_url, ip_addrs_iter) = value; - let mut addrs = BTreeSet::new(); - if let Some(url) = relay_url { - addrs.insert(TransportAddr::Relay(url)); - } - for addr in ip_addrs_iter { - addrs.insert(TransportAddr::Ip(*addr)); - } - EndpointAddr { id, addrs } - } -} - impl From for EndpointAddr { fn from(endpoint_id: EndpointId) -> Self { EndpointAddr::new(endpoint_id) diff --git a/iroh-base/src/ticket/endpoint.rs b/iroh-base/src/ticket/endpoint.rs index 9883c398c9d..68da6ef6d77 100644 --- a/iroh-base/src/ticket/endpoint.rs +++ b/iroh-base/src/ticket/endpoint.rs @@ -36,7 +36,7 @@ pub struct EndpointTicket { /// Wire format for [`EndpointTicket`]. #[derive(Serialize, Deserialize)] enum TicketWireFormat { - Variant0(Variant1EndpointTicket), + Variant1(Variant1EndpointTicket), } // Legacy @@ -49,7 +49,7 @@ impl Ticket for EndpointTicket { const KIND: &'static str = "endpoint"; fn to_bytes(&self) -> Vec { - let data = TicketWireFormat::Variant0(Variant1EndpointTicket { + let data = TicketWireFormat::Variant1(Variant1EndpointTicket { addr: Variant1EndpointAddr { id: self.addr.id, info: Variant1AddrInfo { @@ -62,7 +62,7 @@ impl Ticket for EndpointTicket { fn from_bytes(bytes: &[u8]) -> Result { let res: TicketWireFormat = postcard::from_bytes(bytes)?; - let TicketWireFormat::Variant0(Variant1EndpointTicket { addr }) = res; + let TicketWireFormat::Variant1(Variant1EndpointTicket { addr }) = res; Ok(Self { addr: EndpointAddr { id: addr.id, diff --git a/iroh-dns-server/examples/publish.rs b/iroh-dns-server/examples/publish.rs index 74ab74aad2e..99adec17cc0 100644 --- a/iroh-dns-server/examples/publish.rs +++ b/iroh-dns-server/examples/publish.rs @@ -105,7 +105,7 @@ async fn main() -> Result<()> { let pkarr = PkarrRelayClient::new(pkarr_relay_url); let endpoint_info = EndpointInfo::new(endpoint_id) .with_relay_url(relay_url.map(Into::into)) - .with_ip_addresses(args.addr.into_iter().collect()) + .with_ip_addrs(args.addr.into_iter().collect()) .with_user_data(args.user_data); let signed_packet = endpoint_info.to_pkarr_signed_packet(&secret_key, 30)?; tracing::debug!("signed packet: {signed_packet:?}"); diff --git a/iroh-dns-server/examples/resolve.rs b/iroh-dns-server/examples/resolve.rs index 1b7e1219df5..2f628585165 100644 --- a/iroh-dns-server/examples/resolve.rs +++ b/iroh-dns-server/examples/resolve.rs @@ -82,7 +82,7 @@ async fn main() -> Result<()> { for url in resolved.relay_urls() { println!(" relay={url}") } - for addr in resolved.ip_addresses() { + for addr in resolved.ip_addrs() { println!(" addr={addr}") } if let Some(user_data) = resolved.user_data() { diff --git a/iroh-relay/src/endpoint_info.rs b/iroh-relay/src/endpoint_info.rs index f232989ef34..90ab090511d 100644 --- a/iroh-relay/src/endpoint_info.rs +++ b/iroh-relay/src/endpoint_info.rs @@ -150,7 +150,7 @@ impl EndpointData { } /// Sets the direct addresses and returns the updated endpoint data. - pub fn with_ip_addresses(mut self, addresses: BTreeSet) -> Self { + pub fn with_ip_addrs(mut self, addresses: BTreeSet) -> Self { for addr in addresses.into_iter() { self.addrs.insert(TransportAddr::Ip(addr)); } @@ -177,7 +177,7 @@ impl EndpointData { } /// Returns the direct addresses of the endpoint. - pub fn ip_addresses(&self) -> impl Iterator { + pub fn ip_addrs(&self) -> impl Iterator { self.addrs.iter().filter_map(|addr| match addr { TransportAddr::Ip(addr) => Some(addr), _ => None, @@ -185,7 +185,7 @@ impl EndpointData { } /// Removes all direct addresses from the endpoint data. - pub fn clear_ip_addresses(&mut self) { + pub fn clear_ip_addrs(&mut self) { self.addrs .retain(|addr| !matches!(addr, TransportAddr::Ip(_))); } @@ -366,9 +366,9 @@ impl EndpointInfo { self } - /// Sets the direct addresses and returns the updated endpoint info. - pub fn with_ip_addresses(mut self, addrs: BTreeSet) -> Self { - self.data = self.data.with_ip_addresses(addrs); + /// Sets the IP based addresses and returns the updated endpoint info. + pub fn with_ip_addrs(mut self, addrs: BTreeSet) -> Self { + self.data = self.data.with_ip_addrs(addrs); self } @@ -785,7 +785,7 @@ mod tests { "1992d53c02cdc04566e5c0edb1ce83305cd550297953a047a445ea3264b54b18", )?) .with_relay_url(Some("https://euw1-1.relay.iroh.network./".parse()?)) - .with_ip_addresses(BTreeSet::from([ + .with_ip_addrs(BTreeSet::from([ "192.168.96.145:60165".parse().unwrap(), "213.208.157.87:60165".parse().unwrap(), ])); diff --git a/iroh/bench/src/iroh.rs b/iroh/bench/src/iroh.rs index 25ae818f215..b3f0eb84155 100644 --- a/iroh/bench/src/iroh.rs +++ b/iroh/bench/src/iroh.rs @@ -54,7 +54,7 @@ pub fn server_endpoint( let addr = ep.bound_sockets(); let addr = SocketAddr::new("127.0.0.1".parse().unwrap(), addr[0].port()); - let mut addr = EndpointAddr::new(ep.id()).with_ip_addresses([addr]); + let mut addr = EndpointAddr::new(ep.id()).with_ip_addr(addr); if let Some(relay_url) = relay_url { addr = addr.with_relay_url(relay_url.clone()); } diff --git a/iroh/examples/0rtt.rs b/iroh/examples/0rtt.rs index 1113ec82e19..e5b556d5381 100644 --- a/iroh/examples/0rtt.rs +++ b/iroh/examples/0rtt.rs @@ -144,7 +144,7 @@ async fn accept(_args: Args) -> n0_snafu::Result<()> { let Some(addr) = addrs.next().await else { snafu::whatever!("Address stream closed"); }; - if !addr.ip_addresses().count() == 0 { + if !addr.ip_addrs().count() == 0 { break addr; } }; diff --git a/iroh/examples/connect-unreliable.rs b/iroh/examples/connect-unreliable.rs index 61c2fae6cfd..991c40d8110 100644 --- a/iroh/examples/connect-unreliable.rs +++ b/iroh/examples/connect-unreliable.rs @@ -60,7 +60,7 @@ async fn main() -> n0_snafu::Result<()> { println!("endpoint id: {me}"); println!("endpoint listening addresses:"); endpoint_addr - .ip_addresses() + .ip_addrs() .for_each(|addr| println!("\t{addr}")); let relay_url = endpoint_addr .relay_urls() diff --git a/iroh/examples/connect.rs b/iroh/examples/connect.rs index fbae03cfe8f..7c2da47a8f7 100644 --- a/iroh/examples/connect.rs +++ b/iroh/examples/connect.rs @@ -58,7 +58,7 @@ async fn main() -> Result<()> { let me = endpoint.id(); println!("endpoint id: {me}"); println!("endpoint listening addresses:"); - for addr in endpoint_addr.ip_addresses() { + for addr in endpoint_addr.ip_addrs() { println!("\t{addr}") } diff --git a/iroh/examples/listen-unreliable.rs b/iroh/examples/listen-unreliable.rs index ec6e59fac23..15c39d54c4a 100644 --- a/iroh/examples/listen-unreliable.rs +++ b/iroh/examples/listen-unreliable.rs @@ -41,7 +41,7 @@ async fn main() -> Result<()> { let endpoint_addr = endpoint.addr(); let local_addrs = endpoint_addr - .ip_addresses() + .ip_addrs() .map(|addr| { let addr = addr.to_string(); println!("\t{addr}"); diff --git a/iroh/examples/listen.rs b/iroh/examples/listen.rs index 09daea14de1..96077508848 100644 --- a/iroh/examples/listen.rs +++ b/iroh/examples/listen.rs @@ -43,7 +43,7 @@ async fn main() -> n0_snafu::Result<()> { let endpoint_addr = endpoint.addr(); let local_addrs = endpoint_addr - .ip_addresses() + .ip_addrs() .map(|addr| { let addr = addr.to_string(); println!("\t{addr}"); diff --git a/iroh/examples/transfer.rs b/iroh/examples/transfer.rs index 6d2839df6dd..587055885a1 100644 --- a/iroh/examples/transfer.rs +++ b/iroh/examples/transfer.rs @@ -288,7 +288,7 @@ impl EndpointArgs { let endpoint_addr = endpoint.addr(); println!("Our direct addresses:"); - for addr in endpoint_addr.ip_addresses() { + for addr in endpoint_addr.ip_addrs() { println!("\t{addr}"); } diff --git a/iroh/src/discovery/mdns.rs b/iroh/src/discovery/mdns.rs index 3ba0fbdc050..983a0dfa04d 100644 --- a/iroh/src/discovery/mdns.rs +++ b/iroh/src/discovery/mdns.rs @@ -279,7 +279,7 @@ impl MdnsDiscovery { tracing::trace!(?data, "MdnsDiscovery address changed"); discovery.remove_all(); let addrs = - MdnsDiscovery::socketaddrs_to_addrs(data.ip_addresses()); + MdnsDiscovery::socketaddrs_to_addrs(data.ip_addrs()); for addr in addrs { discovery.add(addr.0, addr.1) } @@ -508,7 +508,7 @@ fn peer_to_discovery_item(peer: &Peer, endpoint_id: &EndpointId) -> DiscoveryIte None }; let endpoint_info = EndpointInfo::new(*endpoint_id) - .with_ip_addresses(ip_addrs) + .with_ip_addrs(ip_addrs) .with_user_data(user_data); DiscoveryItem::new(endpoint_info, NAME, None) } diff --git a/iroh/src/discovery/pkarr.rs b/iroh/src/discovery/pkarr.rs index 97467c7ad1a..e520049bc8f 100644 --- a/iroh/src/discovery/pkarr.rs +++ b/iroh/src/discovery/pkarr.rs @@ -317,7 +317,7 @@ impl PkarrPublisher { let mut data = data.clone(); if data.relay_urls().next().is_some() { // If relay url is set: only publish relay url, and no addrs. - data.clear_ip_addresses(); + data.clear_ip_addrs(); } let info = EndpointInfo::from_parts(self.endpoint_id, data); self.watchable.set(Some(info)).ok(); diff --git a/iroh/src/discovery/pkarr/dht.rs b/iroh/src/discovery/pkarr/dht.rs index 42eb80f89c1..e9d6efc9985 100644 --- a/iroh/src/discovery/pkarr/dht.rs +++ b/iroh/src/discovery/pkarr/dht.rs @@ -299,7 +299,7 @@ impl Discovery for DhtDiscovery { tracing::debug!("publishing {data:?}"); let mut info = EndpointInfo::from_parts(keypair.public(), data.clone()); if !self.0.include_direct_addresses { - info.clear_ip_addresses(); + info.clear_ip_addrs(); } let Ok(signed_packet) = info.to_pkarr_signed_packet(keypair, self.0.ttl) else { tracing::warn!("failed to create signed packet"); diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 72d76f237fe..05ba80ea3d6 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -698,7 +698,7 @@ impl Endpoint { self.add_endpoint_addr(endpoint_addr.clone(), Source::App)?; } let endpoint_id = endpoint_addr.id; - let ip_addresses: Vec<_> = endpoint_addr.ip_addresses().cloned().collect(); + let ip_addresses: Vec<_> = endpoint_addr.ip_addrs().cloned().collect(); let relay_url = endpoint_addr.relay_urls().next().cloned(); // Get the mapped IPv6 address from the magic socket. Quinn will connect to this @@ -870,7 +870,7 @@ impl Endpoint { /// [`RelayUrl`]: crate::RelayUrl #[cfg(not(wasm_browser))] pub fn watch_addr(&self) -> impl n0_watcher::Watcher + use<> { - let watch_addrs = self.msock.ip_addresses(); + let watch_addrs = self.msock.ip_addrs(); let watch_relay = self.msock.home_relay(); let endpoint_id = self.id(); @@ -2723,7 +2723,7 @@ mod tests { .bind() .await?; - assert!(ep.addr().ip_addresses().count() > 0); + assert!(ep.addr().ip_addrs().count() > 0); Ok(()) } diff --git a/iroh/src/magicsock.rs b/iroh/src/magicsock.rs index e565910e276..f87abdf2c3f 100644 --- a/iroh/src/magicsock.rs +++ b/iroh/src/magicsock.rs @@ -329,7 +329,7 @@ impl MagicSock { /// /// [`Watcher`]: n0_watcher::Watcher /// [`Watcher::initialized`]: n0_watcher::Watcher::initialized - pub(crate) fn ip_addresses(&self) -> n0_watcher::Direct> { + pub(crate) fn ip_addrs(&self) -> n0_watcher::Direct> { self.direct_addrs.addrs.watch() } @@ -2693,8 +2693,8 @@ mod tests { let me = m.endpoint.id().fmt_short(); let mut stream = m.endpoint.watch_addr().stream(); while let Some(addr) = stream.next().await { - info!(%me, "conn{} endpoints update: {:?}", my_idx + 1, addr.ip_addresses().collect::>()); - update_direct_addrs(&stacks, my_idx, addr.ip_addresses().copied().collect()); + info!(%me, "conn{} endpoints update: {:?}", my_idx + 1, addr.ip_addrs().collect::>()); + update_direct_addrs(&stacks, my_idx, addr.ip_addrs().copied().collect()); } }); } @@ -3080,12 +3080,12 @@ mod tests { let ms = Handle::new(default_options(&mut rng)).await.unwrap(); // See if we can get endpoints. - let eps0 = ms.ip_addresses().get(); + let eps0 = ms.ip_addrs().get(); println!("{eps0:?}"); assert!(!eps0.is_empty()); // Getting the endpoints again immediately should give the same results. - let eps1 = ms.ip_addresses().get(); + let eps1 = ms.ip_addrs().get(); println!("{eps1:?}"); assert_eq!(eps0, eps1); } @@ -3237,7 +3237,7 @@ mod tests { let _accept_task = AbortOnDropHandle::new(accept_task); let addrs = msock_2 - .ip_addresses() + .ip_addrs() .get() .into_iter() .map(|x| TransportAddr::Ip(x.addr)) @@ -3350,7 +3350,7 @@ mod tests { // Provide correct addressing information let addrs = msock_2 - .ip_addresses() + .ip_addrs() .get() .into_iter() .map(|x| TransportAddr::Ip(x.addr)) diff --git a/iroh/src/magicsock/endpoint_map.rs b/iroh/src/magicsock/endpoint_map.rs index 2d6e8e30ce7..e23da332321 100644 --- a/iroh/src/magicsock/endpoint_map.rs +++ b/iroh/src/magicsock/endpoint_map.rs @@ -391,13 +391,13 @@ impl EndpointMapInner { }); endpoint_state.update_from_endpoint_addr( endpoint_addr.relay_urls().next(), - endpoint_addr.ip_addresses().copied(), + endpoint_addr.ip_addrs().copied(), source0, have_ipv6, metrics, ); let id = endpoint_state.id(); - for addr in endpoint_addr.ip_addresses() { + for addr in endpoint_addr.ip_addrs() { self.set_endpoint_state_for_ip_port(*addr, id); } } @@ -419,7 +419,7 @@ impl EndpointMapInner { if let Entry::Occupied(mut entry) = self.by_id.entry(id) { let endpoint = entry.get_mut(); endpoint.remove_direct_addr(&ipp, now, why); - if endpoint.ip_addresses().count() == 0 { + if endpoint.ip_addrs().count() == 0 { let endpoint_id = endpoint.public_key(); let mapped_addr = endpoint.quic_mapped_addr(); self.by_endpoint_key.remove(endpoint_id); @@ -707,7 +707,7 @@ impl EndpointMapInner { continue; }; - for ip_port in ep.ip_addresses() { + for ip_port in ep.ip_addrs() { self.by_ip_port.remove(&ip_port); } @@ -757,7 +757,7 @@ impl IpPort { mod tests { use std::net::Ipv4Addr; - use iroh_base::SecretKey; + use iroh_base::{SecretKey, TransportAddr}; use rand::SeedableRng; use tracing_test::traced_test; @@ -792,14 +792,13 @@ mod tests { let relay_x: RelayUrl = "https://my-relay-1.com".parse().unwrap(); let relay_y: RelayUrl = "https://my-relay-2.com".parse().unwrap(); - let direct_addresses_a = [addr(4000), addr(4001)]; - let direct_addresses_c = [addr(5000)]; + let ip_addresses_a = [TransportAddr::Ip(addr(4000)), TransportAddr::Ip(addr(4001))]; + let ip_addresses_c = [TransportAddr::Ip(addr(5000))]; - let endpoint_addr_a = EndpointAddr::new(endpoint_a) - .with_relay_url(relay_x) - .with_ip_addresses(direct_addresses_a); + let addrs_a = std::iter::once(TransportAddr::Relay(relay_x)).chain(ip_addresses_a); + let endpoint_addr_a = EndpointAddr::new(endpoint_a).with_addrs(addrs_a); let endpoint_addr_b = EndpointAddr::new(endpoint_b).with_relay_url(relay_y); - let endpoint_addr_c = EndpointAddr::new(endpoint_c).with_ip_addresses(direct_addresses_c); + let endpoint_addr_c = EndpointAddr::new(endpoint_c).with_addrs(ip_addresses_c); let endpoint_addr_d = EndpointAddr::new(endpoint_d); endpoint_map.add_test_addr(endpoint_addr_a); @@ -877,7 +876,7 @@ mod tests { info!("Adding active addresses"); for i in 0..MAX_INACTIVE_DIRECT_ADDRESSES { let addr = SocketAddr::new(LOCALHOST, 5000 + i as u16); - let endpoint_addr = EndpointAddr::new(public_key).with_ip_addresses([addr]); + let endpoint_addr = EndpointAddr::new(public_key).with_ip_addr(addr); // add address endpoint_map.add_test_addr(endpoint_addr); // make it active @@ -887,7 +886,7 @@ mod tests { info!("Adding offline/inactive addresses"); for i in 0..MAX_INACTIVE_DIRECT_ADDRESSES * 2 { let addr = SocketAddr::new(LOCALHOST, 6000 + i as u16); - let endpoint_addr = EndpointAddr::new(public_key).with_ip_addresses([addr]); + let endpoint_addr = EndpointAddr::new(public_key).with_ip_addr(addr); endpoint_map.add_test_addr(endpoint_addr); } @@ -909,14 +908,14 @@ mod tests { // Half the offline addresses should have been pruned. All the active and alive // addresses should have been kept. assert_eq!( - endpoint.ip_addresses().count(), + endpoint.ip_addrs().count(), MAX_INACTIVE_DIRECT_ADDRESSES * 3 ); // We should have both offline and alive addresses which are not active. assert_eq!( endpoint - .ip_address_states() + .ip_addr_states() .filter(|(_addr, state)| !state.is_active()) .count(), MAX_INACTIVE_DIRECT_ADDRESSES * 2 @@ -931,7 +930,7 @@ mod tests { // add one active endpoint and more than MAX_INACTIVE_ENDPOINTS inactive endpoints let active_endpoint = SecretKey::generate(&mut rng).public(); let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 167); - endpoint_map.add_test_addr(EndpointAddr::new(active_endpoint).with_ip_addresses([addr])); + endpoint_map.add_test_addr(EndpointAddr::new(active_endpoint).with_ip_addr(addr)); endpoint_map .inner .lock() diff --git a/iroh/src/magicsock/endpoint_map/endpoint_state.rs b/iroh/src/magicsock/endpoint_map/endpoint_state.rs index e636c40ec25..e4b1c2a2209 100644 --- a/iroh/src/magicsock/endpoint_map/endpoint_state.rs +++ b/iroh/src/magicsock/endpoint_map/endpoint_state.rs @@ -1206,12 +1206,12 @@ impl EndpointState { } /// Get the IP addresses for this endpoint. - pub(super) fn ip_addresses(&self) -> impl Iterator + '_ { + pub(super) fn ip_addrs(&self) -> impl Iterator + '_ { self.udp_paths.paths().keys().copied() } #[cfg(test)] - pub(super) fn ip_address_states(&self) -> impl Iterator + '_ { + pub(super) fn ip_addr_states(&self) -> impl Iterator + '_ { self.udp_paths.paths().iter() }