From 626fbfdba8aa216e1785befefe513840c53b7e1d Mon Sep 17 00:00:00 2001 From: Jannis Braun <151788261+TheZwiss@users.noreply.github.com> Date: Tue, 31 Mar 2026 23:58:27 +0200 Subject: [PATCH] fix(federation): address code review findings for FED-009 - Resolve homeUserId from DB in sendFederatedCallStart/End (not raw userId) - Clear existing timeout in createFederatedCall before overwriting - Clear federatedCallToken/Url in leaveVoice and handleForceDisconnect - Remove unnecessary `as any` cast in relay processor --- packages/server/src/routes/federation.ts | 2 +- packages/server/src/ws/events.ts | 11 +++++++++-- packages/server/src/ws/handler.ts | 2 ++ packages/web/src/stores/voiceStore.ts | 4 ++++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/server/src/routes/federation.ts b/packages/server/src/routes/federation.ts index 3c2962c4..5d471e2a 100644 --- a/packages/server/src/routes/federation.ts +++ b/packages/server/src/routes/federation.ts @@ -3092,7 +3092,7 @@ function processDmCallStartEvent( callerName: callerStub.displayName ?? callerStub.username, livekitUrl: event.call!.livekitUrl, livekitToken: token, - } as any); + }); } accepted.push(event.messageId); diff --git a/packages/server/src/ws/events.ts b/packages/server/src/ws/events.ts index 6b9cc085..15dd82ba 100644 --- a/packages/server/src/ws/events.ts +++ b/packages/server/src/ws/events.ts @@ -1765,7 +1765,7 @@ async function sendFederatedCallStart( livekitUrl, tokens, caller: { - homeUserId: callerId, + homeUserId: members.find(m => m.userId === callerId)?.homeUserId || callerId, homeInstance: ourOrigin, displayName: callerName, }, @@ -1852,6 +1852,13 @@ async function sendFederatedCallEnd(dmChannelId: string, endedByUserId: string): } if (targets.size === 0) return; + // Resolve actual homeUserId from DB + const endUser = db.select({ homeUserId: schema.users.homeUserId }) + .from(schema.users) + .where(eq(schema.users.id, endedByUserId)) + .get(); + const resolvedHomeUserId = endUser?.homeUserId || endedByUserId; + const event = { eventType: 'dm_call_end' as const, messageId: generateSnowflake(), @@ -1859,7 +1866,7 @@ async function sendFederatedCallEnd(dmChannelId: string, endedByUserId: string): timestamp: Date.now(), federatedId: channel.federatedId, call: { - endedBy: { homeUserId: endedByUserId, homeInstance: ourOrigin }, + endedBy: { homeUserId: resolvedHomeUserId, homeInstance: ourOrigin }, }, }; diff --git a/packages/server/src/ws/handler.ts b/packages/server/src/ws/handler.ts index e6b24e10..e38ff5aa 100644 --- a/packages/server/src/ws/handler.ts +++ b/packages/server/src/ws/handler.ts @@ -445,6 +445,8 @@ class ConnectionManager { /** Register a federated call received via S2S. Adds 60s ringing timeout. */ createFederatedCall(entry: FederatedCallEntry): void { + // Clear any existing entry + timeout to avoid leaked timers + this.clearFederatedCall(entry.dmChannelId); this.federatedCalls.set(entry.dmChannelId, entry); // 60s ringing timeout — mirrors host behavior diff --git a/packages/web/src/stores/voiceStore.ts b/packages/web/src/stores/voiceStore.ts index 3bc9f5b1..a648a366 100644 --- a/packages/web/src/stores/voiceStore.ts +++ b/packages/web/src/stores/voiceStore.ts @@ -482,6 +482,8 @@ export const useVoiceStore = create()( focusedParticipantId: null, activeDmCall: null, outgoingCall: null, + federatedCallToken: null, + federatedCallUrl: null, deafenedUserIds: new Set(), participantMutes: new Map(), streamVolumes: new Map(), @@ -517,6 +519,8 @@ export const useVoiceStore = create()( focusedParticipantId: null, activeDmCall: null, outgoingCall: null, + federatedCallToken: null, + federatedCallUrl: null, deafenedUserIds: new Set(), participantMutes: new Map(), streamVolumes: new Map(),