diff --git a/iroh-net/src/magicsock.rs b/iroh-net/src/magicsock.rs index 3fd7c45886..3e5b037263 100644 --- a/iroh-net/src/magicsock.rs +++ b/iroh-net/src/magicsock.rs @@ -1272,6 +1272,7 @@ impl Actor { msock_sender: self.inner.actor_sender.clone(), public_key: dm.src, derp_region: Some(region_id), + active: true, }); self.peer_map.set_endpoint_for_ip_port(&ipp, id); let ep = self.peer_map.by_id_mut(&id).expect("inserted"); @@ -2168,6 +2169,7 @@ impl Actor { msock_sender: self.inner.actor_sender.clone(), public_key: sender, derp_region: src.derp_region(), + active: true, }); } self.handle_ping(ping, &sender, src, derp_node_src).await; diff --git a/iroh-net/src/magicsock/endpoint.rs b/iroh-net/src/magicsock/endpoint.rs index 6c598c0316..2e69e50543 100644 --- a/iroh-net/src/magicsock/endpoint.rs +++ b/iroh-net/src/magicsock/endpoint.rs @@ -3,7 +3,7 @@ use std::{ hash::Hash, net::{IpAddr, SocketAddr}, path::Path, - time::Duration, + time::{Duration, Instant}, }; use anyhow::Context; @@ -12,7 +12,7 @@ use iroh_metrics::inc; use rand::seq::IteratorRandom; use serde::{Deserialize, Serialize}; use tokio::io::AsyncWriteExt; -use tokio::{sync::mpsc, time::Instant}; +use tokio::sync::mpsc; use tracing::{debug, info, trace, warn}; use crate::{ @@ -76,8 +76,8 @@ pub(super) struct Endpoint { sent_ping: HashMap, - /// Last time this endpoint was used. - last_active: Instant, + /// Last time this endpoint was used. If set to `None` it is inactive. + last_active: Option, } #[derive(derive_more::Debug)] @@ -92,6 +92,8 @@ pub(super) struct Options { pub(super) msock_sender: mpsc::Sender, pub(super) public_key: PublicKey, pub(super) derp_region: Option, + /// Is this endpoint currently active (sending data)? + pub(super) active: bool, } impl Endpoint { @@ -117,7 +119,7 @@ impl Endpoint { endpoint_state: HashMap::new(), is_call_me_maybe_ep: HashMap::new(), pending_cli_pings: Vec::new(), - last_active: Instant::now(), + last_active: options.active.then(Instant::now), } } @@ -923,13 +925,21 @@ impl Endpoint { self.endpoint_state.get(addr).and_then(|ep| ep.last_ping) } + /// Checks if this `Endpoint` is currently actively being used. + fn is_active(&self, now: &Instant) -> bool { + match self.last_active { + Some(last_active) => now.duration_since(last_active) <= SESSION_ACTIVE_TIMEOUT, + None => false, + } + } + /// Send a heartbeat to the peer to keep the connection alive, or trigger a full ping /// if necessary. pub(super) async fn stayin_alive(&mut self) { trace!("stayin_alive"); let now = Instant::now(); - if now.duration_since(self.last_active) > SESSION_ACTIVE_TIMEOUT { - debug!("skipping stayin alive: session is inactive"); + if !self.is_active(&now) { + trace!("skipping stayin alive: session is inactive"); return; } @@ -962,7 +972,7 @@ impl Endpoint { pub(crate) async fn get_send_addrs(&mut self) -> (Option, Option) { let now = Instant::now(); - self.last_active = now; + self.last_active.replace(now); let (udp_addr, derp_region, should_ping) = self.addr_for_send(&now); // Trigger a round of pings if we haven't had any full pings yet. @@ -1078,6 +1088,7 @@ impl PeerMap { msock_sender, public_key: peer_id, derp_region: info.derp_region, + active: false, }); } @@ -1451,7 +1462,7 @@ mod tests { is_call_me_maybe_ep: HashMap::new(), pending_cli_pings: Vec::new(), sent_ping: HashMap::new(), - last_active: now, + last_active: Some(now), }, socket_addr, ) @@ -1493,7 +1504,7 @@ mod tests { is_call_me_maybe_ep: HashMap::new(), pending_cli_pings: Vec::new(), sent_ping: HashMap::new(), - last_active: now, + last_active: Some(now), } }; @@ -1518,7 +1529,7 @@ mod tests { is_call_me_maybe_ep: HashMap::new(), pending_cli_pings: Vec::new(), sent_ping: HashMap::new(), - last_active: now, + last_active: Some(now), } }; @@ -1583,7 +1594,7 @@ mod tests { is_call_me_maybe_ep: HashMap::new(), pending_cli_pings: Vec::new(), sent_ping: HashMap::new(), - last_active: now, + last_active: Some(now), }, socket_addr, )