Skip to content

fix(quic): dial from ephemeral port instead of reusing listener port#487

Merged
lucassaldanha merged 1 commit into
libp2p:developfrom
lucassaldanha:fix-quic-dialing
Jun 10, 2026
Merged

fix(quic): dial from ephemeral port instead of reusing listener port#487
lucassaldanha merged 1 commit into
libp2p:developfrom
lucassaldanha:fix-quic-dialing

Conversation

@lucassaldanha

Copy link
Copy Markdown
Collaborator

When the dialing transport had an active QUIC listener, dial() tried to bind a separate NioDatagramChannel to the listener's own port using only SO_REUSEADDR. On Linux two UDP sockets cannot share a port without SO_REUSEPORT (an Epoll-only option), so the bind threw BindException. The fallback then re-used the same non-@sharable QUIC codec handler instance on a second channel, which also throws, so the outbound connection never completed and timed out — 0 successful outbound dials on listening nodes.

Always bind the dial socket to an ephemeral port (the path already exercised by every passing QUIC test). NAT-consistent dialing for hole punching is unaffected: dialAsListener reuses the listener socket directly.

Add QuicServerTestJava.dialWhileListeningCompletes regression test that dials while a listener is active — the previously-untested broken branch.

When the dialing transport had an active QUIC listener (as every real
node does), dial() tried to bind a separate NioDatagramChannel to the
listener's own port using only SO_REUSEADDR. On Linux two UDP sockets
cannot share a port without SO_REUSEPORT (an Epoll-only option), so the
bind threw BindException. The fallback then re-used the same non-@sharable
QUIC codec handler instance on a second channel, which also throws, so the
outbound connection never completed and timed out — 0 successful outbound
dials on listening nodes.

Always bind the dial socket to an ephemeral port (the path already
exercised by every passing QUIC test). NAT-consistent dialing for hole
punching is unaffected: dialAsListener reuses the listener socket directly.

Add QuicServerTestJava.dialWhileListeningCompletes regression test that
dials while a listener is active — the previously-untested broken branch.

@StefanBratanov StefanBratanov left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@lucassaldanha lucassaldanha merged commit edeeae5 into libp2p:develop Jun 10, 2026
2 checks passed
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.

2 participants