From f6ace5455624a2921f9ce8e981a98f457ad13fb9 Mon Sep 17 00:00:00 2001 From: Siavash Sameni Date: Tue, 26 May 2026 06:35:31 +0400 Subject: [PATCH] fix(call): enable direct video and shorten portmap probe --- desktop/src-tauri/src/engine.rs | 27 +++++++++------------- desktop/src-tauri/src/lib.rs | 40 ++++++++++++++++++++++++++++----- 2 files changed, 44 insertions(+), 23 deletions(-) diff --git a/desktop/src-tauri/src/engine.rs b/desktop/src-tauri/src/engine.rs index 452ca7c..1a42568 100644 --- a/desktop/src-tauri/src/engine.rs +++ b/desktop/src-tauri/src/engine.rs @@ -759,7 +759,7 @@ impl CallEngine { t_ms = call_t0.elapsed().as_millis(), "first-join diag: direct P2P — skipping relay handshake (QUIC TLS is the encryption layer)" ); - (None, transport) + (Some(wzp_proto::CodecId::H264Baseline), transport) }; crate::emit_call_debug( &app, @@ -1869,8 +1869,9 @@ impl CallEngine { )); // Video send task (Android) — mirror of the desktop branch. Only - // spawns when the relay handshake negotiated a video codec; on - // direct P2P video is currently disabled. + // spawns when a video codec is available. Relay calls negotiate this + // in the media handshake; direct P2P uses the common H264 baseline + // codec because the relay handshake is intentionally skipped. let camera_tx = if let Some(vid_codec) = _negotiated_video_codec { let (tx, mut rx) = tokio::sync::mpsc::channel::(4); let vid_transport = transport.clone(); @@ -2172,11 +2173,7 @@ impl CallEngine { "video:send_disabled", serde_json::json!({ "t_ms": call_t0.elapsed().as_millis(), - "reason": if is_direct_p2p { - "direct_p2p_skips_relay_handshake" - } else { - "no_video_codec_negotiated" - }, + "reason": "no_video_codec_negotiated", "platform": "android", }), ); @@ -2310,7 +2307,7 @@ impl CallEngine { (hs.video_codec, transport) } else { info!("direct P2P — skipping relay handshake (QUIC TLS is the encryption layer)"); - (None, transport) + (Some(wzp_proto::CodecId::H264Baseline), transport) }; crate::emit_call_debug( &_app, @@ -3050,9 +3047,9 @@ impl CallEngine { event_cb.clone(), )); - // Video send task — active only when the handshake negotiated a video codec. - // Camera frames arrive via camera_tx; the task encodes and packetizes them. - // Blocker 4 (camera capture) will push frames into this channel. + // Video send task — active when a video codec is available. Relay calls + // negotiate this in the media handshake; direct P2P uses the common H264 + // baseline codec because the relay handshake is intentionally skipped. let camera_tx = if let Some(vid_codec) = _negotiated_video_codec { let (tx, mut rx) = tokio::sync::mpsc::channel::(4); let vid_transport = transport.clone(); @@ -3354,11 +3351,7 @@ impl CallEngine { "video:send_disabled", serde_json::json!({ "t_ms": call_t0.elapsed().as_millis(), - "reason": if is_direct_p2p { - "direct_p2p_skips_relay_handshake" - } else { - "no_video_codec_negotiated" - }, + "reason": "no_video_codec_negotiated", "platform": "desktop", }), ); diff --git a/desktop/src-tauri/src/lib.rs b/desktop/src-tauri/src/lib.rs index fba32f1..90baaad 100644 --- a/desktop/src-tauri/src/lib.rs +++ b/desktop/src-tauri/src/lib.rs @@ -2462,8 +2462,13 @@ async fn place_call( .map(|la| la.port()) .unwrap_or(0); if v4_port > 0 { - match wzp_client::portmap::acquire_port_mapping(v4_port, None).await { - Ok(mapping) => { + match tokio::time::timeout( + std::time::Duration::from_millis(750), + wzp_client::portmap::acquire_port_mapping(v4_port, None), + ) + .await + { + Ok(Ok(mapping)) => { let addr = mapping.external_addr.to_string(); tracing::info!(%addr, protocol = ?mapping.protocol, "place_call: port mapping acquired"); emit_call_debug( @@ -2475,10 +2480,19 @@ async fn place_call( ); Some(addr) } - Err(e) => { + Ok(Err(e)) => { tracing::debug!(error = %e, "place_call: port mapping unavailable (normal on most networks)"); None } + Err(_) => { + tracing::debug!("place_call: port mapping quick probe timed out"); + emit_call_debug( + &app, + "place_call:portmap_timeout", + serde_json::json!({ "timeout_ms": 750 }), + ); + None + } } } else { None @@ -2705,8 +2719,13 @@ async fn answer_call( .map(|la| la.port()) .unwrap_or(0); if v4_port > 0 { - match wzp_client::portmap::acquire_port_mapping(v4_port, None).await { - Ok(mapping) => { + match tokio::time::timeout( + std::time::Duration::from_millis(750), + wzp_client::portmap::acquire_port_mapping(v4_port, None), + ) + .await + { + Ok(Ok(mapping)) => { tracing::info!( addr = %mapping.external_addr, protocol = ?mapping.protocol, @@ -2714,10 +2733,19 @@ async fn answer_call( ); Some(mapping.external_addr.to_string()) } - Err(e) => { + Ok(Err(e)) => { tracing::debug!(error = %e, "answer_call: port mapping unavailable"); None } + Err(_) => { + tracing::debug!("answer_call: port mapping quick probe timed out"); + emit_call_debug( + &app, + "answer_call:portmap_timeout", + serde_json::json!({ "timeout_ms": 750 }), + ); + None + } } } else { None