diff options
Diffstat (limited to 'src/swarm')
| -rw-r--r-- | src/swarm/pair.rs | 4 | ||||
| -rw-r--r-- | src/swarm/peer/inbound.rs | 3 | ||||
| -rw-r--r-- | src/swarm/peer/keepalive.rs | 15 |
3 files changed, 19 insertions, 3 deletions
diff --git a/src/swarm/pair.rs b/src/swarm/pair.rs index 41fc219..0d45b32 100644 --- a/src/swarm/pair.rs +++ b/src/swarm/pair.rs @@ -1,5 +1,5 @@ -//! Which side of a pair of nodes leads, for duties only one side needs to do (sending -//! keepalive STATUSes). +//! Which side of a pair of nodes leads, for what one side needs to start (the first +//! keepalive; then the two take turns, `PeerState::take_keepalive_due`). //! //! Both sides decide on their own, from the two keys alone, and agree. The leader is //! chosen per pair by one bit of a hash of both keys, not by comparing the keys: a diff --git a/src/swarm/peer/inbound.rs b/src/swarm/peer/inbound.rs index 0eaefb9..2e89739 100644 --- a/src/swarm/peer/inbound.rs +++ b/src/swarm/peer/inbound.rs @@ -11,7 +11,7 @@ use super::epoch::observe_peer_epoch; use super::handshake::{ discover_peers, ensure_handshake, establish_peer, peer_swarm, remember_peer, send_hello_reply, }; -use super::keepalive::{heal_if_diverged, local_status, note_alive, note_status}; +use super::keepalive::{heal_if_diverged, local_status, note_alive, note_status, status_received}; use super::lanes::SyncLanes; use crate::state::AppState; use crate::swarm::sync::SyncEvent; @@ -149,6 +149,7 @@ pub(crate) async fn handle_message( crate::swarm::blob::handle(state, &peer, blob).await; } transport::ParsedMessage::Status(remote) => { + status_received(state, &peer).await; let local = on_status(state, &peer, &remote, reactivated).await; if let Err(error) = state .transport diff --git a/src/swarm/peer/keepalive.rs b/src/swarm/peer/keepalive.rs index 460b71e..efb8a65 100644 --- a/src/swarm/peer/keepalive.rs +++ b/src/swarm/peer/keepalive.rs @@ -63,6 +63,10 @@ pub(super) async fn note_alive(state: &AppState, peer: &str, message: &ParsedMes }; let reactivated = { let mut peer_state = peer_state.lock().await; + if matches!(message, ParsedMessage::Ping(_)) { + // Its keepalive (or a path probe): the next is ours. + peer_state.keepalive_received_at = Some(now); + } if peer_state.unreachable_since.is_some() { // Reachable again (`mark_seen` clears it). state.topology_changed.notify_one(); @@ -147,6 +151,17 @@ pub(crate) async fn local_status(state: &AppState, peer: &str) -> transport::Sta } } +/// A STATUS (not a reply) from `peer`: its keepalive, and a STATUS between us +/// (`Timing::status_refresh`). +pub(super) async fn status_received(state: &AppState, peer: &str) { + if let Some(peer_state) = state.get_peer_state(peer).await { + let mut peer_state = peer_state.lock().await; + let now = Instant::now(); + peer_state.keepalive_received_at = Some(now); + peer_state.last_status_at = Some(now); + } +} + /// What a peer's status says about it. pub(super) async fn note_status(state: &AppState, peer: &str, remote: &transport::Status) { if let Some(peer_state) = state.get_peer_state(peer).await { |
