Our Info: display peer-observed external address

Store the external address reported by peers via your_observed_addr in
initial exchange. Display it in Our Info panel with NAT classification.
Replaces reliance on iroh's pkarr/STUN for external address discovery
while keeping clear_address_lookup() (no dns.iroh.link publishing).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Scott Reimers 2026-04-19 17:37:33 -04:00
parent d1036a2d7d
commit ffb13d6791
2 changed files with 34 additions and 2 deletions

View file

@ -613,6 +613,8 @@ pub struct ConnectionManager {
activity_log: Arc<std::sync::Mutex<ActivityLog>>,
/// UPnP external address (prepended to self-reported addresses in anchor registration)
upnp_external_addr: Option<SocketAddr>,
/// External address as observed by peers (from initial exchange your_observed_addr)
pub observed_external_addr: std::sync::Mutex<Option<SocketAddr>>,
/// Stable bind address (from --bind flag), used for anchor advertised address
bind_addr: Option<SocketAddr>,
/// Our detected NAT type (from STUN probing on startup)
@ -684,6 +686,7 @@ impl ConnectionManager {
recovery_tx: None,
activity_log,
upnp_external_addr,
observed_external_addr: std::sync::Mutex::new(None),
bind_addr,
nat_type,
nat_mapping,
@ -1597,9 +1600,12 @@ impl ConnectionManager {
}
}
// Log observed address (STUN-like feedback)
// Store observed address (STUN-like feedback from peer)
if let Some(ref observed) = their_payload.your_observed_addr {
info!(observed_addr = %observed, reporter = hex::encode(remote_node_id), "Peer reports our address as");
if let Ok(addr) = observed.parse::<std::net::SocketAddr>() {
*self.observed_external_addr.lock().unwrap() = Some(addr);
}
}
// Store peer's NAT type
@ -6709,6 +6715,9 @@ pub enum ConnCommand {
GetUpnpExternalAddr {
reply: oneshot::Sender<Option<SocketAddr>>,
},
GetObservedExternalAddr {
reply: oneshot::Sender<Option<SocketAddr>>,
},
TouchSessionIfExists {
peer: NodeId,
},
@ -7204,6 +7213,12 @@ impl ConnHandle {
rx.await.ok().flatten()
}
pub async fn observed_external_addr(&self) -> Option<SocketAddr> {
let (tx, rx) = oneshot::channel();
let _ = self.tx.send(ConnCommand::GetObservedExternalAddr { reply: tx }).await;
rx.await.ok().flatten()
}
/// Touch session last_active (fire-and-forget, no-op if not a session peer).
pub fn touch_session_if_exists(&self, peer: &NodeId) {
let _ = self.tx.try_send(ConnCommand::TouchSessionIfExists { peer: *peer });
@ -8119,6 +8134,10 @@ impl ConnectionActor {
let cm = self.cm.lock().await;
let _ = reply.send(cm.upnp_external_addr);
}
ConnCommand::GetObservedExternalAddr { reply } => {
let cm = self.cm.lock().await;
let _ = reply.send(*cm.observed_external_addr.lock().unwrap());
}
ConnCommand::TouchSessionIfExists { peer } => {
let mut cm = self.cm.lock().await;
if let Some(session) = cm.sessions.get_mut(&peer) {