fix: buffer ICE candidates and discard stale signaling events

Two fixes for call connectivity:

1. ICE candidate buffering: Candidates arriving before the WebRTC
   session exists (callee ringing) or before remote description is
   set (caller waiting for answer) are now queued in
   pendingIceCandidates and flushed once setRemoteDescription is
   called. This was the root cause of calls getting stuck at
   "Connecting" — ICE candidates were silently dropped.

2. Stale event filter: All signaling events older than 30 seconds
   are discarded in CallManager.onSignalingEvent() to prevent
   old cached events from triggering phantom calls.

Also: removed cleanup() from WebRTC onDisconnected callback to
avoid double-cleanup race with the CallManager state observer.

https://claude.ai/code/session_017hZm7yu7CzmcQgZGSaqSXS
This commit is contained in:
Claude
2026-04-02 00:22:41 +00:00
parent f1fd5ec786
commit e072b9ac99
2 changed files with 29 additions and 2 deletions
@@ -60,8 +60,11 @@ class CallManager(
companion object {
const val CALL_TIMEOUT_MS = 60_000L // 60 seconds ringing timeout
const val ENDED_DISPLAY_MS = 2_000L // show "call ended" briefly before resetting
const val MAX_EVENT_AGE_SECONDS = 30L // discard signaling events older than this
}
private fun isEventTooOld(event: Event): Boolean = TimeUtils.now() - event.createdAt > MAX_EVENT_AGE_SECONDS
suspend fun initiateCall(
calleePubKey: HexKey,
callType: CallType,
@@ -194,6 +197,8 @@ class CallManager(
}
fun onSignalingEvent(event: Event) {
if (isEventTooOld(event)) return
when (event) {
is CallOfferEvent -> onIncomingCallEvent(event)
is CallAnswerEvent -> onCallAnswered(event)