fix: 10s timeout on handshake CallAnswer; button stays visible during connect

- handshake.rs: add 10s timeout on recv_signal() waiting for CallAnswer —
  previously hung forever if relay didn't respond, making join button
  disappear with no feedback
- main.ts: keep join button visible + show "Connecting…" state instead of
  hiding it before the await; button restores correctly on error

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-05-25 06:59:57 +04:00
parent 32c07d1b61
commit b0a3b1f18e
2 changed files with 14 additions and 8 deletions

View File

@@ -101,12 +101,15 @@ pub async fn perform_handshake(
.await
.map_err(HandshakeError::Transport)?;
// 5. Wait for CallAnswer
let answer = transport
.recv_signal()
.await
.map_err(HandshakeError::Transport)?
.ok_or(HandshakeError::ConnectionClosed)?;
// 5. Wait for CallAnswer — 10s timeout guards against relay not responding.
let answer = tokio::time::timeout(
std::time::Duration::from_secs(10),
transport.recv_signal(),
)
.await
.map_err(|_| HandshakeError::Transport(wzp_proto::TransportError::Timeout { ms: 10_000 }))?
.map_err(HandshakeError::Transport)?
.ok_or(HandshakeError::ConnectionClosed)?;
let (callee_identity_pub, callee_ephemeral_pub, callee_signature, _chosen_profile) =
match answer {

View File

@@ -331,7 +331,9 @@ joinVoiceBtn.addEventListener("click", async () => {
const s = loadSettings();
if (!relay) { showToast("No relay configured"); return; }
connectPending = true;
joinVoiceBtn.classList.add("hidden");
const origText = joinVoiceBtn.textContent;
joinVoiceBtn.textContent = "Connecting…";
(joinVoiceBtn as HTMLButtonElement).disabled = true;
try {
await invoke("connect", {
relay: relay.address,
@@ -344,9 +346,10 @@ joinVoiceBtn.addEventListener("click", async () => {
} catch (e: any) {
console.error("connect failed:", e);
showToast(`Join failed: ${e}`);
joinVoiceBtn.classList.remove("hidden");
} finally {
connectPending = false;
joinVoiceBtn.textContent = origText;
(joinVoiceBtn as HTMLButtonElement).disabled = false;
}
});