developer settings for ratcheting

This commit is contained in:
Timo
2025-04-15 18:23:23 +02:00
parent 6f38c8b0a7
commit 62445340cb
5 changed files with 56 additions and 7 deletions

View File

@@ -5,7 +5,11 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { BaseKeyProvider, createKeyMaterialFromBuffer } from "livekit-client";
import {
BaseKeyProvider,
createKeyMaterialFromBuffer,
KeyProviderEvent,
} from "livekit-client";
import { logger } from "matrix-js-sdk/lib/logger";
import {
type MatrixRTCSession,
@@ -16,7 +20,11 @@ export class MatrixKeyProvider extends BaseKeyProvider {
private rtcSession?: MatrixRTCSession;
public constructor() {
super({ ratchetWindowSize: 100, keyringSize: 256 });
// ratchetWindowSize the amount of ratchets we try consecutively before
// throwing an error log. After those attempts we will still try more retry batches.
// So there can be more than 10 ratchets in total.
super({ ratchetWindowSize: 10, keyringSize: 256 });
this.on(KeyProviderEvent.KeyRatcheted, this.onKeyRatcheted);
}
public setRTCSession(rtcSession: MatrixRTCSession): void {
@@ -60,4 +68,12 @@ export class MatrixKeyProvider extends BaseKeyProvider {
},
);
};
public onKeyRatcheted = (material: CryptoKey, keyIndex?: number): void => {
logger.debug(
`Key ratcheted event received for livekit room=${this.rtcSession?.room.roomId} keyIndex=${keyIndex}`,
`material:`,
material,
);
};
}

View File

@@ -13,7 +13,7 @@ import {
type RoomOptions,
Track,
} from "livekit-client";
import { useEffect, useMemo, useRef } from "react";
import { useCallback, useEffect, useMemo, useRef } from "react";
import E2EEWorker from "livekit-client/e2ee-worker?worker";
import { logger } from "matrix-js-sdk/lib/logger";
import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc";
@@ -37,6 +37,7 @@ import { type EncryptionSystem } from "../e2ee/sharedKeyManagement";
interface UseLivekitResult {
livekitRoom?: Room;
connState: ECConnectionState;
doKeyRatchet: () => void;
}
export function useLiveKit(
@@ -331,8 +332,16 @@ export function useLiveKit(
}
}, [room, devices, connectionState]);
const doKeyRatchet = useCallback(() => {
// not providing a key index will default to the current key
e2eeOptions?.keyProvider.ratchetKey(
room.localParticipant.identity,
undefined,
);
}, [e2eeOptions?.keyProvider, room.localParticipant.identity]);
return {
connState: connectionState,
livekitRoom: room,
doKeyRatchet,
};
}

View File

@@ -114,7 +114,7 @@ export interface ActiveCallProps
export const ActiveCall: FC<ActiveCallProps> = (props) => {
const sfuConfig = useOpenIDSFU(props.client, props.rtcSession);
const { livekitRoom, connState } = useLiveKit(
const { livekitRoom, connState, doKeyRatchet } = useLiveKit(
props.rtcSession,
props.muteStates,
sfuConfig,
@@ -164,6 +164,7 @@ export const ActiveCall: FC<ActiveCallProps> = (props) => {
vm={vm}
livekitRoom={livekitRoom}
connState={connState}
doKeyRatchet={doKeyRatchet}
/>
</ReactionsSenderProvider>
</RoomContext.Provider>
@@ -184,6 +185,7 @@ export interface InCallViewProps {
otelGroupCallMembership?: OTelGroupCallMembership;
connState: ECConnectionState;
onShareClick: (() => void) | null;
doKeyRatchet?: () => void;
}
export const InCallView: FC<InCallViewProps> = ({
@@ -198,6 +200,7 @@ export const InCallView: FC<InCallViewProps> = ({
hideHeader,
connState,
onShareClick,
doKeyRatchet,
}) => {
const { supportsReactions, sendReaction, toggleRaisedHand } =
useReactionsSender();
@@ -710,6 +713,7 @@ export const InCallView: FC<InCallViewProps> = ({
tab={settingsTab}
onTabChange={setSettingsTab}
livekitRoom={livekitRoom}
doKeyRatchet={doKeyRatchet}
/>
</>
)}

View File

@@ -7,6 +7,7 @@ Please see LICENSE in the repository root for full details.
import { type ChangeEvent, type FC, useCallback, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { Button } from "@vector-im/compound-web";
import { FieldRow, InputField } from "../input/Input";
import {
@@ -25,9 +26,14 @@ import { useUrlParams } from "../UrlParams";
interface Props {
client: MatrixClient;
livekitRoom?: LivekitRoom;
doKeyRatchet?: () => void;
}
export const DeveloperSettingsTab: FC<Props> = ({ client, livekitRoom }) => {
export const DeveloperSettingsTab: FC<Props> = ({
client,
livekitRoom,
doKeyRatchet,
}) => {
const { t } = useTranslation();
const [duplicateTiles, setDuplicateTiles] = useSetting(duplicateTilesSetting);
const [debugTileLayout, setDebugTileLayout] = useSetting(
@@ -88,7 +94,13 @@ export const DeveloperSettingsTab: FC<Props> = ({ client, livekitRoom }) => {
{t("developer_mode.device_id", {
id: client.getDeviceId() || "unknown",
})}
</p>
</p>{" "}
<FieldRow>
<Button size="sm" onClick={() => doKeyRatchet?.()}>
{" "}
Ratchet current key{" "}
</Button>{" "}
</FieldRow>
<FieldRow>
<InputField
id="duplicateTiles"

View File

@@ -49,6 +49,7 @@ interface Props {
client: MatrixClient;
roomId?: string;
livekitRoom?: LivekitRoom;
doKeyRatchet?: () => void;
}
export const defaultSettingsTab: SettingsTab = "audio";
@@ -61,6 +62,7 @@ export const SettingsModal: FC<Props> = ({
client,
roomId,
livekitRoom,
doKeyRatchet,
}) => {
const { t } = useTranslation();
@@ -144,7 +146,13 @@ export const SettingsModal: FC<Props> = ({
const developerTab: Tab<SettingsTab> = {
key: "developer",
name: t("settings.developer_tab_title"),
content: <DeveloperSettingsTab client={client} livekitRoom={livekitRoom} />,
content: (
<DeveloperSettingsTab
client={client}
livekitRoom={livekitRoom}
doKeyRatchet={doKeyRatchet}
/>
),
};
const tabs = [audioTab, videoTab];