Hangup tears down ALL live sessions, not just the primary

Fixkamo-internal
Shipped
April 26, 2026 at 10:47 PM UTC
Author
kamo
Commit
33ab822

Self-call edge case left a session leaked: dialing your own extension creates an outbound session, then Asterisk loops the call back as a second inbound session, so two sessions exist at once. The single activeSessionRef only tracked the most recent (inbound), so: 1. Reject (hangup the loopback overlay) → inbound rejected, ref nulled. 2. Outbound continues unattended; Asterisk routes it to voicemail. 3. UI flips to End Call because the outbound goes Established. 4. Click End Call → hangup() reads ref, finds null, no-op. 5. Voicemail audio keeps playing; only a page refresh clears it. Maintain an allSessionsRef Set alongside the primary ref: - wireSession adds every session. - terminated/failed events remove from the set, only reset call state if THAT session was primary, and promote a survivor to primary so mute/hold/transfer keep targeting a live call. - reject() removes the rejected session from the set and promotes a survivor (so the UI doesn't briefly point at nothing). - hangup() iterates the set and calls hangup() on every member, then clears the set and the primary ref. - Per-session listeners (accepted / hold / unhold / mute / unmute) now short-circuit when the firing session isn't the current primary, so stale events from a backgrounded session can't flip UI state for a different active call.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing