diff options
| author | tv <tv@krebsco.de> | 2026-11-01 20:36:17 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-01 20:36:17 +0100 |
| commit | dbb614e1ecf27ca37f54dba4e2c8fe3810af8c8c (patch) | |
| tree | ac7c141812d534f3c51907e5634fcb6c8aadc468 /src/state/peer.rs | |
| parent | 7f018573730dc57f9608fe41faa54b44abba841d (diff) | |
peer worker sleeps until deadline, not fixed time
Diffstat (limited to 'src/state/peer.rs')
| -rw-r--r-- | src/state/peer.rs | 73 |
1 files changed, 55 insertions, 18 deletions
diff --git a/src/state/peer.rs b/src/state/peer.rs index 3e1332d..cb42dc1 100644 --- a/src/state/peer.rs +++ b/src/state/peer.rs @@ -392,6 +392,26 @@ impl PeerState { timing: &Timing, now: Instant, ) -> Option<Keepalive> { + if self.keepalive_due_at(timing).is_none_or(|at| now < at) { + return None; + } + self.last_keepalive_at = Some(now); + let status = self + .last_status_at + .is_none_or(|t| now.saturating_duration_since(t) >= timing.status_refresh); + Some(if status { + Keepalive::Status + } else { + Keepalive::Ping + }) + } + + /// When the next keepalive is due (`take_keepalive_due`), if any is: none to a + /// dormant peer, nor before the handshake. + pub(crate) fn keepalive_due_at(&self, timing: &Timing) -> Option<Instant> { + if self.liveness.is_dormant() || self.hello_state != HelloState::Established { + return None; + } let our_turn = match (self.last_keepalive_at, self.keepalive_received_at) { (None, None) => self.leads, (None, Some(_)) => true, @@ -407,27 +427,44 @@ impl PeerState { } else { timing.keepalive + timing.keepalive / 2 }; - let due = !self.liveness.is_dormant() - && self.hello_state == HelloState::Established - && now.saturating_duration_since(self.added_at) >= timing.keepalive - && self.quiet_for(now) >= quiet_enough - && self - .last_keepalive_at - .is_none_or(|t| now.saturating_duration_since(t) >= timing.keepalive); - if !due { - return None; - } - self.last_keepalive_at = Some(now); - let status = self - .last_status_at - .is_none_or(|t| now.saturating_duration_since(t) >= timing.status_refresh); - Some(if status { - Keepalive::Status - } else { - Keepalive::Ping + let quiet_since = self.last_seen.unwrap_or(self.added_at); + let at = (self.added_at + timing.keepalive).max(quiet_since + quiet_enough); + Some(match self.last_keepalive_at { + Some(sent) => at.max(sent + timing.keepalive), + None => at, }) } + /// When the peer worker next has something to do for this peer + /// (`swarm::peer::run_peer_worker`): a keepalive (to a `neighbour`), dormancy (of a + /// neighbour, once `ready`), a HELLO retry, an overdue sync answer. None if nothing + /// is due until something changes. + pub(crate) fn next_due( + &self, + timing: &Timing, + neighbour: bool, + ready: bool, + ) -> Option<Instant> { + let dormancy = (ready && neighbour && !self.liveness.is_dormant()) + .then(|| self.last_seen.unwrap_or(self.added_at) + timing.dormant_after); + let keepalive = if neighbour { + self.keepalive_due_at(timing) + } else { + None + }; + let hello = match self.hello_state { + HelloState::AwaitingReply { next_attempt } => Some(next_attempt), + _ => None, + }; + let reply = (!self.liveness.is_dormant() && self.hello_state == HelloState::Established) + .then(|| self.sync.reply.as_ref().map(|wait| wait.deadline)) + .flatten(); + [dormancy, keepalive, hello, reply] + .into_iter() + .flatten() + .min() + } + /// Self-healing check on a STATUS or STATUS_REPLY. Returns true if a re-handshake /// should start. pub(crate) fn needs_heal( |
