fix: address critical audit findings

#3 JSON escaping: CallIceCandidateEvent.serializeCandidate() now
escapes backslashes and quotes in SDP/sdpMid strings before
interpolation. Prevents malformed JSON when SDP contains special
characters.

#4 Thread safety: remoteDescriptionSet changed from Boolean to
AtomicBoolean to prevent race conditions between WebRTC callback
threads and main thread accessing the flag simultaneously.

#5 Async cleanup: hangup() no longer calls cleanup() synchronously
after launching the coroutine. Cleanup is now triggered by the
CallManager state collector when Ended state is reached, avoiding
resource disposal during active WebRTC callbacks.

#7 EglBase leak: createWebRtcSession() now wraps initialize() and
createPeerConnection() in try-catch that disposes the session on
failure, preventing EGL context leaks from failed initialization.

#10 SDP failure: createOffer/createAnswer onCreateFailure() now
calls onError() to surface SDP creation failures to the user
instead of silently logging them.

#11 Notification age: EventNotificationConsumer now uses
CallOfferEvent.EXPIRATION_SECONDS (20s) instead of hardcoded 30s
to align with the actual event expiration.

https://claude.ai/code/session_017hZm7yu7CzmcQgZGSaqSXS
This commit is contained in:
Claude
2026-04-02 03:25:11 +00:00
parent 0e31afbb25
commit 3f82bb5ff6
4 changed files with 30 additions and 14 deletions
@@ -69,7 +69,11 @@ class CallIceCandidateEvent(
sdp: String,
sdpMid: String,
sdpMLineIndex: Int,
): String = """{"candidate":"$sdp","sdpMid":"$sdpMid","sdpMLineIndex":$sdpMLineIndex}"""
): String {
val escapedSdp = sdp.replace("\\", "\\\\").replace("\"", "\\\"")
val escapedMid = sdpMid.replace("\\", "\\\\").replace("\"", "\\\"")
return """{"candidate":"$escapedSdp","sdpMid":"$escapedMid","sdpMLineIndex":$sdpMLineIndex}"""
}
fun build(
candidateJson: String,