aboutsummaryrefslogtreecommitdiffstats
path: root/src/transport
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport')
-rw-r--r--src/transport/libp2p.rs50
1 files changed, 40 insertions, 10 deletions
diff --git a/src/transport/libp2p.rs b/src/transport/libp2p.rs
index 6602c2e..2808fae 100644
--- a/src/transport/libp2p.rs
+++ b/src/transport/libp2p.rs
@@ -579,8 +579,9 @@ impl Book {
}
/// Where others could dial us directly: the announced addresses, or else those we
- /// listen on (`published`) and where the router forwards to them (`mapped`), without
- /// the peer ID.
+ /// listen on (`published`), where the router forwards to them (`mapped`), and where
+ /// AutoNAT found others can dial us (`public_address`: a port forwarded by hand, say),
+ /// without the peer ID.
fn direct(&self) -> Vec<Multiaddr> {
if !self.announced.is_empty() {
return self.announced.clone();
@@ -592,14 +593,24 @@ impl Book {
.cloned()
.collect();
let mut direct = published(&direct);
- direct.extend(
- self.mapped
- .iter()
- .filter(|address| !direct.contains(address))
- .cloned()
- .collect::<Vec<_>>(),
- );
- direct
+ let confirmed = self.public_address.iter().filter_map(|address| {
+ let mut address = address.clone();
+ if let Some(Protocol::P2p(_)) = address.iter().last() {
+ address.pop();
+ }
+ (!address.is_empty() && !is_relayed(&address)).then_some(address)
+ });
+ // First: the member list keeps only so many (`members::MAX_ADDRESSES`), and a
+ // node listening everywhere has many.
+ let mut first: Vec<Multiaddr> = Vec::new();
+ for address in self.mapped.iter().cloned().chain(confirmed) {
+ if !first.contains(&address) {
+ first.push(address);
+ }
+ }
+ direct.retain(|address| !first.contains(address));
+ first.extend(direct);
+ first
}
}
@@ -2449,6 +2460,25 @@ mod tests {
);
}
+ /// A port forwarded by hand: once AutoNAT found the node dialable at the router's
+ /// address, that is published with the listen addresses; announced ones still win.
+ #[test]
+ fn the_address_autonat_confirmed_is_published() {
+ let parse = |text: &str| text.parse::<Multiaddr>().unwrap();
+ let lan = parse("/ip4/10.23.1.5/udp/9663/quic-v1");
+ let public = parse("/ip4/91.65.180.254/udp/9663/quic-v1");
+ let mut book = Book {
+ listening: vec![lan.clone()],
+ ..Book::default()
+ };
+ assert_eq!(book.direct(), [lan.clone()]);
+ book.public_address = Some(public.clone().with_p2p(peer()).unwrap());
+ assert_eq!(book.direct(), [public.clone(), lan.clone()]);
+ let announced = parse("/dns4/example.org/udp/9663/quic-v1");
+ book.announced = vec![announced.clone()];
+ assert_eq!(book.direct(), [announced]);
+ }
+
#[test]
fn local_addresses_are_left_out_unless_there_are_only_local_ones() {
let parse = |text: &str| text.parse::<Multiaddr>().unwrap();