diff options
Diffstat (limited to 'src/swarm/peer/handshake.rs')
| -rw-r--r-- | src/swarm/peer/handshake.rs | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/src/swarm/peer/handshake.rs b/src/swarm/peer/handshake.rs index c46df9c..038dac6 100644 --- a/src/swarm/peer/handshake.rs +++ b/src/swarm/peer/handshake.rs @@ -13,6 +13,12 @@ use crate::swarm::sync::SyncEvent; use crate::swarm::topology; use crate::transport::{self, ParsedMessage}; +/// Most peers a HELLO_REPLY lists, and most we take from one: each listed peer may get +/// a HELLO, so a long list (a hub's hundreds of neighbours, or a peer making up keys) +/// costs the recipient as much as it is long. A joining node needs only a few to find +/// the swarm; the member list gives it the rest once it is ready. +const MAX_LISTED_PEERS: usize = 64; + pub(crate) async fn remember_peer(state: &AppState, peer: &str) { if peer.is_empty() { warn!("Ignoring empty peer public key"); @@ -183,6 +189,12 @@ pub(super) async fn send_hello_reply( peers.push(known); } } + // Those the recipient would most likely pick as neighbours itself (lowest pair + // score with it, as `topology` ranks them), if there are too many. + if peers.len() > MAX_LISTED_PEERS { + peers.sort_by_cached_key(|known| topology::pair_score(peer, known)); + peers.truncate(MAX_LISTED_PEERS); + } let auth = state .swarm_key @@ -215,18 +227,31 @@ pub(super) async fn send_hello_reply( Ok(()) } +/// Greets the peers a HELLO_REPLY listed: at most `MAX_LISTED_PEERS`, only valid +/// identities, and, once the member list is known, only those that are our neighbours +/// (it says whom we greet; a listed peer that isn't one would get nothing from us, so +/// it isn't remembered either). pub(super) async fn discover_peers(state: &AppState, from_peer: &str, advertised_peers: &[String]) { - // TODO here we could add a trace t oshwo advertised_peers + let view_known = topology::view_known(state); + let mut taken = 0; for discovered_peer in advertised_peers { - if discovered_peer == from_peer { + if discovered_peer == from_peer || !state.transport.is_peer_id(discovered_peer) { continue; } - - remember_peer(state, discovered_peer).await; - - if !topology::is_neighbour(state, discovered_peer) { + if view_known && !topology::is_neighbour(state, discovered_peer) { continue; } + if taken == MAX_LISTED_PEERS { + debug!( + from = %from_peer, + listed = advertised_peers.len(), + "HELLO_REPLY listed more peers than we take; ignoring the rest" + ); + break; + } + taken += 1; + + remember_peer(state, discovered_peer).await; if let Err(error) = send_hello_once(state, discovered_peer).await { warn!( peer = %discovered_peer, |
