feat(nat): smart candidate filtering + acceptor NAT tickle + 4s timeout
Major P2P improvements for cross-network calls: Smart candidate filtering (smart_dial_order): - Strip LAN candidates when peer's public IP differs from ours (172.16.x.x is unreachable from a different network) - Strip all IPv6 candidates (Phase 7 disabled, wastes dial slots) - Only keep mapped + reflexive for cross-network calls - LAN candidates preserved when both peers share the same public IP Acceptor NAT tickle: - A-role sends a 1-byte UDP packet to each peer candidate BEFORE accepting. This opens the NAT pinhole for return traffic from the Dialer's IP — critical for address-restricted NATs that only allow inbound from IPs they've seen outbound traffic to. - Uses SO_REUSEADDR on the same port as the quinn endpoint. Direct timeout increased from 2s to 4s: - Cross-network QUIC handshakes through CGNAT can take 2-3s - 2s was too aggressive for 5G/LTE networks Diagnostic fix: - Record "timeout:4s" for candidates still in-flight when the timeout fires (previously these had no diagnostic entry) 5 new tests for smart_dial_order edge cases. 593 tests pass, 0 regressions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -476,12 +476,15 @@ async fn connect(
|
||||
|
||||
let room_sni = room.clone();
|
||||
let call_sni = format!("call-{room}");
|
||||
let own_reflex_parsed: Option<std::net::SocketAddr> =
|
||||
own_reflex_addr.as_deref().and_then(|s| s.parse().ok());
|
||||
match wzp_client::dual_path::race(
|
||||
r,
|
||||
candidates,
|
||||
relay_sockaddr,
|
||||
room_sni,
|
||||
call_sni,
|
||||
own_reflex_parsed,
|
||||
signal_endpoint_for_race.clone(),
|
||||
ipv6_endpoint_for_race.clone(),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user