fix(desktop): direct calls used wrong identity file — mac identity mismatch
Some checks failed
Mirror to GitHub / mirror (push) Failing after 37s
Build Release Binaries / build-amd64 (push) Failing after 3m40s

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
This commit is contained in:
Siavash Sameni
2026-04-10 12:15:23 +04:00
parent da09fdb6e9
commit 2fd94651e4

View File

@@ -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}"));