diff --git a/Cargo.lock b/Cargo.lock index 6c046b79a7..d488e96aa2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5067,7 +5067,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.48.0", ] [[package]] diff --git a/iroh/src/magicsock.rs b/iroh/src/magicsock.rs index abb61bd949..bb8efc97c1 100644 --- a/iroh/src/magicsock.rs +++ b/iroh/src/magicsock.rs @@ -1232,6 +1232,8 @@ impl Actor { } else { self.re_stun(UpdateReason::LinkChangeMinor); } + + self.msock.remote_map.on_network_change(is_major); } fn handle_relay_map_change(&mut self) { diff --git a/iroh/src/magicsock/remote_map.rs b/iroh/src/magicsock/remote_map.rs index b08ea47cc8..22abb5af96 100644 --- a/iroh/src/magicsock/remote_map.rs +++ b/iroh/src/magicsock/remote_map.rs @@ -98,6 +98,17 @@ impl RemoteMap { handles.retain(|_eid, handle| !handle.sender.is_closed()) } + pub(super) fn on_network_change(&self, is_major: bool) { + let handles = self.actor_handles.lock().expect("poisoned"); + for entry in handles.values() { + if let Some(sender) = entry.sender.get() { + sender + .try_send(RemoteStateMessage::NetworkChange { is_major }) + .ok(); + } + } + } + /// Returns the sender for the [`RemoteStateActor`]. /// /// If needed a new actor is started on demand. diff --git a/iroh/src/magicsock/remote_map/remote_state.rs b/iroh/src/magicsock/remote_map/remote_state.rs index a1adc3aaec..4bd8c2a806 100644 --- a/iroh/src/magicsock/remote_map/remote_state.rs +++ b/iroh/src/magicsock/remote_map/remote_state.rs @@ -368,6 +368,28 @@ impl RemoteStateActor { }; tx.send(info).ok(); } + RemoteStateMessage::NetworkChange { is_major } => { + self.handle_network_change(is_major); + } + } + } + + fn handle_network_change(&mut self, is_major: bool) { + for conn in self.connections.values() { + if let Some(quinn_conn) = conn.handle.upgrade() { + for (path_id, addr) in &conn.open_paths { + if let Some(path) = quinn_conn.path(*path_id) { + // Ping the current path + if let Err(err) = path.ping() { + warn!(%err, ?path_id, ?addr, "failed to ping path"); + } + } + } + } + } + + if is_major { + self.trigger_holepunching(); } } @@ -1175,6 +1197,8 @@ pub(crate) enum RemoteStateMessage { /// /// This currently only includes a list of all known transport addresses for the remote. RemoteInfo(oneshot::Sender), + /// The network status has changed in some way + NetworkChange { is_major: bool }, } /// A handle to a [`RemoteStateActor`].