From 1c32f4534c88304205e2de6d5d0c33a8bb0162d9 Mon Sep 17 00:00:00 2001 From: tv Date: Fri, 23 Oct 2026 13:11:55 +0200 Subject: ping only from one side --- src/state.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'src/state.rs') 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); -- cgit v1.3.1