Base JWT service endpoint choice directly on the MatrixRTC mode

Since we removed the extra 'legacy' mode, meaning there's nothing simplified anymore by translating things over to a JWT service version.

(Also, simplify some things by making the mode static for the duration of a call.)
This commit is contained in:
Robin
2026-09-08 21:22:52 +02:00
parent d38daef567
commit 5cfe7ea4df
10 changed files with 58 additions and 115 deletions
+25 -43
View File
@@ -54,7 +54,6 @@ import { type IMembershipManager } from "matrix-js-sdk/lib/matrixrtc/IMembership
import {
createToggle$,
filterBehavior,
generateItem,
generateItems,
pauseWhen,
} from "../../utils/observable";
@@ -113,7 +112,6 @@ import {
} from "./localMember/LocalMember.ts";
import {
createLocalTransport$,
JwtEndpointVersion,
type LocalTransport,
} from "./localMember/LocalTransport.ts";
import {
@@ -191,7 +189,7 @@ export interface CallViewModelOptions {
/** Optional value overriding the connection factory, for testing purposes. */
connectionFactory?: ConnectionFactory;
/** The version & compatibility mode of MatrixRTC that we should use. */
matrixRTCMode$?: Behavior<MatrixRTCMode>;
matrixRTCMode?: MatrixRTCMode;
/** Optional behavior overriding for the screensharing, for testing */
toggleScreensharing?: () => void;
}
@@ -453,10 +451,8 @@ export function createCallViewModel$(
const configMatrixRTCMode = Config.get().matrix_rtc_mode as
| MatrixRTCMode
| undefined;
const matrixRTCMode$ =
configMatrixRTCMode !== undefined
? constant(configMatrixRTCMode)
: (options.matrixRTCMode$ ?? constant(MatrixRTCMode.Compatibility));
const matrixRTCMode =
configMatrixRTCMode ?? options.matrixRTCMode ?? MatrixRTCMode.Compatibility;
// Each hbar seperates a block of input variables required for the CallViewModel to function.
// The outputs of this block is written under the hbar.
@@ -490,38 +486,26 @@ export function createCallViewModel$(
memberId: uuidv4(),
};
const localTransport$ = scope.behavior(
matrixRTCMode$.pipe(
generateItem(
"CallViewModel localTransport$",
// Re-create LocalTransport whenever the mode changes
(mode) => ({ keys: [mode], data: undefined }),
(scope, _data$, mode) =>
options.localTransport ??
createLocalTransport$({
scope: scope,
memberships$: memberships$,
ownMembershipIdentity,
client,
delayId$: scope.behavior(
(
fromEvent(
matrixRTCSession,
MembershipManagerEvent.DelayIdChanged,
// The type of reemitted event includes the original emitted as the second arg.
) as Observable<[string | undefined, IMembershipManager]>
).pipe(map(([delayId]) => delayId ?? null)),
matrixRTCSession.delayId ?? null,
),
roomId: matrixRoom.roomId,
forceJwtEndpoint:
mode === MatrixRTCMode.Matrix_2_0
? JwtEndpointVersion.Matrix_2_0
: JwtEndpointVersion.Legacy,
}),
const localTransport =
options.localTransport ??
createLocalTransport$({
scope: scope,
memberships$: memberships$,
ownMembershipIdentity,
client,
delayId$: scope.behavior(
(
fromEvent(
matrixRTCSession,
MembershipManagerEvent.DelayIdChanged,
// The type of reemitted event includes the original emitted as the second arg.
) as Observable<[string | undefined, IMembershipManager]>
).pipe(map(([delayId]) => delayId ?? null)),
matrixRTCSession.delayId ?? null,
),
),
);
roomId: matrixRoom.roomId,
matrixRTCMode,
});
const connectionFactory =
options.connectionFactory ??
@@ -539,8 +523,7 @@ export function createCallViewModel$(
scope: scope,
connectionFactory: connectionFactory,
localTransport$: scope.behavior(
localTransport$.pipe(
switchMap((t) => t.active$),
localTransport.active$.pipe(
catchError((e: unknown) => {
logger.info(
"could not pass local transport to createConnectionManager$. localTransport$ threw an error",
@@ -583,9 +566,7 @@ export function createCallViewModel$(
transport,
{
encryptMedia: livekitKeyProvider !== undefined,
// We merely sample the current mode here, so the user would need to
// manually rejoin to switch to a different one
matrixRTCMode: matrixRTCMode$.value,
matrixRTCMode,
delayedLeaveTimings,
},
);
@@ -606,6 +587,7 @@ export function createCallViewModel$(
localTransport$,
roomId: matrixRoom.roomId,
baseUrl: client.baseUrl,
matrixRTCMode,
logger: logger.getChild(`[${Date.now()}]`),
});
@@ -238,7 +238,7 @@ export function withCallViewModel(mode: MatrixRTCMode) {
);
},
},
matrixRTCMode$: constant(mode),
matrixRTCMode: mode,
...options,
},
raisedHands$,
@@ -230,6 +230,7 @@ describe("LocalMembership", () => {
},
roomId: "!test-room-id:example.org",
baseUrl: "https://matrix.example.org",
matrixRTCMode: MATRIX_RTC_MODE,
};
beforeEach(() => {
@@ -143,7 +143,7 @@ interface Props {
) => void;
homeserverConnected: HomeserverConnected;
roomId: string;
localTransport$: Behavior<LocalTransport>;
localTransport: LocalTransport;
matrixRTCSession: Pick<
MatrixRTCSession,
"updateCallIntent" | "leaveRoomSession"
@@ -163,7 +163,7 @@ interface Props {
* @param props.createPublisherFactory Factory to create a publisher once we have a connection.
* @param props.joinMatrixRTC Callback to join the matrix RTC session once we have a transport.
* @param props.homeserverConnected The homeserver connected state.
* @param props.localTransport$ The transport to advertise in our membership.
* @param props.localTransport The transport to advertise in our membership.
* @param props.logger The logger to use.
* @param props.muteStates The mute states for video and audio.
* @param props.matrixRTCSession The matrix RTC session to join.
@@ -282,8 +282,7 @@ export const createLocalMembership$ = ({
// The transport that we will advertise in our membership, paired with info as
// to whether delayed event delegation is supported
const joinParams$ = localTransport$.pipe(
switchMap((lt) => lt.advertised$),
const joinParams$ = localTransport.advertised$.pipe(
catchError(handleTransportError),
distinctUntilChanged(areLivekitTransportsEqual),
switchMap((transport) => {
@@ -304,16 +303,12 @@ export const createLocalMembership$ = ({
// Unwrap the local transport and set the state of the LocalMembership to error in case the transport is an error.
const activeTransport$ = scope.behavior(
localTransport$.pipe(
switchMap((lt) => {
return combineLatest([lt.active$, lt.advertised$]).pipe(
map(([active, advertised]) => {
// Our policy is to not publish to another transport if our prefered transport is miss-configured
if (advertised == null) return null;
combineLatest([localTransport.active$, localTransport.advertised$]).pipe(
map(([active, advertised]) => {
// Our policy is to not publish to another transport if our prefered transport is miss-configured
if (advertised == null) return null;
return active?.transport ?? null;
}),
);
return active?.transport ?? null;
}),
catchError(handleTransportError),
distinctUntilChanged(areLivekitTransportsEqual),
@@ -41,6 +41,7 @@ import {
import * as openIDSFU from "../../../livekit/openIDSFU";
import { customLivekitUrl } from "../../../settings/settings";
import { testJWTToken } from "../../../utils/test-fixtures";
import { MatrixRTCMode } from "../../../config/ConfigOptions";
describe("LocalTransport", () => {
const openIdResponse: openIDSFU.SFUConfig = {
@@ -67,7 +68,7 @@ describe("LocalTransport", () => {
getDeviceId: vi.fn(),
},
ownMembershipIdentity: ownMemberMock,
forceJwtEndpoint: JwtEndpointVersion.Legacy,
matrixRTCMode: MatrixRTCMode.Compatibility,
delayId$: constant("delay_id_mock"),
});
await flushPromises();
@@ -108,7 +109,7 @@ describe("LocalTransport", () => {
getDeviceId: vi.fn(),
},
ownMembershipIdentity: ownMemberMock,
forceJwtEndpoint: JwtEndpointVersion.Legacy,
matrixRTCMode: MatrixRTCMode.Compatibility,
delayId$: constant("delay_id_mock"),
});
active$.subscribe(
@@ -150,7 +151,7 @@ describe("LocalTransport", () => {
baseUrl: "https://example.org",
},
ownMembershipIdentity: ownMemberMock,
forceJwtEndpoint: JwtEndpointVersion.Legacy,
matrixRTCMode: MatrixRTCMode.Compatibility,
delayId$: constant("delay_id_mock"),
});
@@ -194,7 +195,7 @@ describe("LocalTransport", () => {
ownMembershipIdentity: ownMemberMock,
scope: testScope(),
roomId: "!example_room_id",
forceJwtEndpoint: JwtEndpointVersion.Legacy,
matrixRTCMode: MatrixRTCMode.Compatibility,
delayId$: constant(null),
memberships$: constant(new Epoch<CallMembership[]>([])),
client: {
@@ -306,7 +307,7 @@ describe("LocalTransport", () => {
scope: testScope(),
ownMembershipIdentity: ownMemberMock,
roomId: "!example_room_id",
forceJwtEndpoint: JwtEndpointVersion.Legacy,
matrixRTCMode: MatrixRTCMode.Compatibility,
delayId$: constant(null),
memberships$: constant(new Epoch<CallMembership[]>([])),
client: {
@@ -37,6 +37,7 @@ import {
import { areLivekitTransportsEqual } from "../remoteMembers/MatrixLivekitMembers.ts";
import { customLivekitUrl } from "../../../settings/settings.ts";
import { RtcTransportAutoDiscovery } from "./RtcTransportAutoDiscovery.ts";
import { type MatrixRTCMode } from "../../../config/ConfigOptions.ts";
/*
* It figures out “which LiveKit focus URL/alias the local user should use,”
@@ -53,15 +54,10 @@ interface Props {
OpenIDClientParts;
// Used by the jwt service to create the livekit room and compute the livekit alias.
roomId: string;
forceJwtEndpoint: JwtEndpointVersion;
matrixRTCMode: MatrixRTCMode;
delayId$: Behavior<string | null>;
}
export enum JwtEndpointVersion {
Legacy = "legacy",
Matrix_2_0 = "matrix_2_0",
}
// TODO livekit_alias-cleanup
// 1. We need to move away from transports map to connections!!!
//
@@ -122,7 +118,7 @@ export const createLocalTransport$ = ({
ownMembershipIdentity,
client,
roomId,
forceJwtEndpoint,
matrixRTCMode,
delayId$,
}: Props): LocalTransport => {
const logger = rootLogger.getChild("[LocalTransport]");
@@ -167,7 +163,7 @@ export const createLocalTransport$ = ({
try {
return await doOpenIdAndJWTFromUrl(
transport,
forceJwtEndpoint,
matrixRTCMode,
ownMembershipIdentity,
roomId,
client,
@@ -219,7 +215,7 @@ export const createLocalTransport$ = ({
* use we don't want to risk any issues by re-using a token.
*
* @param transport The transport to authenticate with.
* @param forceJwtEndpoint Whether to force the JWT endpoint to be used.
* @param matrixRTCMode Whether to force the JWT endpoint to be used.
* @param membership The identity of the local member.
* @param roomId The room ID to use for the JWT.
* @param client The client to use for the OpenID token.
@@ -229,7 +225,7 @@ export const createLocalTransport$ = ({
*/
async function doOpenIdAndJWTFromUrl(
transport: LivekitTransportConfig,
forceJwtEndpoint: JwtEndpointVersion,
matrixRTCMode: MatrixRTCMode,
membership: CallMembershipIdentityParts,
roomId: string,
client: Pick<
@@ -246,7 +242,7 @@ async function doOpenIdAndJWTFromUrl(
transport.livekit_service_url,
roomId,
{
forceJwtEndpoint: forceJwtEndpoint,
matrixRTCMode,
delayEndpointBaseUrl: client.baseUrl,
delayId,
},