fix(whatsapp-call): stop browser from bypassing media server on inbound
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>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
0bf6a2cee8
commit
c6c3ba054e
@@ -143,9 +143,15 @@ function waitForIceGatheringComplete(pc) {
|
||||
});
|
||||
}
|
||||
|
||||
// ── Server-relay mode: detect by absence of sdpOffer in incoming call data ──
|
||||
// ── Server-relay mode detection ──
|
||||
// Prefer the explicit flag set by Rails whenever it's available (call object
|
||||
// from GET /whatsapp_calls/:id, inbox serializer, or the incoming ActionCable
|
||||
// broadcast). Fall back to the presence of sdpOffer so legacy deployments keep
|
||||
// working when the field isn't set.
|
||||
function isServerRelayCall(call) {
|
||||
return !call.sdpOffer;
|
||||
if (call?.mediaServerEnabled === true) return true;
|
||||
if (call?.mediaServerEnabled === false) return false;
|
||||
return !call?.sdpOffer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -290,6 +296,7 @@ export async function acceptWhatsappCallById(callId) {
|
||||
conversationId: data.conversation_id,
|
||||
sdpOffer: data.sdp_offer,
|
||||
iceServers: data.ice_servers,
|
||||
mediaServerEnabled: data.media_server_enabled,
|
||||
caller: data.caller,
|
||||
};
|
||||
callsStore.addIncomingCall(call);
|
||||
|
||||
@@ -226,6 +226,7 @@ class ActionCableConnector extends BaseActionCableConnector {
|
||||
caller: data.caller,
|
||||
sdpOffer: data.sdp_offer || null,
|
||||
iceServers: data.ice_servers || null,
|
||||
mediaServerEnabled: data.media_server_enabled,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -14,8 +14,14 @@ class Api::V1::Accounts::WhatsappCallsController < Api::V1::Accounts::BaseContro
|
||||
conversation_id: @call.conversation_id,
|
||||
inbox_id: @call.inbox_id,
|
||||
message_id: @call.message_id,
|
||||
sdp_offer: @call.ringing? ? @call.sdp_offer : nil,
|
||||
ice_servers: @call.ice_servers,
|
||||
# In server-relay mode the browser must not talk WebRTC to Meta directly
|
||||
# — the media server owns that peer connection. Omitting sdp_offer forces
|
||||
# the FE's isServerRelayCall() check to return true so the accept flow
|
||||
# waits for the whatsapp_call.agent_offer broadcast from Rails instead of
|
||||
# negotiating straight with Meta.
|
||||
sdp_offer: @call.ringing? && !Call.media_server_enabled? ? @call.sdp_offer : nil,
|
||||
ice_servers: Call.media_server_enabled? ? [] : @call.ice_servers,
|
||||
media_server_enabled: Call.media_server_enabled?,
|
||||
caller: caller_info
|
||||
}
|
||||
end
|
||||
|
||||
@@ -157,6 +157,7 @@ class Whatsapp::IncomingCallService
|
||||
direction: call.direction_label,
|
||||
inbox_id: call.inbox_id,
|
||||
conversation_id: call.conversation_id,
|
||||
media_server_enabled: Call.media_server_enabled?,
|
||||
caller: {
|
||||
name: contact.name,
|
||||
phone: contact.phone_number,
|
||||
|
||||
Reference in New Issue
Block a user