fix(voice): persist late outbound SDP answers when ACCEPTED races connect

If status=ACCEPTED is processed before Meta's connect webhook, the call
is already in_progress when accept_outbound_call runs, and the previous
guard dropped the SDP answer — leaving the browser without the data it
needs to complete the WebRTC handshake. Gate on a stored sdp_answer
instead of in_progress so out-of-order delivery still persists and
broadcasts the answer (and connect retries stay idempotent).
This commit is contained in:
Tanmay Deep Sharma
2026-05-07 19:57:27 +07:00
parent 9d889f691b
commit 3c33d912df
@@ -84,10 +84,15 @@ class Whatsapp::IncomingCallService
# `connect` is the WebRTC tunnel-ready signal, not the pickup signal. Apply
# Meta's SDP answer so the handshake completes during ringing; the call
# stays in `ringing` until status=ACCEPTED arrives.
# stays in `ringing` until status=ACCEPTED arrives. Don't gate on
# in_progress: an out-of-order ACCEPTED can flip status before connect is
# processed, and dropping the SDP answer would leave the browser without
# the data it needs to complete the handshake. Use the stored answer as
# the idempotency key instead.
def accept_outbound_call(call, payload)
call.with_lock do
next if call.in_progress? || call.terminal?
next if call.terminal?
next if call.meta&.dig('sdp_answer').present?
# Pin setup:active so browsers don't renegotiate when Meta echoes actpass.
sdp_answer = payload.dig(:session, :sdp)&.gsub('a=setup:actpass', 'a=setup:active')