feat(ui): birthday attack toggle in settings (default off)
Some checks failed
Mirror to GitHub / mirror (push) Failing after 22s
Build Release Binaries / build-amd64 (push) Failing after 3m36s

New setting: "Birthday attack (opens extra ports for hard NAT)"
- Default: OFF — no extra latency on call setup
- When ON: waits up to 3s for peer's birthday ports if peer has
  non-cone NAT, adds them to the dial race

Gated end-to-end: Settings → localStorage → JS invoke →
Rust connect param → birthday wait + target injection.
LAN/cone calls unaffected regardless of setting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-04-14 16:54:22 +04:00
parent 8c360186df
commit 488efcb614
3 changed files with 18 additions and 1 deletions

View File

@@ -337,8 +337,12 @@ async fn connect(
// fails if direct P2P doesn't connect. Useful for testing NAT
// traversal without the relay masking failures.
direct_only: Option<bool>,
// Enable birthday attack for hard NAT traversal. Adds ~3s to
// call setup when peer has symmetric NAT.
birthday_attack: Option<bool>,
) -> Result<String, String> {
let force_direct = direct_only.unwrap_or(false);
let enable_birthday = birthday_attack.unwrap_or(false);
emit_call_debug(&app, "connect:start", serde_json::json!({
"relay": relay,
"room": room,
@@ -346,6 +350,7 @@ async fn connect(
"peer_local_addrs": peer_local_addrs,
"peer_mapped_addr": peer_mapped_addr,
"direct_only": force_direct,
"birthday_attack": enable_birthday,
}));
let mut engine_lock = state.engine.lock().await;
if engine_lock.is_some() {
@@ -450,7 +455,7 @@ async fn connect(
// the race immediately — LAN/cone calls shouldn't wait.
let mut birthday_addrs: Vec<std::net::SocketAddr> = Vec::new();
{
let peer_needs_birthday = {
let peer_needs_birthday = enable_birthday && {
let sig = state.signal.lock().await;
sig.peer_hard_nat_probe.as_ref()
.map(|p| p.allocation != "port-preserving")