Inbound calls were reaching the media server, DTLS was completing after
the DTLSRoleServer fix, and yet no media flowed — Meta still timed out
at 20s. Tracing the session 182412 showed why: the browser uploaded a
local .webm recording at t+22s. That only happens on the legacy
browser-direct-to-Meta path, which means the browser negotiated WebRTC
straight with Meta instead of waiting for the media server's agent
offer.
Root cause: GET /whatsapp_calls/:id returns Meta's sdp_offer whenever
the call is ringing, regardless of media-server mode. The FE calls
that endpoint from acceptWhatsappCallById when the call isn't in the
incoming-calls store yet (page reload, bubble click). It then sees a
truthy sdpOffer, isServerRelayCall() returns false, and the browser
dials Meta itself. Meta's DTLS was with *our* media server, so the
browser's peer connection never got media and Meta saw silence.
Fix:
- show omits sdp_offer / ice_servers when media_server_enabled and
returns media_server_enabled as an explicit flag so the FE picks the
right path.
- broadcast_incoming_call carries the same flag through ActionCable.
- FE isServerRelayCall prefers the explicit flag; only falls back to
sdpOffer presence when the flag isn't provided.
- acceptWhatsappCallById and the ActionCable handler propagate the
flag into the call object.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>