aboutsummaryrefslogtreecommitdiffstats
path: root/src/swarm/peer/inbound.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/swarm/peer/inbound.rs')
-rw-r--r--src/swarm/peer/inbound.rs24
1 files changed, 21 insertions, 3 deletions
diff --git a/src/swarm/peer/inbound.rs b/src/swarm/peer/inbound.rs
index 1454c3e..28066cb 100644
--- a/src/swarm/peer/inbound.rs
+++ b/src/swarm/peer/inbound.rs
@@ -143,13 +143,31 @@ pub(crate) async fn handle_message(
crate::swarm::blob::handle(state, &peer, blob).await;
}
transport::ParsedMessage::Status(remote) => {
- // An announcement is no keepalive; it is answered only if our heads differ,
- // so the announcer learns what we have that it lacks.
+ // An announcement is no keepalive; it is answered only if we lack some of the
+ // heads it announced (`relay::lacks`), so the announcer learns what we have
+ // that it lacks while we pull. Having all of them, we are as far or further,
+ // and what we have further we announced ourselves; differing heads alone are
+ // no reason, as changes on their way to us make them differ while writes go on.
if !remote.announcing {
status_received(state, &peer).await;
}
let local = on_status(state, &peer, &remote, reactivated).await;
- if remote.announcing && local.heads == remote.heads {
+ if remote.announcing {
+ if local.heads != remote.heads {
+ // Off the consumer: telling which heads we lack takes the document's
+ // lock.
+ let (state, peer) = (state.clone(), peer.clone());
+ tokio::spawn(async move {
+ if crate::swarm::relay::lacks(&state, &remote.heads).await
+ && let Err(error) = state
+ .transport
+ .send_message(&peer, &ParsedMessage::StatusReply(local))
+ .await
+ {
+ debug!(peer = %peer, error = %format!("{error:#}"), "STATUS_REPLY failed");
+ }
+ });
+ }
return Ok(());
}
if let Err(error) = state