From 2fd94651e42018cf7c96bf8443e1b8e9223889f9 Mon Sep 17 00:00:00 2001 From: Siavash Sameni Date: Fri, 10 Apr 2026 12:15:23 +0400 Subject: [PATCH] =?UTF-8?q?fix(desktop):=20direct=20calls=20used=20wrong?= =?UTF-8?q?=20identity=20file=20=E2=80=94=20mac=20identity=20mismatch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The non-Android branch of CallEngine::start loaded the seed from \$HOME/.wzp/identity directly, while register_signal in lib.rs goes through the shared load_or_create_seed() helper which resolves via APP_DATA_DIR → Tauri's app_data_dir(). On macOS those are two completely different files: register_signal → ~/Library/Application Support/com.wzp.desktop/.wzp/identity CallEngine::start (old) → ~/.wzp/identity On a fresh install they end up holding two different random seeds. Register and CallEngine then derive two different fingerprints from those seeds, and when a direct call comes in the relay routes it to "you" under the register_signal fingerprint, but once CallEngine tries to join the call-* room it advertises a DIFFERENT fingerprint — which fails the call_registry ACL check on the relay side (only the two authorised participants of a call can join its room). Silent hang, the call never completes. Android hit this bug earlier in the week and was fixed by switching its CallEngine::start branch to `crate::load_or_create_seed()`. Backport the same single-line change to the desktop branch so both platforms share one identity source of truth. Also bring the desktop branch up to parity with the android branch on diagnostic logging: - log CallEngine::start entry with relay/room/alias/quality/has_reuse - log endpoint.local_addr on reuse / create - log "QUIC connection established, performing handshake" between connect() and perform_handshake() so a hang at either step is immediately localisable - map_err all three potential failure points (create_endpoint, connect, perform_handshake) to an explicit error! trace --- desktop/src-tauri/src/engine.rs | 60 +++++++++++++++------------------ 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/desktop/src-tauri/src/engine.rs b/desktop/src-tauri/src/engine.rs index b6dc272..29998d4 100644 --- a/desktop/src-tauri/src/engine.rs +++ b/desktop/src-tauri/src/engine.rs @@ -553,52 +553,45 @@ impl CallEngine { where F: Fn(&str, &str) + Send + Sync + 'static, { + info!(%relay, %room, %alias, %quality, has_reuse = reuse_endpoint.is_some(), "CallEngine::start (desktop) invoked"); let _ = rustls::crypto::ring::default_provider().install_default(); let relay_addr: SocketAddr = relay.parse()?; - // Load or generate identity - let seed = { - let path = { - let home = std::env::var("HOME").unwrap_or_else(|_| ".".into()); - std::path::PathBuf::from(home).join(".wzp").join("identity") - }; - if path.exists() { - if let Ok(hex) = std::fs::read_to_string(&path) { - if let Ok(s) = wzp_crypto::Seed::from_hex(hex.trim()) { - s - } else { - wzp_crypto::Seed::generate() - } - } else { - wzp_crypto::Seed::generate() - } - } else { - let s = wzp_crypto::Seed::generate(); - if let Some(p) = path.parent() { - std::fs::create_dir_all(p).ok(); - } - let hex: String = s.0.iter().map(|b| format!("{b:02x}")).collect(); - std::fs::write(&path, hex).ok(); - s - } - }; - + // Identity via the SHARED helper — same path resolution as + // register_signal (Tauri app_data_dir, e.g. on macOS + // ~/Library/Application Support/com.wzp.desktop/.wzp/identity). + // + // The previous implementation loaded the seed manually from + // $HOME/.wzp/identity which is a DIFFERENT file on macOS, so + // register_signal and CallEngine::start were using different + // identities — direct calls placed from desktop were routed + // by the relay under the CallEngine fingerprint but the callee + // had registered under a different fingerprint, making the + // call unroutable. + let seed = crate::load_or_create_seed() + .map_err(|e| anyhow::anyhow!("identity: {e}"))?; let fp = seed.derive_identity().public_identity().fingerprint; let fingerprint = fp.to_string(); info!(%fp, "identity loaded"); - // Connect — reuse the signal endpoint if the direct-call path gave us - // one, otherwise create a fresh one (SFU room join path). + // Connect — reuse the signal endpoint if the direct-call path gave + // us one, otherwise create a fresh one (SFU room join path). let endpoint = if let Some(ep) = reuse_endpoint { - info!("reusing signal endpoint for media connection"); + info!(local_addr = ?ep.local_addr().ok(), "reusing signal endpoint for media connection"); ep } else { let bind_addr: SocketAddr = "0.0.0.0:0".parse().unwrap(); - wzp_transport::create_endpoint(bind_addr, None)? + let ep = wzp_transport::create_endpoint(bind_addr, None) + .map_err(|e| { error!("create_endpoint failed: {e}"); e })?; + info!(local_addr = ?ep.local_addr().ok(), "created new endpoint, dialing relay"); + ep }; let client_config = wzp_transport::client_config(); - let conn = wzp_transport::connect(&endpoint, relay_addr, &room, client_config).await?; + let conn = wzp_transport::connect(&endpoint, relay_addr, &room, client_config) + .await + .map_err(|e| { error!("connect failed: {e}"); e })?; + info!("QUIC connection established, performing handshake"); let transport = Arc::new(wzp_transport::QuinnTransport::new(conn)); // Handshake @@ -607,7 +600,8 @@ impl CallEngine { &seed.0, Some(&alias), ) - .await?; + .await + .map_err(|e| { error!("perform_handshake failed: {e}"); e })?; info!("connected to relay, handshake complete"); event_cb("connected", &format!("joined room {room}"));