aboutsummaryrefslogtreecommitdiffstats
path: root/src/swarm/relay.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/swarm/relay.rs')
-rw-r--r--src/swarm/relay.rs42
1 files changed, 8 insertions, 34 deletions
diff --git a/src/swarm/relay.rs b/src/swarm/relay.rs
index 5ab93f2..1393d50 100644
--- a/src/swarm/relay.rs
+++ b/src/swarm/relay.rs
@@ -16,10 +16,11 @@
//! message would announce to every neighbour, and announcements would outnumber the
//! data they announce (about 15 to 1 at 250 nodes).
//!
-//! In a full mesh the writer reaches everyone itself, so nothing is announced, but to
-//! the neighbours the writer can't reach: those on none of its transports (a member on
-//! Tor alone, reached through one on Tor and libp2p, from a writer on libp2p alone).
-//! Whom it reaches is what the member list makes its neighbours (`topology::neighbours_of`).
+//! In a full mesh too: the member list makes every member the writer's neighbour, but
+//! that says nothing about whether the writer reaches them. One behind NAT may reach a
+//! single one of them, one on another transport (on Tor alone) none, and no node can
+//! tell which from where it is. A neighbour that has the changes already does nothing
+//! with an announcement but answer it.
use std::collections::{HashMap, HashSet};
use std::sync::atomic::Ordering;
@@ -44,15 +45,7 @@ const ANNOUNCE_DELAY: Duration = Duration::from_millis(200);
/// After changes from `from` were applied and our heads changed: tell our other
/// neighbours, in the next announcement round.
pub(crate) async fn announce(state: &AppState, from: &str) {
- // While the view is unknown everyone counts as a neighbour, but that isn't a full
- // mesh: the others may not hear from the writer.
- if !state.initial_sync_done.load(Ordering::Acquire)
- || (topology::view_known(state)
- && topology::is_full_mesh(state)
- && unreached(state, &HashSet::from([from.to_owned()]))
- .await
- .is_empty())
- {
+ if !state.initial_sync_done.load(Ordering::Acquire) {
return;
}
let schedule = {
@@ -101,38 +94,19 @@ async fn announce_now(state: &AppState, senders: &HashSet<String>) {
/// The neighbours to tell of the changes `senders` sent us. The peer whose changes we
/// announce has them already, so with a single sender it is skipped; with several, each
-/// lacks the others' changes. In a full mesh, also those every sender is a neighbour of:
-/// the writers reached them themselves.
+/// lacks the others' changes.
async fn unreached(state: &AppState, senders: &HashSet<String>) -> Vec<String> {
let skip = match senders.len() {
1 => senders.iter().next().cloned(),
_ => None,
};
- let full_mesh = topology::view_known(state) && topology::is_full_mesh(state);
- // Unknown (a sender not in the member list): nobody counts as reached by it.
- let reached: Vec<Option<std::collections::BTreeSet<String>>> = if full_mesh {
- senders
- .iter()
- .map(|sender| topology::neighbours_of(state, sender))
- .collect()
- } else {
- Vec::new()
- };
- let reached_by_all = |peer: &str| {
- full_mesh
- && reached.iter().zip(senders).all(|(neighbours, sender)| {
- sender == peer || neighbours.as_ref().is_some_and(|n| n.contains(peer))
- })
- };
state
.peer_states
.read()
.await
.keys()
.filter(|peer| {
- skip.as_deref() != Some(peer.as_str())
- && topology::is_neighbour(state, peer)
- && !reached_by_all(peer)
+ skip.as_deref() != Some(peer.as_str()) && topology::is_neighbour(state, peer)
})
.cloned()
.collect()