diff options
| author | tv <tv@krebsco.de> | 2026-10-23 13:11:55 +0200 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-10-23 13:11:55 +0200 |
| commit | 1c32f4534c88304205e2de6d5d0c33a8bb0162d9 (patch) | |
| tree | d82904bf3deff6ddd855ad1fb32b68c7f6373ca8 | |
| parent | 64fbe99234425259d2758982caa52e1a62272d03 (diff) | |
ping only from one side
| -rw-r--r-- | src/state.rs | 22 | ||||
| -rw-r--r-- | src/swarm/peer.rs | 3 |
2 files changed, 22 insertions, 3 deletions
diff --git a/src/state.rs b/src/state.rs index a43c2f9..dd360de 100644 --- a/src/state.rs +++ b/src/state.rs @@ -274,11 +274,29 @@ impl PeerState { } /// True (and records the ping) if an established, quiet peer needs a keepalive. - pub(crate) fn take_keepalive_due(&mut self, timing: &Timing, now: Instant) -> bool { + /// + /// One PING and its PONG tell both sides that the other is alive, so only one side of + /// a pair needs to ping: the one with the smaller key (`we_ping`). Each of its PINGs + /// makes the other side's peer look recently heard from, so the other side never + /// pings while it does. If the pings stop, the other side pings once it has heard + /// nothing for half an interval more. Without that, both sides would get due at about + /// the same time (each one's quiet time starts with the same exchange) and their + /// PINGs would often cross. + pub(crate) fn take_keepalive_due( + &mut self, + timing: &Timing, + we_ping: bool, + now: Instant, + ) -> bool { + let quiet_enough = if we_ping { + timing.keepalive + } else { + timing.keepalive + timing.keepalive / 2 + }; let due = self.liveness == Liveness::Active && self.hello_state == HelloState::Established && now.saturating_duration_since(self.added_at) >= timing.keepalive - && self.quiet_for(now) >= timing.keepalive + && self.quiet_for(now) >= quiet_enough && self .last_ping_at .is_none_or(|t| now.saturating_duration_since(t) >= timing.keepalive); diff --git a/src/swarm/peer.rs b/src/swarm/peer.rs index bad8e24..5928ac2 100644 --- a/src/swarm/peer.rs +++ b/src/swarm/peer.rs @@ -410,7 +410,8 @@ pub(crate) async fn run_peer_worker(state: AppState) { let (became_dormant, ping_due, unanswered) = { let mut peer_state = peer_state_mutex.lock().await; let became_dormant = ready && peer_state.check_dormancy(&state.timing, now); - let ping_due = peer_state.take_keepalive_due(&state.timing, now); + let we_ping = state.local_id() < peer.as_str(); + let ping_due = peer_state.take_keepalive_due(&state.timing, we_ping, now); let unanswered = peer_state.take_overdue_sync_reply(now); (became_dormant, ping_due, unanswered) }; |
