fix(connect): install MediaPathReport oneshot BEFORE race starts

The peer's MediaPathReport can arrive while our dual_path::race is
still running. Previously, the oneshot was created AFTER the race
completed, so the recv loop had nowhere to deliver the report —
it was silently dropped, causing a 3s timeout and false relay
fallback on ~50% of calls.

Fix: create the oneshot and install it in SignalState BEFORE
starting the race. The oneshot::Receiver buffers the value so the
connect command can read it immediately after the race finishes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-04-12 13:06:13 +04:00
parent bd6733b2e5
commit 4cfcd5117f

View File

@@ -415,6 +415,18 @@ async fn connect(
"relay_addr": relay_sockaddr.to_string(),
"own_reflex_addr": own_reflex_addr,
}));
// Phase 6 fix: install the oneshot BEFORE the race
// starts. The peer's MediaPathReport can arrive
// while our race is still running — if we set up
// the oneshot after the race, the recv loop has
// nowhere to send the report and it gets dropped,
// causing a 3s timeout and false relay fallback.
let (path_report_tx, path_report_rx) = tokio::sync::oneshot::channel::<bool>();
{
let mut sig = state.signal.lock().await;
sig.pending_path_report = Some(path_report_tx);
}
let room_sni = room.clone();
let call_sni = format!("call-{room}");
match wzp_client::dual_path::race(
@@ -456,12 +468,14 @@ async fn connect(
.unwrap_or(&room)
.to_string();
// Install the oneshot for receiving the peer's report
let (tx, rx) = tokio::sync::oneshot::channel::<bool>();
// The oneshot was installed BEFORE the race
// (see path_report_tx above) so the peer's
// report is already buffered in path_report_rx
// if it arrived during the race.
let rx = path_report_rx;
let peer_direct_ok = {
let transport_for_report = {
let mut sig = state.signal.lock().await;
sig.pending_path_report = Some(tx);
let sig = state.signal.lock().await;
sig.transport.as_ref().cloned()
};
// Send our report