Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prefix the user+device state key if needed #4262

Merged
merged 4 commits into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions spec/unit/matrixrtc/MatrixRTCSession.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,42 @@ describe("MatrixRTCSession", () => {
jest.useRealTimers();
});

describe("non-legacy calls", () => {
const activeFocusConfig = { type: "livekit", livekit_service_url: "https://active.url" };
const activeFocus = { type: "livekit", focus_selection: "oldest_membership" };

function testJoin(useOwnedStateEvents: boolean): void {
if (useOwnedStateEvents) {
mockRoom.getVersion = jest.fn().mockReturnValue("org.matrix.msc3779.default");
}

jest.useFakeTimers();
sess!.joinRoomSession([activeFocusConfig], activeFocus, { useLegacyMemberEvents: false });
expect(client.sendStateEvent).toHaveBeenCalledWith(
mockRoom!.roomId,
EventType.GroupCallMemberPrefix,
{
application: "m.call",
scope: "m.room",
call_id: "",
device_id: "AAAAAAA",
foci_preferred: [activeFocusConfig],
focus_active: activeFocus,
} satisfies SessionMembershipData,
`${!useOwnedStateEvents ? "_" : ""}@alice:example.org_AAAAAAA`,
);
jest.useRealTimers();
}

it("sends a membership event with session payload when joining a non-legacy call", () => {
testJoin(false);
});

it("does not prefix the state key with _ for rooms that support user-owned state events", () => {
testJoin(true);
});
});

it("does nothing if join called when already joined", () => {
sess!.joinRoomSession([mockFocus], mockFocus);

Expand Down
1 change: 1 addition & 0 deletions spec/unit/matrixrtc/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export function makeMockRoom(membershipData: MembershipData, localAge: number |
getLiveTimeline: jest.fn().mockReturnValue({
getState: jest.fn().mockReturnValue(roomState),
}),
getVersion: jest.fn().mockReturnValue("default"),
} as unknown as Room;
}

Expand Down
11 changes: 10 additions & 1 deletion src/matrixrtc/MatrixRTCSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -869,7 +869,7 @@ export class MatrixRTCSession extends TypedEventEmitter<MatrixRTCSessionEvent, M
this.room.roomId,
EventType.GroupCallMemberPrefix,
newContent,
legacy ? localUserId : `${localUserId}_${localDeviceId}`,
legacy ? localUserId : this.makeMembershipStateKey(localUserId, localDeviceId),
);
logger.info(`Sent updated call member event.`);

Expand Down Expand Up @@ -899,6 +899,15 @@ export class MatrixRTCSession extends TypedEventEmitter<MatrixRTCSessionEvent, M
return false;
}

private makeMembershipStateKey(localUserId: string, localDeviceId: string): string {
const stateKey = `${localUserId}_${localDeviceId}`;
if (/^org\.matrix\.msc3779\b/.exec(this.room.getVersion())) {
return stateKey;
} else {
return `_${stateKey}`;
}
Comment on lines +904 to +908
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah nice preparing for the owned state events is a smart idea.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to give background on this: We never use the state key to actually compute the state events.
Which is somewhat broken. In theory a proper state event has to use a spec conform key.
With our implementation this is not checked (we could in theory send multiple member events for one user for the same device by using random state keys.)
This is what allows to only update the part where we compute the membership.

We probably want to check if the state key is to spec before parsing a state event.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added an issue here to track this: #4265

}

private onRotateKeyTimeout = (): void => {
if (!this.manageMediaKeys) return;

Expand Down
Loading