summaryrefslogtreecommitdiffstats
path: root/src/swarm
diff options
context:
space:
mode:
Diffstat (limited to 'src/swarm')
-rw-r--r--src/swarm/pair.rs4
-rw-r--r--src/swarm/peer/inbound.rs3
-rw-r--r--src/swarm/peer/keepalive.rs15
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 {