Two regressions from Phase 5.5/5.6:
1. Room connect broken: the connect Tauri command required
peerLocalAddrs as a Vec<String>, but the room-join JS path
doesn't pass it (only the direct-call setup handler does).
Error: "invalid args 'peerLocalAddrs' for command 'connect':
command connect missing required key peerLocalAddrs".
Fix: change to Option<Vec<String>>, unwrap_or_default() at
usage sites. Room connect works again with zero peer addrs.
2. Direct P2P call connects but then CallEngine fails with
"expected CallAnswer, got Discriminant(0)". Root cause: after
the dual-path race picked a direct P2P transport, CallEngine
still ran perform_handshake() on it. That handshake is a
relay-specific protocol — sends a CallOffer signal and waits
for CallAnswer back. On a direct QUIC connection to a phone,
there's nobody running accept_handshake, so the handshake
reads garbage from the peer's first media packet and errors.
Fix: track is_direct_p2p = pre_connected_transport.is_some()
and skip perform_handshake when true. The direct connection
is already TLS-encrypted by QUIC, and both peers' identities
were verified through the signal channel (DirectCallOffer/
Answer carry identity_pub + ephemeral_pub + signature). Both
android and desktop branches updated.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>