From e41f667bfdf1f2508889c3ec26408a2774a3a7e1 Mon Sep 17 00:00:00 2001 From: Eric Bourneuf Date: Thu, 16 May 2024 16:10:17 +0200 Subject: [PATCH 1/5] identify detects if address translation is required --- protocols/identify/src/behaviour.rs | 41 +++++++++++--- swarm/src/behaviour.rs | 29 +++++++++- swarm/src/lib.rs | 86 ++++++++++++++++++++--------- transports/tcp/src/lib.rs | 31 +---------- 4 files changed, 120 insertions(+), 67 deletions(-) diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index ac58ec311fc..653f98603e3 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -24,7 +24,10 @@ use libp2p_core::transport::PortUse; use libp2p_core::{multiaddr, ConnectedPoint, Endpoint, Multiaddr}; use libp2p_identity::PeerId; use libp2p_identity::PublicKey; -use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm}; +use libp2p_swarm::behaviour::{ + ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm, + NewExternalAddrCandidateEndpoint, +}; use libp2p_swarm::{ ConnectionDenied, DialError, ExternalAddresses, ListenAddresses, NetworkBehaviour, NotifyHandler, PeerAddresses, StreamUpgradeError, THandlerInEvent, ToSwarm, @@ -53,6 +56,9 @@ pub struct Behaviour { /// The address a remote observed for us. our_observed_addresses: HashMap, + /// Established connections information (Listener / Dialer / port_reuse or not) + connections_endpoints: HashMap, + /// Pending events to be emitted when polled. events: VecDeque>, /// The addresses of all peers that we have discovered. @@ -154,6 +160,7 @@ impl Behaviour { config, connected: HashMap::new(), our_observed_addresses: Default::default(), + connections_endpoints: Default::default(), events: VecDeque::new(), discovered_peers, listen_addresses: Default::default(), @@ -222,11 +229,14 @@ impl NetworkBehaviour for Behaviour { fn handle_established_inbound_connection( &mut self, - _: ConnectionId, + connection_id: ConnectionId, peer: PeerId, _: &Multiaddr, remote_addr: &Multiaddr, ) -> Result, ConnectionDenied> { + self.connections_endpoints + .insert(connection_id, NewExternalAddrCandidateEndpoint::Listener); + Ok(Handler::new( self.config.interval, peer, @@ -240,12 +250,17 @@ impl NetworkBehaviour for Behaviour { fn handle_established_outbound_connection( &mut self, - _: ConnectionId, + connection_id: ConnectionId, peer: PeerId, addr: &Multiaddr, _: Endpoint, - _: PortUse, + port_use: PortUse, ) -> Result, ConnectionDenied> { + self.connections_endpoints.insert( + connection_id, + NewExternalAddrCandidateEndpoint::Dialer { port_use }, + ); + Ok(Handler::new( self.config.interval, peer, @@ -287,11 +302,18 @@ impl NetworkBehaviour for Behaviour { } } + let endpoint = self + .connections_endpoints + .get(&id) + .expect("we are connected"); + match self.our_observed_addresses.entry(id) { Entry::Vacant(not_yet_observed) => { not_yet_observed.insert(observed.clone()); - self.events - .push_back(ToSwarm::NewExternalAddrCandidate(observed)); + self.events.push_back(ToSwarm::NewExternalAddrCandidate { + endpoint: *endpoint, + observed_addr: observed, + }); } Entry::Occupied(already_observed) if already_observed.get() == &observed => { // No-op, we already observed this address. @@ -304,8 +326,10 @@ impl NetworkBehaviour for Behaviour { ); *already_observed.get_mut() = observed.clone(); - self.events - .push_back(ToSwarm::NewExternalAddrCandidate(observed)); + self.events.push_back(ToSwarm::NewExternalAddrCandidate { + endpoint: *endpoint, + observed_addr: observed, + }); } } } @@ -396,6 +420,7 @@ impl NetworkBehaviour for Behaviour { } self.our_observed_addresses.remove(&connection_id); + self.connections_endpoints.remove(&connection_id); } FromSwarm::DialFailure(DialFailure { peer_id, error, .. }) => { if let (Some(peer_id), Some(cache), DialError::Transport(errors)) = diff --git a/swarm/src/behaviour.rs b/swarm/src/behaviour.rs index b7045c0ec3a..e1c135e3525 100644 --- a/swarm/src/behaviour.rs +++ b/swarm/src/behaviour.rs @@ -219,6 +219,14 @@ pub trait NetworkBehaviour: 'static { -> Poll>>; } +#[derive(Debug, Copy, Clone)] +pub enum NewExternalAddrCandidateEndpoint { + /// no translation is required + Listener, + /// translation is required when dialed with PortUse::New + Dialer { port_use: PortUse }, +} + /// A command issued from a [`NetworkBehaviour`] for the [`Swarm`]. /// /// [`Swarm`]: super::Swarm @@ -282,7 +290,10 @@ pub enum ToSwarm { /// - A protocol such as identify obtained it from a remote. /// - The user provided it based on configuration. /// - We made an educated guess based on one of our listen addresses. - NewExternalAddrCandidate(Multiaddr), + NewExternalAddrCandidate { + endpoint: NewExternalAddrCandidateEndpoint, + observed_addr: Multiaddr, + }, /// Indicates to the [`Swarm`](crate::Swarm) that the provided address is confirmed to be externally reachable. /// @@ -341,7 +352,13 @@ impl ToSwarm { peer_id, connection, }, - ToSwarm::NewExternalAddrCandidate(addr) => ToSwarm::NewExternalAddrCandidate(addr), + ToSwarm::NewExternalAddrCandidate { + endpoint, + observed_addr: addr, + } => ToSwarm::NewExternalAddrCandidate { + endpoint, + observed_addr: addr, + }, ToSwarm::ExternalAddrConfirmed(addr) => ToSwarm::ExternalAddrConfirmed(addr), ToSwarm::ExternalAddrExpired(addr) => ToSwarm::ExternalAddrExpired(addr), ToSwarm::NewExternalAddrOfPeer { @@ -372,7 +389,13 @@ impl ToSwarm { handler, event, }, - ToSwarm::NewExternalAddrCandidate(addr) => ToSwarm::NewExternalAddrCandidate(addr), + ToSwarm::NewExternalAddrCandidate { + endpoint, + observed_addr: addr, + } => ToSwarm::NewExternalAddrCandidate { + endpoint, + observed_addr: addr, + }, ToSwarm::ExternalAddrConfirmed(addr) => ToSwarm::ExternalAddrConfirmed(addr), ToSwarm::ExternalAddrExpired(addr) => ToSwarm::ExternalAddrExpired(addr), ToSwarm::CloseConnection { diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 3c74e82f28e..2b87371b2d2 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -106,6 +106,7 @@ pub mod derive_prelude { pub use libp2p_identity::PeerId; } +use behaviour::NewExternalAddrCandidateEndpoint; pub use behaviour::{ AddressChange, CloseConnection, ConnectionClosed, DialFailure, ExpiredListenAddr, ExternalAddrExpired, ExternalAddresses, FromSwarm, ListenAddresses, ListenFailure, @@ -119,6 +120,7 @@ pub use handler::{ ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerSelect, OneShotHandler, OneShotHandlerConfig, StreamUpgradeError, SubstreamProtocol, }; +use libp2p_core::transport::PortUse; #[cfg(feature = "macros")] pub use libp2p_swarm_derive::NetworkBehaviour; pub use listen_opts::ListenOpts; @@ -1132,39 +1134,69 @@ where self.pending_handler_event = Some((peer_id, handler, event)); } - ToSwarm::NewExternalAddrCandidate(addr) => { + ToSwarm::NewExternalAddrCandidate { + endpoint, + observed_addr, + } => { // Apply address translation to the candidate address. // For TCP without port-reuse, the observed address contains an ephemeral port which needs to be replaced by the port of a listen address. - let translated_addresses = { - let mut addrs: Vec<_> = self - .listened_addrs - .values() - .flatten() - .filter_map(|server| self.transport.address_translation(server, &addr)) - .collect(); - - // remove duplicates - addrs.sort_unstable(); - addrs.dedup(); - addrs - }; - - // If address translation yielded nothing, broadcast the original candidate address. - if translated_addresses.is_empty() { - self.behaviour - .on_swarm_event(FromSwarm::NewExternalAddrCandidate( - NewExternalAddrCandidate { addr: &addr }, - )); - self.pending_swarm_events - .push_back(SwarmEvent::NewExternalAddrCandidate { address: addr }); - } else { - for addr in translated_addresses { + match endpoint { + NewExternalAddrCandidateEndpoint::Listener + | NewExternalAddrCandidateEndpoint::Dialer { + port_use: PortUse::Reuse, + } => { + // no translation is required : use the observed address self.behaviour .on_swarm_event(FromSwarm::NewExternalAddrCandidate( - NewExternalAddrCandidate { addr: &addr }, + NewExternalAddrCandidate { + addr: &observed_addr, + }, )); self.pending_swarm_events - .push_back(SwarmEvent::NewExternalAddrCandidate { address: addr }); + .push_back(SwarmEvent::NewExternalAddrCandidate { + address: observed_addr, + }); + } + NewExternalAddrCandidateEndpoint::Dialer { + port_use: PortUse::New, + } => { + let mut translated_addresses: Vec<_> = self + .listened_addrs + .values() + .flatten() + .filter_map(|server| { + self.transport.address_translation(server, &observed_addr) + }) + .collect(); + + // remove duplicates + translated_addresses.sort_unstable(); + translated_addresses.dedup(); + + // If address translation yielded nothing, broadcast the original candidate address. + if translated_addresses.is_empty() { + self.behaviour + .on_swarm_event(FromSwarm::NewExternalAddrCandidate( + NewExternalAddrCandidate { + addr: &observed_addr, + }, + )); + self.pending_swarm_events.push_back( + SwarmEvent::NewExternalAddrCandidate { + address: observed_addr, + }, + ); + } else { + for addr in translated_addresses { + self.behaviour + .on_swarm_event(FromSwarm::NewExternalAddrCandidate( + NewExternalAddrCandidate { addr: &addr }, + )); + self.pending_swarm_events.push_back( + SwarmEvent::NewExternalAddrCandidate { address: addr }, + ); + } + } } } } diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index d01d83157aa..088de025bda 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -47,11 +47,11 @@ use libp2p_core::{ use provider::{Incoming, Provider}; use socket2::{Domain, Socket, Type}; use std::{ - collections::{HashMap, HashSet, VecDeque}, + collections::{HashSet, VecDeque}, io, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, TcpListener}, pin::Pin, - sync::{Arc, Mutex, RwLock}, + sync::{Arc, RwLock}, task::{Context, Poll, Waker}, time::Duration, }; @@ -75,8 +75,6 @@ struct PortReuse { /// The addresses and ports of the listening sockets /// registered as eligible for port reuse when dialing listen_addrs: Arc>>, - /// Contains a hashset of all multiaddr that where dialed from a reused port. - addr_dialed_from_reuse_poralways_reused_port: Arc>>, } impl PortReuse { @@ -129,27 +127,6 @@ impl PortReuse { None } - - fn dialed_from_reuse_port(&self, addr: SocketAddr) { - self.addr_dialed_from_reuse_poralways_reused_port - .lock() - .expect("`dialed_as_listener` never panic while holding the lock") - .entry(addr) - .or_insert(true); - } - - fn was_dialed_from_reuse_port(&self, addr: &Multiaddr) -> bool { - if let Ok(socket_addr) = multiaddr_to_socketaddr(addr.clone()) { - *self - .addr_dialed_from_reuse_poralways_reused_port - .lock() - .expect("`already_dialed_as_listener` never panic while holding the lock") - .entry(socket_addr) - .or_insert(false) - } else { - false - } - } } impl Config { @@ -398,7 +375,6 @@ where socket .bind(&socket_addr.into()) .map_err(TransportError::Other)?; - self.port_reuse.dialed_from_reuse_port(socket_addr); } _ => {} } @@ -444,9 +420,6 @@ where if !is_tcp_addr(listen) || !is_tcp_addr(observed) { return None; } - if self.port_reuse.was_dialed_from_reuse_port(listen) { - return Some(observed.clone()); - } address_translation(listen, observed) } From 235447bbc2e6aaf5b16b030909745f236ee2f1b3 Mon Sep 17 00:00:00 2001 From: Eric Bourneuf Date: Thu, 16 May 2024 19:04:22 +0200 Subject: [PATCH 2/5] homogeneize fully-p2p-qualified addresses to avoid double probe --- protocols/identify/src/behaviour.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index 653f98603e3..7c8e0269461 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -256,6 +256,14 @@ impl NetworkBehaviour for Behaviour { _: Endpoint, port_use: PortUse, ) -> Result, ConnectionDenied> { + // Contrary to inbound events, outbound events are full-p2p qualified + // so we remove /p2p/ in order to be homogeneous + // this will avoid Autonatv2 to probe twice the same address (fully-p2p-qualified + not fully-p2p-qualified) + let mut addr = addr.clone(); + if matches!(addr.iter().last(), Some(multiaddr::Protocol::P2p(_))) { + addr.pop(); + } + self.connections_endpoints.insert( connection_id, NewExternalAddrCandidateEndpoint::Dialer { port_use }, From 6103cd8a263e6844609d7e8091bfe908933e94e1 Mon Sep 17 00:00:00 2001 From: Eric Bourneuf Date: Wed, 22 May 2024 10:44:15 +0200 Subject: [PATCH 3/5] feat(nat): get rid of Transport::address_translation --- protocols/identify/src/behaviour.rs | 140 ++++++++++++++++++++++------ swarm/src/behaviour.rs | 29 +----- swarm/src/lib.rs | 74 ++------------- 3 files changed, 120 insertions(+), 123 deletions(-) diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index 7c8e0269461..e3a0c677f48 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -20,14 +20,12 @@ use crate::handler::{self, Handler, InEvent}; use crate::protocol::{Info, UpgradeError}; +use libp2p_core::multiaddr::Protocol; use libp2p_core::transport::PortUse; -use libp2p_core::{multiaddr, ConnectedPoint, Endpoint, Multiaddr}; +use libp2p_core::{address_translation, multiaddr, ConnectedPoint, Endpoint, Multiaddr}; use libp2p_identity::PeerId; use libp2p_identity::PublicKey; -use libp2p_swarm::behaviour::{ - ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm, - NewExternalAddrCandidateEndpoint, -}; +use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm}; use libp2p_swarm::{ ConnectionDenied, DialError, ExternalAddresses, ListenAddresses, NetworkBehaviour, NotifyHandler, PeerAddresses, StreamUpgradeError, THandlerInEvent, ToSwarm, @@ -43,6 +41,50 @@ use std::{ time::Duration, }; +/// Whether an [`Multiaddr`] is a valid for the QUIC transport. +fn is_quic_addr(addr: &Multiaddr, v1: bool) -> bool { + use Protocol::*; + let mut iter = addr.iter(); + let Some(first) = iter.next() else { + return false; + }; + let Some(second) = iter.next() else { + return false; + }; + let Some(third) = iter.next() else { + return false; + }; + let fourth = iter.next(); + let fifth = iter.next(); + + matches!(first, Ip4(_) | Ip6(_) | Dns(_) | Dns4(_) | Dns6(_)) + && matches!(second, Udp(_)) + && if v1 { + matches!(third, QuicV1) + } else { + matches!(third, Quic) + } + && matches!(fourth, Some(P2p(_)) | None) + && fifth.is_none() +} + +fn is_tcp_addr(addr: &Multiaddr) -> bool { + use Protocol::*; + + let mut iter = addr.iter(); + + let first = match iter.next() { + None => return false, + Some(p) => p, + }; + let second = match iter.next() { + None => return false, + Some(p) => p, + }; + + matches!(first, Ip4(_) | Ip6(_) | Dns(_) | Dns4(_) | Dns6(_)) && matches!(second, Tcp(_)) +} + /// Network behaviour that automatically identifies nodes periodically, returns information /// about them, and answers identify queries from other nodes. /// @@ -56,8 +98,8 @@ pub struct Behaviour { /// The address a remote observed for us. our_observed_addresses: HashMap, - /// Established connections information (Listener / Dialer / port_reuse or not) - connections_endpoints: HashMap, + /// The outbound connections established without port reuse (require translation) + outbound_connections_without_port_reuse: HashSet, /// Pending events to be emitted when polled. events: VecDeque>, @@ -160,7 +202,7 @@ impl Behaviour { config, connected: HashMap::new(), our_observed_addresses: Default::default(), - connections_endpoints: Default::default(), + outbound_connections_without_port_reuse: Default::default(), events: VecDeque::new(), discovered_peers, listen_addresses: Default::default(), @@ -221,6 +263,57 @@ impl Behaviour { .cloned() .collect() } + + fn emit_new_external_addr_candidate_event( + &mut self, + connection_id: ConnectionId, + observed: &Multiaddr, + ) { + if self + .outbound_connections_without_port_reuse + .contains(&connection_id) + { + // Apply address translation to the candidate address. + // For TCP without port-reuse, the observed address contains an ephemeral port which needs to be replaced by the port of a listen address. + let translated_addresses = { + let mut addrs: Vec<_> = self + .listen_addresses + .iter() + .filter_map(|server| { + if (is_tcp_addr(server) && is_tcp_addr(&observed)) + || (is_quic_addr(server, true) && is_quic_addr(&observed, true)) + || (is_quic_addr(server, false) && is_quic_addr(&observed, false)) + { + address_translation(server, &observed) + } else { + None + } + }) + .collect(); + + // remove duplicates + addrs.sort_unstable(); + addrs.dedup(); + addrs + }; + + // If address translation yielded nothing, broadcast the original candidate address. + if translated_addresses.is_empty() { + self.events + .push_back(ToSwarm::NewExternalAddrCandidate(observed.clone())); + } else { + for addr in translated_addresses { + self.events + .push_back(ToSwarm::NewExternalAddrCandidate(addr)); + } + } + } else { + // outgoing connection dialed with port reuse + // incomming connection + self.events + .push_back(ToSwarm::NewExternalAddrCandidate(observed.clone())); + } + } } impl NetworkBehaviour for Behaviour { @@ -229,14 +322,11 @@ impl NetworkBehaviour for Behaviour { fn handle_established_inbound_connection( &mut self, - connection_id: ConnectionId, + _: ConnectionId, peer: PeerId, _: &Multiaddr, remote_addr: &Multiaddr, ) -> Result, ConnectionDenied> { - self.connections_endpoints - .insert(connection_id, NewExternalAddrCandidateEndpoint::Listener); - Ok(Handler::new( self.config.interval, peer, @@ -264,10 +354,10 @@ impl NetworkBehaviour for Behaviour { addr.pop(); } - self.connections_endpoints.insert( - connection_id, - NewExternalAddrCandidateEndpoint::Dialer { port_use }, - ); + if port_use == PortUse::New { + self.outbound_connections_without_port_reuse + .insert(connection_id); + } Ok(Handler::new( self.config.interval, @@ -310,18 +400,10 @@ impl NetworkBehaviour for Behaviour { } } - let endpoint = self - .connections_endpoints - .get(&id) - .expect("we are connected"); - match self.our_observed_addresses.entry(id) { Entry::Vacant(not_yet_observed) => { not_yet_observed.insert(observed.clone()); - self.events.push_back(ToSwarm::NewExternalAddrCandidate { - endpoint: *endpoint, - observed_addr: observed, - }); + self.emit_new_external_addr_candidate_event(id, &observed); } Entry::Occupied(already_observed) if already_observed.get() == &observed => { // No-op, we already observed this address. @@ -334,10 +416,7 @@ impl NetworkBehaviour for Behaviour { ); *already_observed.get_mut() = observed.clone(); - self.events.push_back(ToSwarm::NewExternalAddrCandidate { - endpoint: *endpoint, - observed_addr: observed, - }); + self.emit_new_external_addr_candidate_event(id, &observed); } } } @@ -428,7 +507,8 @@ impl NetworkBehaviour for Behaviour { } self.our_observed_addresses.remove(&connection_id); - self.connections_endpoints.remove(&connection_id); + self.outbound_connections_without_port_reuse + .remove(&connection_id); } FromSwarm::DialFailure(DialFailure { peer_id, error, .. }) => { if let (Some(peer_id), Some(cache), DialError::Transport(errors)) = diff --git a/swarm/src/behaviour.rs b/swarm/src/behaviour.rs index e1c135e3525..b7045c0ec3a 100644 --- a/swarm/src/behaviour.rs +++ b/swarm/src/behaviour.rs @@ -219,14 +219,6 @@ pub trait NetworkBehaviour: 'static { -> Poll>>; } -#[derive(Debug, Copy, Clone)] -pub enum NewExternalAddrCandidateEndpoint { - /// no translation is required - Listener, - /// translation is required when dialed with PortUse::New - Dialer { port_use: PortUse }, -} - /// A command issued from a [`NetworkBehaviour`] for the [`Swarm`]. /// /// [`Swarm`]: super::Swarm @@ -290,10 +282,7 @@ pub enum ToSwarm { /// - A protocol such as identify obtained it from a remote. /// - The user provided it based on configuration. /// - We made an educated guess based on one of our listen addresses. - NewExternalAddrCandidate { - endpoint: NewExternalAddrCandidateEndpoint, - observed_addr: Multiaddr, - }, + NewExternalAddrCandidate(Multiaddr), /// Indicates to the [`Swarm`](crate::Swarm) that the provided address is confirmed to be externally reachable. /// @@ -352,13 +341,7 @@ impl ToSwarm { peer_id, connection, }, - ToSwarm::NewExternalAddrCandidate { - endpoint, - observed_addr: addr, - } => ToSwarm::NewExternalAddrCandidate { - endpoint, - observed_addr: addr, - }, + ToSwarm::NewExternalAddrCandidate(addr) => ToSwarm::NewExternalAddrCandidate(addr), ToSwarm::ExternalAddrConfirmed(addr) => ToSwarm::ExternalAddrConfirmed(addr), ToSwarm::ExternalAddrExpired(addr) => ToSwarm::ExternalAddrExpired(addr), ToSwarm::NewExternalAddrOfPeer { @@ -389,13 +372,7 @@ impl ToSwarm { handler, event, }, - ToSwarm::NewExternalAddrCandidate { - endpoint, - observed_addr: addr, - } => ToSwarm::NewExternalAddrCandidate { - endpoint, - observed_addr: addr, - }, + ToSwarm::NewExternalAddrCandidate(addr) => ToSwarm::NewExternalAddrCandidate(addr), ToSwarm::ExternalAddrConfirmed(addr) => ToSwarm::ExternalAddrConfirmed(addr), ToSwarm::ExternalAddrExpired(addr) => ToSwarm::ExternalAddrExpired(addr), ToSwarm::CloseConnection { diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 2b87371b2d2..c528e8d586f 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -106,7 +106,6 @@ pub mod derive_prelude { pub use libp2p_identity::PeerId; } -use behaviour::NewExternalAddrCandidateEndpoint; pub use behaviour::{ AddressChange, CloseConnection, ConnectionClosed, DialFailure, ExpiredListenAddr, ExternalAddrExpired, ExternalAddresses, FromSwarm, ListenAddresses, ListenFailure, @@ -120,7 +119,6 @@ pub use handler::{ ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerSelect, OneShotHandler, OneShotHandlerConfig, StreamUpgradeError, SubstreamProtocol, }; -use libp2p_core::transport::PortUse; #[cfg(feature = "macros")] pub use libp2p_swarm_derive::NetworkBehaviour; pub use listen_opts::ListenOpts; @@ -1134,71 +1132,13 @@ where self.pending_handler_event = Some((peer_id, handler, event)); } - ToSwarm::NewExternalAddrCandidate { - endpoint, - observed_addr, - } => { - // Apply address translation to the candidate address. - // For TCP without port-reuse, the observed address contains an ephemeral port which needs to be replaced by the port of a listen address. - match endpoint { - NewExternalAddrCandidateEndpoint::Listener - | NewExternalAddrCandidateEndpoint::Dialer { - port_use: PortUse::Reuse, - } => { - // no translation is required : use the observed address - self.behaviour - .on_swarm_event(FromSwarm::NewExternalAddrCandidate( - NewExternalAddrCandidate { - addr: &observed_addr, - }, - )); - self.pending_swarm_events - .push_back(SwarmEvent::NewExternalAddrCandidate { - address: observed_addr, - }); - } - NewExternalAddrCandidateEndpoint::Dialer { - port_use: PortUse::New, - } => { - let mut translated_addresses: Vec<_> = self - .listened_addrs - .values() - .flatten() - .filter_map(|server| { - self.transport.address_translation(server, &observed_addr) - }) - .collect(); - - // remove duplicates - translated_addresses.sort_unstable(); - translated_addresses.dedup(); - - // If address translation yielded nothing, broadcast the original candidate address. - if translated_addresses.is_empty() { - self.behaviour - .on_swarm_event(FromSwarm::NewExternalAddrCandidate( - NewExternalAddrCandidate { - addr: &observed_addr, - }, - )); - self.pending_swarm_events.push_back( - SwarmEvent::NewExternalAddrCandidate { - address: observed_addr, - }, - ); - } else { - for addr in translated_addresses { - self.behaviour - .on_swarm_event(FromSwarm::NewExternalAddrCandidate( - NewExternalAddrCandidate { addr: &addr }, - )); - self.pending_swarm_events.push_back( - SwarmEvent::NewExternalAddrCandidate { address: addr }, - ); - } - } - } - } + ToSwarm::NewExternalAddrCandidate(addr) => { + self.behaviour + .on_swarm_event(FromSwarm::NewExternalAddrCandidate( + NewExternalAddrCandidate { addr: &addr }, + )); + self.pending_swarm_events + .push_back(SwarmEvent::NewExternalAddrCandidate { address: addr }); } ToSwarm::ExternalAddrConfirmed(addr) => { self.add_external_address(addr.clone()); From 4b16e4291255fc1601588252ba65b7edc59f78d9 Mon Sep 17 00:00:00 2001 From: Eric Bourneuf Date: Thu, 23 May 2024 18:00:47 +0200 Subject: [PATCH 4/5] Thomas remarks --- protocols/identify/src/behaviour.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index e3a0c677f48..d42032badf4 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -99,7 +99,7 @@ pub struct Behaviour { our_observed_addresses: HashMap, /// The outbound connections established without port reuse (require translation) - outbound_connections_without_port_reuse: HashSet, + outbound_connections_with_ephemeral_port: HashSet, /// Pending events to be emitted when polled. events: VecDeque>, @@ -202,7 +202,7 @@ impl Behaviour { config, connected: HashMap::new(), our_observed_addresses: Default::default(), - outbound_connections_without_port_reuse: Default::default(), + outbound_connections_with_ephemeral_port: Default::default(), events: VecDeque::new(), discovered_peers, listen_addresses: Default::default(), @@ -270,7 +270,7 @@ impl Behaviour { observed: &Multiaddr, ) { if self - .outbound_connections_without_port_reuse + .outbound_connections_with_ephemeral_port .contains(&connection_id) { // Apply address translation to the candidate address. @@ -307,12 +307,13 @@ impl Behaviour { .push_back(ToSwarm::NewExternalAddrCandidate(addr)); } } - } else { - // outgoing connection dialed with port reuse - // incomming connection - self.events - .push_back(ToSwarm::NewExternalAddrCandidate(observed.clone())); + return; } + + // outgoing connection dialed with port reuse + // incomming connection + self.events + .push_back(ToSwarm::NewExternalAddrCandidate(observed.clone())); } } @@ -355,7 +356,7 @@ impl NetworkBehaviour for Behaviour { } if port_use == PortUse::New { - self.outbound_connections_without_port_reuse + self.outbound_connections_with_ephemeral_port .insert(connection_id); } @@ -507,7 +508,7 @@ impl NetworkBehaviour for Behaviour { } self.our_observed_addresses.remove(&connection_id); - self.outbound_connections_without_port_reuse + self.outbound_connections_with_ephemeral_port .remove(&connection_id); } FromSwarm::DialFailure(DialFailure { peer_id, error, .. }) => { From 0f538f316e06acf289b4b95ae3a5c512bc62b944 Mon Sep 17 00:00:00 2001 From: Eric Bourneuf Date: Thu, 23 May 2024 18:27:46 +0200 Subject: [PATCH 5/5] removed Transport::address_translation and moved generic address_translation to libp2p_swarm --- core/src/either.rs | 7 -- core/src/lib.rs | 3 - core/src/transport.rs | 18 ----- core/src/transport/and_then.rs | 4 - core/src/transport/boxed.rs | 9 --- core/src/transport/choice.rs | 8 -- core/src/transport/dummy.rs | 4 - core/src/transport/global_only.rs | 4 - core/src/transport/map.rs | 4 - core/src/transport/map_err.rs | 4 - core/src/transport/memory.rs | 4 - core/src/transport/optional.rs | 8 -- core/src/transport/timeout.rs | 4 - core/src/transport/upgrade.rs | 8 -- misc/metrics/src/bandwidth.rs | 4 - protocols/identify/src/behaviour.rs | 6 +- protocols/mdns/src/behaviour/iface/query.rs | 7 +- protocols/relay/src/priv_client/transport.rs | 4 - swarm/src/lib.rs | 2 + {core => swarm}/src/translation.rs | 2 +- transports/dns/src/lib.rs | 8 -- transports/quic/src/transport.rs | 36 --------- transports/quic/tests/smoke.rs | 8 -- transports/tcp/src/lib.rs | 80 ------------------- transports/uds/src/lib.rs | 8 -- transports/webrtc-websys/src/transport.rs | 4 - transports/webrtc/src/tokio/transport.rs | 4 - transports/websocket-websys/src/lib.rs | 4 - transports/websocket/src/framed.rs | 4 - transports/websocket/src/lib.rs | 4 - .../webtransport-websys/src/transport.rs | 4 - 31 files changed, 9 insertions(+), 269 deletions(-) rename {core => swarm}/src/translation.rs (98%) diff --git a/core/src/either.rs b/core/src/either.rs index 590dcd66595..2593174290c 100644 --- a/core/src/either.rs +++ b/core/src/either.rs @@ -192,11 +192,4 @@ where }, } } - - fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { - match self { - Either::Left(a) => a.address_translation(server, observed), - Either::Right(b) => b.address_translation(server, observed), - } - } } diff --git a/core/src/lib.rs b/core/src/lib.rs index abb83481d6c..cf48ee25329 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -45,8 +45,6 @@ mod proto { pub use multiaddr; pub type Negotiated = multistream_select::Negotiated; -mod translation; - pub mod connection; pub mod either; pub mod muxing; @@ -61,7 +59,6 @@ pub use multihash; pub use muxing::StreamMuxer; pub use peer_record::PeerRecord; pub use signed_envelope::SignedEnvelope; -pub use translation::address_translation; pub use transport::Transport; pub use upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; diff --git a/core/src/transport.rs b/core/src/transport.rs index 82aab3fda58..5202c3e0510 100644 --- a/core/src/transport.rs +++ b/core/src/transport.rs @@ -175,24 +175,6 @@ pub trait Transport { cx: &mut Context<'_>, ) -> Poll>; - /// Performs a transport-specific mapping of an address `observed` by a remote onto a - /// local `listen` address to yield an address for the local node that may be reachable - /// for other peers. - /// - /// This is relevant for transports where Network Address Translation (NAT) can occur - /// so that e.g. the peer is observed at a different IP than the IP of the local - /// listening address. See also [`address_translation`][crate::address_translation]. - /// - /// Within [`libp2p::Swarm`]() this is - /// used when extending the listening addresses of the local peer with external addresses - /// observed by remote peers. - /// On transports where this is not relevant (i.e. no NATs are present) `None` should be - /// returned for the sake of de-duplication. - /// - /// Note: if the listen or observed address is not a valid address of this transport, - /// `None` should be returned as well. - fn address_translation(&self, listen: &Multiaddr, observed: &Multiaddr) -> Option; - /// Boxes the transport, including custom transport errors. fn boxed(self) -> boxed::Boxed where diff --git a/core/src/transport/and_then.rs b/core/src/transport/and_then.rs index fb6ed2949a4..e85703f77fb 100644 --- a/core/src/transport/and_then.rs +++ b/core/src/transport/and_then.rs @@ -92,10 +92,6 @@ where Ok(future) } - fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { - self.transport.address_translation(server, observed) - } - fn poll( self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/core/src/transport/boxed.rs b/core/src/transport/boxed.rs index 7b7262c977d..596ab262221 100644 --- a/core/src/transport/boxed.rs +++ b/core/src/transport/boxed.rs @@ -63,7 +63,6 @@ trait Abstract { addr: Multiaddr, opts: DialOpts, ) -> Result, TransportError>; - fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option; fn poll( self: Pin<&mut Self>, cx: &mut Context<'_>, @@ -100,10 +99,6 @@ where Ok(Box::pin(fut) as Dial<_>) } - fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { - Transport::address_translation(self, server, observed) - } - fn poll( self: Pin<&mut Self>, cx: &mut Context<'_>, @@ -151,10 +146,6 @@ impl Transport for Boxed { self.inner.dial(addr, opts) } - fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { - self.inner.address_translation(server, observed) - } - fn poll( mut self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/core/src/transport/choice.rs b/core/src/transport/choice.rs index 097dcd7de2f..4339f6bba71 100644 --- a/core/src/transport/choice.rs +++ b/core/src/transport/choice.rs @@ -140,14 +140,6 @@ where Err(TransportError::MultiaddrNotSupported(addr)) } - fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { - if let Some(addr) = self.0.address_translation(server, observed) { - Some(addr) - } else { - self.1.address_translation(server, observed) - } - } - fn poll( self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/core/src/transport/dummy.rs b/core/src/transport/dummy.rs index a8b1e7e1a90..72558d34a79 100644 --- a/core/src/transport/dummy.rs +++ b/core/src/transport/dummy.rs @@ -79,10 +79,6 @@ impl Transport for DummyTransport { Err(TransportError::MultiaddrNotSupported(addr)) } - fn address_translation(&self, _server: &Multiaddr, _observed: &Multiaddr) -> Option { - None - } - fn poll( self: Pin<&mut Self>, _: &mut Context<'_>, diff --git a/core/src/transport/global_only.rs b/core/src/transport/global_only.rs index d975070ea0f..83774f37004 100644 --- a/core/src/transport/global_only.rs +++ b/core/src/transport/global_only.rs @@ -314,10 +314,6 @@ impl crate::Transport for Transport { } } - fn address_translation(&self, listen: &Multiaddr, observed: &Multiaddr) -> Option { - self.inner.address_translation(listen, observed) - } - fn poll( mut self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/core/src/transport/map.rs b/core/src/transport/map.rs index a7505d36e6c..9aab84ba8b1 100644 --- a/core/src/transport/map.rs +++ b/core/src/transport/map.rs @@ -91,10 +91,6 @@ where }) } - fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { - self.transport.address_translation(server, observed) - } - fn poll( self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/core/src/transport/map_err.rs b/core/src/transport/map_err.rs index 20580c23537..5d44af9af2e 100644 --- a/core/src/transport/map_err.rs +++ b/core/src/transport/map_err.rs @@ -80,10 +80,6 @@ where } } - fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { - self.transport.address_translation(server, observed) - } - fn poll( self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/core/src/transport/memory.rs b/core/src/transport/memory.rs index 72511243e58..85680265e8b 100644 --- a/core/src/transport/memory.rs +++ b/core/src/transport/memory.rs @@ -226,10 +226,6 @@ impl Transport for MemoryTransport { DialFuture::new(port).ok_or(TransportError::Other(MemoryTransportError::Unreachable)) } - fn address_translation(&self, _server: &Multiaddr, _observed: &Multiaddr) -> Option { - None - } - fn poll( mut self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/core/src/transport/optional.rs b/core/src/transport/optional.rs index f381d98f163..f18bfa441b0 100644 --- a/core/src/transport/optional.rs +++ b/core/src/transport/optional.rs @@ -92,14 +92,6 @@ where } } - fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { - if let Some(inner) = &self.0 { - inner.address_translation(server, observed) - } else { - None - } - } - fn poll( self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/core/src/transport/timeout.rs b/core/src/transport/timeout.rs index 1ed4f8a5796..830ed099629 100644 --- a/core/src/transport/timeout.rs +++ b/core/src/transport/timeout.rs @@ -115,10 +115,6 @@ where }) } - fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { - self.inner.address_translation(server, observed) - } - fn poll( self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/core/src/transport/upgrade.rs b/core/src/transport/upgrade.rs index 2a90172e710..66b9e7509af 100644 --- a/core/src/transport/upgrade.rs +++ b/core/src/transport/upgrade.rs @@ -356,10 +356,6 @@ where self.0.listen_on(id, addr) } - fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { - self.0.address_translation(server, observed) - } - fn poll( self: Pin<&mut Self>, cx: &mut Context<'_>, @@ -431,10 +427,6 @@ where .map_err(|err| err.map(TransportUpgradeError::Transport)) } - fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { - self.inner.address_translation(server, observed) - } - fn poll( self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/misc/metrics/src/bandwidth.rs b/misc/metrics/src/bandwidth.rs index 366283130d5..8a0f54e5b65 100644 --- a/misc/metrics/src/bandwidth.rs +++ b/misc/metrics/src/bandwidth.rs @@ -98,10 +98,6 @@ where }))) } - fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { - self.transport.address_translation(server, observed) - } - fn poll( self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index d42032badf4..5af8ce23ab7 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -22,13 +22,13 @@ use crate::handler::{self, Handler, InEvent}; use crate::protocol::{Info, UpgradeError}; use libp2p_core::multiaddr::Protocol; use libp2p_core::transport::PortUse; -use libp2p_core::{address_translation, multiaddr, ConnectedPoint, Endpoint, Multiaddr}; +use libp2p_core::{multiaddr, ConnectedPoint, Endpoint, Multiaddr}; use libp2p_identity::PeerId; use libp2p_identity::PublicKey; use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm}; use libp2p_swarm::{ - ConnectionDenied, DialError, ExternalAddresses, ListenAddresses, NetworkBehaviour, - NotifyHandler, PeerAddresses, StreamUpgradeError, THandlerInEvent, ToSwarm, + address_translation, ConnectionDenied, DialError, ExternalAddresses, ListenAddresses, + NetworkBehaviour, NotifyHandler, PeerAddresses, StreamUpgradeError, THandlerInEvent, ToSwarm, }; use libp2p_swarm::{ConnectionId, THandler, THandlerOutEvent}; diff --git a/protocols/mdns/src/behaviour/iface/query.rs b/protocols/mdns/src/behaviour/iface/query.rs index eeb699fca6b..f28c39fb245 100644 --- a/protocols/mdns/src/behaviour/iface/query.rs +++ b/protocols/mdns/src/behaviour/iface/query.rs @@ -24,10 +24,9 @@ use hickory_proto::{ op::Message, rr::{Name, RData}, }; -use libp2p_core::{ - address_translation, - multiaddr::{Multiaddr, Protocol}, -}; +use libp2p_core::multiaddr::{Multiaddr, Protocol}; +use libp2p_swarm::address_translation; + use libp2p_identity::PeerId; use std::time::Instant; use std::{fmt, net::SocketAddr, str, time::Duration}; diff --git a/protocols/relay/src/priv_client/transport.rs b/protocols/relay/src/priv_client/transport.rs index c4cc4b6a6d0..54587719793 100644 --- a/protocols/relay/src/priv_client/transport.rs +++ b/protocols/relay/src/priv_client/transport.rs @@ -210,10 +210,6 @@ impl libp2p_core::Transport for Transport { .boxed()) } - fn address_translation(&self, _server: &Multiaddr, _observed: &Multiaddr) -> Option { - None - } - fn poll( mut self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index c528e8d586f..b3effa4fef5 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -68,6 +68,7 @@ pub mod dial_opts; pub mod dummy; pub mod handler; mod listen_opts; +pub mod translation; /// Bundles all symbols required for the [`libp2p_swarm_derive::NetworkBehaviour`] macro. #[doc(hidden)] @@ -153,6 +154,7 @@ use std::{ task::{Context, Poll}, }; use tracing::Instrument; +pub use translation::address_translation; /// Event generated by the [`NetworkBehaviour`] that the swarm will report back. type TBehaviourOutEvent = ::ToSwarm; diff --git a/core/src/translation.rs b/swarm/src/translation.rs similarity index 98% rename from core/src/translation.rs rename to swarm/src/translation.rs index efddae31052..fd448bfaf23 100644 --- a/core/src/translation.rs +++ b/swarm/src/translation.rs @@ -18,7 +18,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use multiaddr::{Multiaddr, Protocol}; +use libp2p_core::{multiaddr::Protocol, Multiaddr}; /// Perform IP address translation. /// diff --git a/transports/dns/src/lib.rs b/transports/dns/src/lib.rs index 7df74b6c91d..2f6ccb27150 100644 --- a/transports/dns/src/lib.rs +++ b/transports/dns/src/lib.rs @@ -237,10 +237,6 @@ where self.do_dial(addr, dial_opts) } - fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { - self.inner.lock().address_translation(server, observed) - } - fn poll( self: Pin<&mut Self>, cx: &mut Context<'_>, @@ -668,10 +664,6 @@ mod tests { Ok(Box::pin(future::ready(Ok(())))) } - fn address_translation(&self, _: &Multiaddr, _: &Multiaddr) -> Option { - None - } - fn poll( self: Pin<&mut Self>, _: &mut Context<'_>, diff --git a/transports/quic/src/transport.rs b/transports/quic/src/transport.rs index d9ca9740a90..ff0a4a20dc4 100644 --- a/transports/quic/src/transport.rs +++ b/transports/quic/src/transport.rs @@ -249,15 +249,6 @@ impl Transport for GenTransport

{ } } - fn address_translation(&self, listen: &Multiaddr, observed: &Multiaddr) -> Option { - if !is_quic_addr(listen, self.support_draft_29) - || !is_quic_addr(observed, self.support_draft_29) - { - return None; - } - Some(observed.clone()) - } - fn dial( &mut self, addr: Multiaddr, @@ -723,33 +714,6 @@ fn multiaddr_to_socketaddr( } } -/// Whether an [`Multiaddr`] is a valid for the QUIC transport. -fn is_quic_addr(addr: &Multiaddr, support_draft_29: bool) -> bool { - use Protocol::*; - let mut iter = addr.iter(); - let Some(first) = iter.next() else { - return false; - }; - let Some(second) = iter.next() else { - return false; - }; - let Some(third) = iter.next() else { - return false; - }; - let fourth = iter.next(); - let fifth = iter.next(); - - matches!(first, Ip4(_) | Ip6(_) | Dns(_) | Dns4(_) | Dns6(_)) - && matches!(second, Udp(_)) - && if support_draft_29 { - matches!(third, QuicV1 | Quic) - } else { - matches!(third, QuicV1) - } - && matches!(fourth, Some(P2p(_)) | None) - && fifth.is_none() -} - /// Turns an IP address and port into the corresponding QUIC multiaddr. fn socketaddr_to_multiaddr(socket_addr: &SocketAddr, version: ProtocolVersion) -> Multiaddr { let quic_proto = match version { diff --git a/transports/quic/tests/smoke.rs b/transports/quic/tests/smoke.rs index a95f23748b1..6a1e0e0df9e 100644 --- a/transports/quic/tests/smoke.rs +++ b/transports/quic/tests/smoke.rs @@ -117,14 +117,6 @@ async fn wrapped_with_delay() { self.0.lock().unwrap().remove_listener(id) } - fn address_translation( - &self, - listen: &Multiaddr, - observed: &Multiaddr, - ) -> Option { - self.0.lock().unwrap().address_translation(listen, observed) - } - /// Delayed dial, i.e. calling [`Transport::dial`] on the inner [`Transport`] not within the /// synchronous [`Transport::dial`] method, but within the [`Future`] returned by the outer /// [`Transport::dial`]. diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index 088de025bda..183d90b77a3 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -40,7 +40,6 @@ use futures::{future::Ready, prelude::*, stream::SelectAll}; use futures_timer::Delay; use if_watch::IfEvent; use libp2p_core::{ - address_translation, multiaddr::{Multiaddr, Protocol}, transport::{DialOpts, ListenerId, PortUse, TransportError, TransportEvent}, }; @@ -399,31 +398,6 @@ where .boxed()) } - /// When port reuse is disabled and hence ephemeral local ports are - /// used for outgoing connections, the returned address is the - /// `observed` address with the port replaced by the port of the - /// `listen` address. - /// - /// If port reuse is enabled, `Some(observed)` is returned, as there - /// is a chance that the `observed` address _and_ port are reachable - /// for other peers if there is a NAT in the way that does endpoint- - /// independent filtering. Furthermore, even if that is not the case - /// and TCP hole punching techniques must be used for NAT traversal, - /// the `observed` address is still the one that a remote should connect - /// to for the purpose of the hole punching procedure, as it represents - /// the mapped IP and port of the NAT device in front of the local - /// node. - /// - /// `None` is returned if one of the given addresses is not a TCP/IP - /// address. - fn address_translation(&self, listen: &Multiaddr, observed: &Multiaddr) -> Option { - if !is_tcp_addr(listen) || !is_tcp_addr(observed) { - return None; - } - - address_translation(listen, observed) - } - /// Poll all listeners. #[tracing::instrument(level = "trace", name = "Transport::poll", skip(self, cx))] fn poll( @@ -713,23 +687,6 @@ fn ip_to_multiaddr(ip: IpAddr, port: u16) -> Multiaddr { Multiaddr::empty().with(ip.into()).with(Protocol::Tcp(port)) } -fn is_tcp_addr(addr: &Multiaddr) -> bool { - use Protocol::*; - - let mut iter = addr.iter(); - - let first = match iter.next() { - None => return false, - Some(p) => p, - }; - let second = match iter.next() { - None => return false, - Some(p) => p, - }; - - matches!(first, Ip4(_) | Ip6(_) | Dns(_) | Dns4(_) | Dns6(_)) && matches!(second, Tcp(_)) -} - #[cfg(test)] mod tests { use super::*; @@ -1198,43 +1155,6 @@ mod tests { test_address_translation::() } - fn test_address_translation() - where - T: Default + libp2p_core::Transport, - { - let transport = T::default(); - - let port = 42; - let tcp_listen_addr = Multiaddr::empty() - .with(Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1))) - .with(Protocol::Tcp(port)); - let observed_ip = Ipv4Addr::new(123, 45, 67, 8); - let tcp_observed_addr = Multiaddr::empty() - .with(Protocol::Ip4(observed_ip)) - .with(Protocol::Tcp(1)) - .with(Protocol::P2p(PeerId::random())); - - let translated = transport - .address_translation(&tcp_listen_addr, &tcp_observed_addr) - .unwrap(); - let mut iter = translated.iter(); - assert_eq!(iter.next(), Some(Protocol::Ip4(observed_ip))); - assert_eq!(iter.next(), Some(Protocol::Tcp(port))); - assert_eq!(iter.next(), None); - - let quic_addr = Multiaddr::empty() - .with(Protocol::Ip4(Ipv4Addr::new(87, 65, 43, 21))) - .with(Protocol::Udp(1)) - .with(Protocol::QuicV1); - - assert!(transport - .address_translation(&tcp_listen_addr, &quic_addr) - .is_none()); - assert!(transport - .address_translation(&quic_addr, &tcp_observed_addr) - .is_none()); - } - #[test] fn test_remove_listener() { let _ = tracing_subscriber::fmt() diff --git a/transports/uds/src/lib.rs b/transports/uds/src/lib.rs index 4ef4c20552e..5c57e255b4d 100644 --- a/transports/uds/src/lib.rs +++ b/transports/uds/src/lib.rs @@ -169,14 +169,6 @@ macro_rules! codegen { } } - fn address_translation( - &self, - _server: &Multiaddr, - _observed: &Multiaddr, - ) -> Option { - None - } - fn poll( mut self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/transports/webrtc-websys/src/transport.rs b/transports/webrtc-websys/src/transport.rs index 16faa95fb14..836acb0b9f6 100644 --- a/transports/webrtc-websys/src/transport.rs +++ b/transports/webrtc-websys/src/transport.rs @@ -104,10 +104,6 @@ impl libp2p_core::Transport for Transport { ) -> Poll> { Poll::Pending } - - fn address_translation(&self, _listen: &Multiaddr, _observed: &Multiaddr) -> Option { - None - } } /// Checks if local Firefox. diff --git a/transports/webrtc/src/tokio/transport.rs b/transports/webrtc/src/tokio/transport.rs index 0cf18bab59c..62049c8f59b 100644 --- a/transports/webrtc/src/tokio/transport.rs +++ b/transports/webrtc/src/tokio/transport.rs @@ -162,10 +162,6 @@ impl libp2p_core::Transport for Transport { } .boxed()) } - - fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { - libp2p_core::address_translation(server, observed) - } } /// A stream of incoming connections on one or more interfaces. diff --git a/transports/websocket-websys/src/lib.rs b/transports/websocket-websys/src/lib.rs index 87fa3cf6f5e..5f57b68650b 100644 --- a/transports/websocket-websys/src/lib.rs +++ b/transports/websocket-websys/src/lib.rs @@ -116,10 +116,6 @@ impl libp2p_core::Transport for Transport { ) -> std::task::Poll> { Poll::Pending } - - fn address_translation(&self, _listen: &Multiaddr, _observed: &Multiaddr) -> Option { - None - } } // Try to convert Multiaddr to a Websocket url. diff --git a/transports/websocket/src/framed.rs b/transports/websocket/src/framed.rs index d4d83c26584..2085cec9af8 100644 --- a/transports/websocket/src/framed.rs +++ b/transports/websocket/src/framed.rs @@ -156,10 +156,6 @@ where self.do_dial(addr, dial_opts) } - fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { - self.transport.lock().address_translation(server, observed) - } - fn poll( mut self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/transports/websocket/src/lib.rs b/transports/websocket/src/lib.rs index 639cab71d31..40d6db44471 100644 --- a/transports/websocket/src/lib.rs +++ b/transports/websocket/src/lib.rs @@ -210,10 +210,6 @@ where self.transport.dial(addr, opts) } - fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { - self.transport.address_translation(server, observed) - } - fn poll( mut self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/transports/webtransport-websys/src/transport.rs b/transports/webtransport-websys/src/transport.rs index 9f828922182..1b470fc40b6 100644 --- a/transports/webtransport-websys/src/transport.rs +++ b/transports/webtransport-websys/src/transport.rs @@ -99,8 +99,4 @@ impl libp2p_core::Transport for Transport { ) -> Poll> { Poll::Pending } - - fn address_translation(&self, _listen: &Multiaddr, _observed: &Multiaddr) -> Option { - None - } }