diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/state/peer.rs | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/src/state/peer.rs b/src/state/peer.rs index a1d40ab..434f5fd 100644 --- a/src/state/peer.rs +++ b/src/state/peer.rs @@ -110,10 +110,9 @@ pub(crate) struct PeerState { pub(crate) last_status_at: Option<Instant>, /// Since when we wait for an answer from it (to a keepalive, or to a sync message /// whose answer is overdue) with nothing heard from it since, and whether we asked - /// again: halfway to `Timing::unreached_after` a PING (`take_ask_again_due`; a sync - /// message whose answer is overdue goes again anyway), so one lost message or answer - /// doesn't do it; after it, we don't count it as reached (`swarm::reach`). Cleared by - /// any message from it (`mark_seen`). + /// again: halfway to `Timing::unreached_after` a PING (`take_ask_again_due`), so one + /// lost message or answer doesn't do it; after it, we don't count it as reached + /// (`swarm::reach`). Cleared by any message from it (`mark_seen`). awaiting_answer: Option<(Instant, bool)>, /// Last time a sync message from this peer was applied (survives resets: the @@ -283,8 +282,9 @@ impl PeerState { if overdue.is_some() { self.incidents.reply_timeouts += 1; if let Some(started) = started { - // It goes again now: that is asking again. - self.awaiting_answer.get_or_insert((started, true)); + // Asked again with a PING too: a peer that has nothing to say answers no + // sync message, however often it goes. + self.awaiting_answer.get_or_insert((started, false)); } if let Some(largest) = largest { self.whole_failed(largest, now); @@ -753,6 +753,28 @@ mod tests { assert!(!peer.answer_overdue(&timing, sent + timing.unreached_after * 2)); } + /// A sync message whose answer is overdue is asked after with a PING too: a peer with + /// nothing to say answers none, however often it goes, and still counts as reached + /// once it answers the PING. + #[test] + fn unanswered_sync_messages_are_asked_after() { + let timing = Timing::from_keepalive(Duration::from_secs(60), Duration::from_secs(300)); + let mut peer = PeerState::new(true, &timing); + peer.hello_state = HelloState::Established; + let sent = peer.added_at; + peer.sync.expect_reply( + Vec::new(), + sent, + crate::swarm::throughput::SyncBytes::default(), + 100, + ); + let overdue = sent + timing.sync_reply_timeout; + assert!(peer.take_overdue_sync_reply(overdue).is_some()); + assert!(peer.take_ask_again_due(&timing, overdue)); + peer.mark_seen(overdue + Duration::from_millis(50)); + assert!(!peer.answer_overdue(&timing, sent + timing.unreached_after)); + } + /// Keepalives are PINGs, every `status_refresh` a STATUS; only when quiet. #[test] fn keepalives_are_pings_and_now_and_then_a_status() { |
