diff --git a/iroh-net/src/hp/magicsock.rs b/iroh-net/src/hp/magicsock.rs index f697a11d53..4035d9f91f 100644 --- a/iroh-net/src/hp/magicsock.rs +++ b/iroh-net/src/hp/magicsock.rs @@ -10,4 +10,5 @@ mod timer; mod udp_actor; pub use self::conn::{Conn, Options}; +pub use self::endpoint::EndpointInfo; pub use self::timer::Timer; diff --git a/iroh-net/src/hp/magicsock/conn.rs b/iroh-net/src/hp/magicsock/conn.rs index c3d4079cd1..1b4025f124 100644 --- a/iroh-net/src/hp/magicsock/conn.rs +++ b/iroh-net/src/hp/magicsock/conn.rs @@ -36,7 +36,7 @@ use crate::{ use super::{ derp_actor::{DerpActor, DerpActorMessage, DerpReadResult}, - endpoint::{Options as EndpointOptions, PeerMap}, + endpoint::{EndpointInfo, Options as EndpointOptions, PeerMap}, rebinding_conn::RebindingUdpConn, udp_actor::{IpPacket, NetworkReadResult, NetworkSource, UdpActor, UdpActorMessage}, }; @@ -365,7 +365,7 @@ impl Conn { Ok(c) } - pub async fn tracked_endpoints(&self) -> Result> { + pub async fn tracked_endpoints(&self) -> Result> { let (s, r) = sync::oneshot::channel(); self.actor_sender .send(ActorMessage::TrackedEndpoints(s)) @@ -741,7 +741,7 @@ impl Drop for WgGuard { #[derive(Debug)] pub(super) enum ActorMessage { SetDerpMap(Option, sync::oneshot::Sender<()>), - TrackedEndpoints(sync::oneshot::Sender>), + TrackedEndpoints(sync::oneshot::Sender>), LocalEndpoints(sync::oneshot::Sender>), GetMappingAddr( key::node::PublicKey, @@ -893,11 +893,7 @@ impl Actor { let _ = s.send(()); } ActorMessage::TrackedEndpoints(s) => { - let eps: Vec<_> = self - .peer_map - .endpoints() - .map(|(_, ep)| ep.public_key.clone()) - .collect(); + let eps: Vec<_> = self.peer_map.endpoints().map(|(_, ep)| ep.info()).collect(); let _ = s.send(eps); } ActorMessage::LocalEndpoints(s) => { @@ -2739,7 +2735,13 @@ mod tests { } async fn tracked_endpoints(&self) -> Vec { - self.conn.tracked_endpoints().await.unwrap_or_default() + self.conn + .tracked_endpoints() + .await + .unwrap_or_default() + .into_iter() + .map(|ep| ep.public_key) + .collect() } fn public(&self) -> key::node::PublicKey { diff --git a/iroh-net/src/hp/magicsock/endpoint.rs b/iroh-net/src/hp/magicsock/endpoint.rs index 58bca7be60..c541fd657a 100644 --- a/iroh-net/src/hp/magicsock/endpoint.rs +++ b/iroh-net/src/hp/magicsock/endpoint.rs @@ -122,6 +122,26 @@ impl Endpoint { &self.public_key } + /// Returns info about this endpoint + pub fn info(&self) -> EndpointInfo { + let addrs = self + .endpoint_state + .keys() + .filter_map(|addr| match addr { + SendAddr::Udp(addr) => Some(*addr), + _ => None, + }) + .collect(); + + EndpointInfo { + public_key: self.public_key.clone(), + derp_addr: self.derp_addr, + addrs, + has_direct_connection: self.is_best_addr_valid(Instant::now()), + latency: self.best_addr.as_ref().and_then(|a| a.latency), + } + } + /// Returns the address(es) that should be used for sending the next packet. /// Zero, one, or both of UDP address and DERP addr may be non-zero. fn addr_for_send(&mut self, now: &Instant) -> (Option, Option, bool) { @@ -1008,6 +1028,21 @@ struct EndpointState { index: Index, } +/// Details about an Endpoint +#[derive(Debug, Clone)] +pub struct EndpointInfo { + /// The public key of the endpoint. + pub public_key: key::node::PublicKey, + /// Derp region, if available. + pub derp_addr: Option, + /// List of addresses this node might be reachable under. + pub addrs: Vec, + /// Is this node currently direcly reachable? + pub has_direct_connection: bool, + /// Current latency information, for a direct connection if available. + pub latency: Option, +} + #[derive(Default, Debug, PartialEq, Eq, Clone, Copy, Hash)] enum Index { #[default]