Skip to content

Conversation

ErakhtinB
Copy link

When PortUse::Reuse fails and falls back to ephemeral ports, detect this by comparing observed ports with listening ports rather than tracking the original PortUse intent.

Fixes #5820

Description

Notes & open questions

Change checklist

  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • A changelog entry has been made in the appropriate crates

When PortUse::Reuse fails and falls back to ephemeral ports,
detect this by comparing observed ports with listening ports
rather than tracking the original PortUse intent.

Fixes libp2p#5820
Copy link
Member

@elenaf9 elenaf9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR and sorry for the (very) long delay!

Two nits, rest LGTM!

Comment on lines +370 to +374
if observed_port_matches_listening_port(observed, &self.listen_addresses) {
// If the observed port matches any of our listening ports,
// then port reuse actually worked. Use the original observed address.
self.events
.push_back(ToSwarm::NewExternalAddrCandidate(observed.clone()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that this is existing logic, but IMO we should only emit an event here if self.external_addresses doesn't contain the address yet. Otherwise, we keep emitting events for the same addresses again and again.

Comment on lines +95 to +101
for protocol in addr.iter() {
match protocol {
Tcp(port) | Udp(port) => return Some(port),
_ => continue,
}
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should return the protocol here so that below the type of protocol is also checked in the comparison. Theoretically, a port could be reachable for one protocol but not for the other.

Comment on lines +871 to +889
#[test]
fn test_address_translation_when_port_differs() {
use libp2p_identity::Keypair;
use libp2p_swarm::behaviour::FromSwarm;

// Create a behavior with some listening addresses
let keypair = Keypair::generate_ed25519();
let config = Config::new("test/1.0.0".to_string(), keypair.public());
let mut behaviour = Behaviour::new(config);

// Add a listening address
let listen_addr: Multiaddr = "/ip4/0.0.0.0/tcp/8080".parse().unwrap();
behaviour
.listen_addresses
.on_swarm_event(&FromSwarm::NewListenAddr(
libp2p_swarm::behaviour::NewListenAddr {
listener_id: libp2p_core::transport::ListenerId::next(),
addr: &listen_addr,
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests are very much appreciated, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Address translation doesn't work correctly with non-reused ephemeral ports

2 participants