ChainSafe / ChainSafe/js-libp2p-quic
Dial from the listener's endpoint so QUIC connections can be hole punched
- Dominant language
- TypeScript
- Stars
- 12
- Forks
- 6
- Avg merge
- 15m
- Merged PRs (30d)
- 2
Description
Hole punching over QUIC needs the dial to be sent from the same UDP port the listener is bound to. Only then does the outgoing packet open the same NAT mapping that the other peer was told to send to. The transport cannot do this today.
`Client::new` in rust/lib.rs creates its own `quinn::Endpoint` on a random free port, while `Server::new` binds the configured one. That is two endpoints on two sockets, so a dial never uses the listener's mapping, and two dials timed together never meet. `@libp2p/tcp` has the same problem, which is why hole punching in js-libp2p today needs a circuit relay for the WebRTC signalling path.
quinn already supports one endpoint doing both. Its `Endpoint` is documented for use with incoming and outgoing connections, and the endpoint that `Server::new` builds through `new_with_abstract_socket` already gets `Some(server_config)`. It only lacks a default client config, so `connect()` returns `NoDefaultClientConfig`. rust-libp2p used this approach for its QUIC hole punching (libp2p/rust-libp2p#3964).
Would you accept a PR for this, and which shape do you prefer?
1. Dials reuse the listener's endpoint automatically whenever the transport is listening on a matching address family, and fall back to the current client otherwise. This is the better option for hole punching, but it changes the source port of outgoing connections for everyone using the package.
2. An option on `quic()` that turns it on, leaving current behaviour unchanged.
I am happy to write it either way. I would rather ask first than guess at the API.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with rust/lib.rs, especially Client::new, Server::new, and the quinn::Endpoint setup, then inspect the quic() entry point and existing connection tests. First resolve whether listener endpoint reuse is automatic or opt-in; done means the selected API lets QUIC dials use the listener's bound UDP port where applicable while preserving the intended fallback behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, typescript
- Domain
- networking
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100