fix: cross-instance event contamination in federated DM calls

Root cause: sendToFederatedCallUsers used sendToDmMembers when dmChannelId
was set, which broadcast to ALL DM members including the caller's replicated
stub. The caller's multi-instance WS received dm_call_accepted with the
REMOTE instance's dmChannelId, causing token request for a non-existent
channel (403) and preventing the caller from connecting.

Fix 1: sendToFederatedCallUsers always uses ringedUserIds (exact recipients)
instead of sendToDmMembers (all members including caller stub).

Fix 2: dm_call_accepted handler only sets activeDmCall if the client is the
caller (wasOutgoingCall) or already connected to LiveKit. Other instances of
the same user just clear ringing without entering stuck "Connecting..." state.
This commit is contained in:
Jannis Braun
2026-04-08 13:50:25 +02:00
parent 94461f8967
commit 86fe713a7c
2 changed files with 15 additions and 12 deletions
+6 -7
View File
@@ -754,16 +754,15 @@ class ConnectionManager {
}
}
/** Send event to users involved in a federated call. Works for both Path A (DM exists) and Path B (no local DM). */
/** Send event to users who were ringed for a federated call.
* ALWAYS uses ringedUserIds, never sendToDmMembers — sendToDmMembers would
* also reach the caller's replicated stub, causing cross-instance event contamination
* (the caller's multi-instance WS gets dm_call_accepted with the wrong dmChannelId). */
sendToFederatedCallUsers(federatedId: string, event: ServerEvent): void {
const call = this.federatedCalls.get(federatedId);
if (!call) return;
if (call.dmChannelId) {
this.sendToDmMembers(call.dmChannelId, event);
} else {
for (const uid of call.ringedUserIds) {
this.sendToUser(uid, event);
}
for (const uid of call.ringedUserIds) {
this.sendToUser(uid, event);
}
}