aboutsummaryrefslogtreecommitdiffstats
path: root/src/transport/libp2p/book.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/libp2p/book.rs')
-rw-r--r--src/transport/libp2p/book.rs55
1 files changed, 50 insertions, 5 deletions
diff --git a/src/transport/libp2p/book.rs b/src/transport/libp2p/book.rs
index f466aef..b2ce7bb 100644
--- a/src/transport/libp2p/book.rs
+++ b/src/transport/libp2p/book.rs
@@ -53,6 +53,9 @@ pub(super) struct Book {
pub(super) ignored: Vec<IpRange>,
/// `Libp2pConfig::prefer`: addresses there first (`preference`).
pub(super) preferred: Vec<IpRange>,
+ /// Which address ranges have a route from here (`routes`): those without are left
+ /// out, as if ignored.
+ pub(super) routes: Routes,
/// `Libp2pConfig::relay`: this node relays, and says so.
pub(super) serving: bool,
/// Relays named to pick (configured, listed), by peer: picked first.
@@ -275,7 +278,10 @@ impl Book {
direct.retain(|address| !first.contains(address));
direct.sort_by_key(|address| self.preferred_range(address));
first.extend(direct);
- first.retain(|address| !ignored(&self.ignored, address));
+ first.retain(|address| {
+ !ignored(&self.ignored, address)
+ && ip_of(address).is_none_or(|ip| self.routes.publishable(ip))
+ });
first
}
}
@@ -464,7 +470,7 @@ impl Book {
if !self.addresses.contains_key(&peer) && self.addresses.len() >= MAX_PEERS {
return;
}
- if left_out(&self.ignored, &address) {
+ if self.left_out(&address) {
return;
}
if self
@@ -481,6 +487,38 @@ impl Book {
addresses.truncate(ADDRESSES_PER_PEER);
}
+ /// Whether `address` can only be reached over a range left out: ignored
+ /// (`left_out`), or without a route from here (`routes`), directly or through a
+ /// relay there.
+ pub(super) fn left_out(&mut self, address: &Multiaddr) -> bool {
+ if left_out(&self.ignored, address) {
+ return true;
+ }
+ let at = if is_relayed(address) {
+ address
+ .iter()
+ .take_while(|protocol| !matches!(protocol, Protocol::P2pCircuit))
+ .collect::<Multiaddr>()
+ } else {
+ address.clone()
+ };
+ ip_of(&at).is_some_and(|ip| !self.routes.routable(ip))
+ }
+
+ /// Asks again which ranges have a route (`Routes::recheck`); the addresses in those
+ /// that lost theirs go.
+ pub(super) fn recheck_routes(&mut self) {
+ let lost = self.routes.recheck();
+ if lost.is_empty() {
+ return;
+ }
+ for known in self.addresses.values_mut() {
+ known.retain(|address| {
+ ip_of(address).is_none_or(|ip| !lost.iter().any(|range| range.contains(ip)))
+ });
+ }
+ }
+
/// 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
@@ -506,10 +544,17 @@ impl Book {
.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());
+ let candidates: Vec<Multiaddr> = candidates
+ .into_iter()
+ .filter(|address| !self.left_out(address))
+ .take(EXPLORED_AT_ONCE)
+ .collect();
+ self.explored
+ .entry(peer)
+ .or_default()
+ .extend(candidates.iter().cloned());
candidates
}
@@ -567,7 +612,7 @@ pub(super) fn ip_of(address: &Multiaddr) -> Option<std::net::IpAddr> {
}
/// Whether `ip` can be reached from the internet, as far as its range tells.
-fn is_public(ip: std::net::IpAddr) -> bool {
+pub(super) fn is_public(ip: std::net::IpAddr) -> bool {
use std::net::IpAddr;
match ip {
IpAddr::V4(ip) => {