diff --git a/iroh/src/endpoint.rs b/iroh/src/endpoint.rs index 6fd9673168..ae4e63af5c 100644 --- a/iroh/src/endpoint.rs +++ b/iroh/src/endpoint.rs @@ -38,7 +38,7 @@ use crate::{ dns::{default_resolver, DnsResolver}, magicsock::{self, Handle, QuicMappedAddr}, tls, - watchable::{DirectWatcher, Watcher}, + watchable::{DirectWatcher, MapWatcher, OrWatcher, Watcher}, }; mod rtt_actor; @@ -74,6 +74,22 @@ const DISCOVERY_WAIT_PERIOD: Duration = Duration::from_millis(500); type DiscoveryBuilder = Box Option> + Send + Sync>; +type NodeAddrMapper = Box< + dyn Fn((Option>, Option)) -> Option + + Send + + Sync + + 'static, +>; + +/// TODO(matheus23): DOCS (don't even ask) +/// +/// Implements [`Watcher`]`>`. +pub type NodeAddrWatcher = MapWatcher< + OrWatcher>>, DirectWatcher>>, + Option, + NodeAddrMapper, +>; + /// Builder for [`Endpoint`]. /// /// By default the endpoint will generate a new random [`SecretKey`], which will result in a @@ -759,26 +775,25 @@ impl Endpoint { /// The returned [`NodeAddr`] will have the current [`RelayUrl`] and direct addresses /// as they would be returned by [`Endpoint::home_relay`] and /// [`Endpoint::direct_addresses`]. - pub fn node_addr(&self) -> Result>> { + pub fn node_addr(&self) -> Result { let watch_addrs = self.direct_addresses(); let watch_relay = self.home_relay(); let node_id = self.node_id(); - let watcher = - watch_addrs - .or(watch_relay) - .map(move |(addrs, relay)| match (addrs, relay) { - (Some(addrs), relay) => Some(NodeAddr::from_parts( - node_id, - relay, - addrs.into_iter().map(|x| x.addr), - )), - (None, Some(relay)) => Some(NodeAddr::from_parts( - node_id, - Some(relay), - std::iter::empty(), - )), - (None, None) => None, - })?; + let mapper: NodeAddrMapper = Box::new(move |(addrs, relay)| match (addrs, relay) { + (Some(addrs), relay) => Some(NodeAddr::from_parts( + node_id, + relay, + addrs.into_iter().map(|x| x.addr), + )), + (None, Some(relay)) => Some(NodeAddr::from_parts( + node_id, + Some(relay), + std::iter::empty(), + )), + (None, None) => None, + }); + + let watcher = watch_addrs.or(watch_relay).map(mapper)?; Ok(watcher) } diff --git a/iroh/src/watchable.rs b/iroh/src/watchable.rs index bd9fffe565..2029ac45c7 100644 --- a/iroh/src/watchable.rs +++ b/iroh/src/watchable.rs @@ -205,13 +205,13 @@ pub trait Watcher: Clone { } /// Maps this watcher with a function that transforms the observed values. - fn map T>( + fn map T>( self, map: F, ) -> Result, Disconnected> { Ok(MapWatcher { current: (map)(self.get()?), - map, + map: Arc::new(map), watcher: self, }) } @@ -292,14 +292,24 @@ impl Watcher for OrWatcher { } /// Maps a [`Watcher`] and allows filtering updates. -#[derive(Clone, Debug)] -pub struct MapWatcher T> { - map: F, +#[derive(Debug)] +pub struct MapWatcher T> { + map: Arc, watcher: W, current: T, } -impl T> Watcher for MapWatcher { +impl T> Clone for MapWatcher { + fn clone(&self) -> Self { + Self { + map: self.map.clone(), + watcher: self.watcher.clone(), + current: self.current.clone(), + } + } +} + +impl T> Watcher for MapWatcher { type Value = T; fn get(&self) -> Result {