diff --git a/src/matrixrtc/EncryptionManager.ts b/src/matrixrtc/EncryptionManager.ts index 30c4439fc..b97cd9dd3 100644 --- a/src/matrixrtc/EncryptionManager.ts +++ b/src/matrixrtc/EncryptionManager.ts @@ -1,10 +1,11 @@ import { logger as rootLogger } from "../logger.ts"; -import { Statistics, type EncryptionConfig } from "./MatrixRTCSession.ts"; +import { type EncryptionConfig } from "./MatrixRTCSession.ts"; import { secureRandomBase64Url } from "../randomstring.ts"; import { decodeBase64, encodeUnpaddedBase64 } from "../base64.ts"; import { safeGetRetryAfterMs } from "../http-api/errors.ts"; import { type CallMembership } from "./CallMembership.ts"; -import { KeyTransportEventListener, KeyTransportEvents, type IKeyTransport } from "./IKeyTransport.ts"; +import { type KeyTransportEventListener, KeyTransportEvents, type IKeyTransport } from "./IKeyTransport.ts"; +import { isMyMembership, type Statistics } from "./types.ts"; const logger = rootLogger.getChild("MatrixRTCSession"); @@ -12,13 +13,37 @@ const logger = rootLogger.getChild("MatrixRTCSession"); * This interface is for testing and for making it possible to interchange the encryption manager. * @internal */ +/** + * Interface representing an encryption manager for handling encryption-related + * operations in a real-time communication context. + */ export interface IEncryptionManager { + /** + * Joins the encryption manager with the provided configuration. + * + * @param joinConfig - The configuration for joining encryption, or undefined + * if no specific configuration is provided. + */ join(joinConfig: EncryptionConfig | undefined): void; + /** + * Leaves the encryption manager, cleaning up any associated resources. + */ leave(): void; + /** + * Called from the MatrixRTCSession when the memberships in this session updated. + * + * @param oldMemberships - The previous state of call memberships before the update. + */ onMembershipsUpdate(oldMemberships: CallMembership[]): void; + /** + * Retrieves the encryption keys currently managed by the encryption manager. + * + * @returns A map where the keys are identifiers and the values are arrays of + * objects containing encryption keys and their associated timestamps. + */ getEncryptionKeys(): Map>; } @@ -112,17 +137,16 @@ export class EncryptionManager implements IEncryptionManager { this.joined = false; } - // TODO deduplicate this method. It also is in MatrixRTCSession. - private isMyMembership = (m: CallMembership): boolean => m.sender === this.userId && m.deviceId === this.deviceId; - public onMembershipsUpdate(oldMemberships: CallMembership[]): void { if (this.manageMediaKeys && this.joined) { const oldMembershipIds = new Set( - oldMemberships.filter((m) => !this.isMyMembership(m)).map(getParticipantIdFromMembership), + oldMemberships + .filter((m) => !isMyMembership(m, this.userId, this.deviceId)) + .map(getParticipantIdFromMembership), ); const newMembershipIds = new Set( this.getMemberships() - .filter((m) => !this.isMyMembership(m)) + .filter((m) => !isMyMembership(m, this.userId, this.deviceId)) .map(getParticipantIdFromMembership), ); @@ -272,7 +296,7 @@ export class EncryptionManager implements IEncryptionManager { private storeLastMembershipFingerprints(): void { this.lastMembershipFingerprints = new Set( this.getMemberships() - .filter((m) => !this.isMyMembership(m)) + .filter((m) => !isMyMembership(m, this.userId, this.deviceId)) .map((m) => `${getParticipantIdFromMembership(m)}:${m.createdTs()}`), ); } diff --git a/src/matrixrtc/NewMembershipManager.ts b/src/matrixrtc/NewMembershipManager.ts index d4307a7a9..10b47fe51 100644 --- a/src/matrixrtc/NewMembershipManager.ts +++ b/src/matrixrtc/NewMembershipManager.ts @@ -24,16 +24,16 @@ import { type Room } from "../models/room.ts"; import { defer, type IDeferred } from "../utils.ts"; import { type CallMembership, DEFAULT_EXPIRE_DURATION, type SessionMembershipData } from "./CallMembership.ts"; import { type Focus } from "./focus.ts"; -import { - type IMembershipManager, - type MembershipManagerEventHandlerMap, - MembershipManagerEvent, - Status, -} from "./types.ts"; +import { isMyMembership, Status } from "./types.ts"; import { isLivekitFocusActive } from "./LivekitFocus.ts"; import { type MembershipConfig } from "./MatrixRTCSession.ts"; import { ActionScheduler, type ActionUpdate } from "./NewMembershipManagerActionScheduler.ts"; import { TypedEventEmitter } from "../models/typed-event-emitter.ts"; +import { + MembershipManagerEvent, + type IMembershipManager, + type MembershipManagerEventHandlerMap, +} from "./IMembershipManager.ts"; const logger = rootLogger.getChild("MatrixRTCSession"); @@ -219,10 +219,9 @@ export class MembershipManager private leavePromiseDefer?: IDeferred; public async onRTCSessionMemberUpdate(memberships: CallMembership[]): Promise { - const isMyMembership = (m: CallMembership): boolean => - m.sender === this.client.getUserId() && m.deviceId === this.client.getDeviceId(); - - if (this.isJoined() && !memberships.some(isMyMembership)) { + const userId = this.client.getUserId(); + const deviceId = this.client.getDeviceId(); + if (userId && deviceId && this.isJoined() && !memberships.some((m) => isMyMembership(m, userId, deviceId))) { // If one of these actions are scheduled or are getting inserted in the next iteration, we should already // take care of our missing membership. const sendingMembershipActions = [