diff options
| author | tv <tv@krebsco.de> | 2026-11-01 05:00:43 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-01 05:00:43 +0100 |
| commit | 67a476525bf23fec7aa10a962668cc77cce6c685 (patch) | |
| tree | a259ef08154e1bc11efee95b22d3f615f564538b /src/transport/libp2p/book.rs | |
| parent | c08574fac02c781b615969943e3d0d95ee402537 (diff) | |
libp2p: dial newly announced peer addresses
Diffstat (limited to 'src/transport/libp2p/book.rs')
| -rw-r--r-- | src/transport/libp2p/book.rs | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/src/transport/libp2p/book.rs b/src/transport/libp2p/book.rs index 44b2694..7de4be7 100644 --- a/src/transport/libp2p/book.rs +++ b/src/transport/libp2p/book.rs @@ -41,6 +41,9 @@ pub(super) struct Book { /// connection to the peer closes, as a peer restarted elsewhere is found by what /// the others say. pub(super) identified: HashMap<PeerId, Vec<Multiaddr>>, + /// Addresses of directly connected peers dialled for a better path (`explore`): + /// not again while connected, unless our own interfaces change. + pub(super) explored: HashMap<PeerId, std::collections::HashSet<Multiaddr>>, pub(super) listening: Vec<Multiaddr>, /// Where the router forwards to our listen addresses (UPnP, `Libp2pConfig::upnp`). pub(super) mapped: Vec<Multiaddr>, @@ -213,6 +216,7 @@ impl Book { for peer in &stale { self.addresses.remove(peer); self.identified.remove(peer); + self.explored.remove(peer); self.relays.remove(peer); self.public_relays.remove(peer); self.continuum.remove(peer); @@ -475,6 +479,38 @@ impl Book { addresses.truncate(ADDRESSES_PER_PEER); } + /// The addresses `explore` dials `peer` at, noted as dialled: a node of the swarm + /// connected directly, at addresses of its not dialled so yet, and with `again` + /// not only those at an IP it isn't connected at (an inbound connection's remote + /// port isn't where the peer listens). + pub(super) fn to_explore(&mut self, peer: PeerId, again: bool) -> Vec<Multiaddr> { + if !self.continuum.contains(&peer) + || book_connection(&self.connections, &peer) != Some(Connection::Direct) + { + return Vec::new(); + } + let used: Vec<Option<std::net::IpAddr>> = self + .connections + .values() + .filter(|(connected, relayed, _)| *connected == peer && !relayed) + .map(|(_, _, address)| ip_of(address)) + .collect(); + let tried = self.explored.entry(peer).or_default(); + let candidates: Vec<Multiaddr> = self + .addresses + .get(&peer) + .into_iter() + .flatten() + .filter(|address| is_ip(address) && !left_out(&self.ignored, address)) + .filter(|address| again || !used.contains(&ip_of(address))) + .filter(|address| !tried.contains(*address)) + .take(EXPLORED_AT_ONCE) + .cloned() + .collect(); + tried.extend(candidates.iter().cloned()); + candidates + } + /// `peer`, connected, identified itself at `listen` (`published`): its direct /// addresses are those from now on, while connected (`remember`); those through /// relays and by name stay. Kept in order of `preference`: of a peer with many, @@ -520,7 +556,7 @@ impl Book { } /// The IP address `address` starts with, if any. -fn ip_of(address: &Multiaddr) -> Option<std::net::IpAddr> { +pub(super) fn ip_of(address: &Multiaddr) -> Option<std::net::IpAddr> { match address.iter().next() { Some(Protocol::Ip4(ip)) => Some(ip.into()), Some(Protocol::Ip6(ip)) => Some(ip.into()), |
