Make the auth choice mode independent again

This commit is contained in:
Johannes Marbach
2026-10-12 20:37:14 +02:00
parent 37d25d4293
commit 54e948fdc0
13 changed files with 48 additions and 142 deletions
+5 -6
View File
@@ -54,21 +54,20 @@ const cases: {
guestFlows: ["cs-api"], guestFlows: ["cs-api"],
}, },
{ {
// In compatibility mode both publish a membership state event, so both // Publishers keep the legacy participant identity that clients predating
// must keep the legacy participant identity that clients predating MSC4195 // MSC4195 expect, which only the JWT service assigns.
// expect, which only the JWT service assigns.
hostShape: "both", hostShape: "both",
guestShape: "both", guestShape: "both",
hostFlows: ["service-legacy"], hostFlows: ["service-legacy"],
guestFlows: ["service-legacy"], guestFlows: ["service-legacy"],
}, },
{ {
// In Matrix 2.0 mode nobody expects a legacy identity, so the CS API wins. // The MatrixRTC mode has no bearing on the choice.
hostShape: "both", hostShape: "both",
guestShape: "both", guestShape: "both",
mode: "2_0", mode: "2_0",
hostFlows: ["cs-api"], hostFlows: ["service-legacy"],
guestFlows: ["cs-api"], guestFlows: ["service-legacy"],
}, },
{ {
hostShape: "url", hostShape: "url",
+15 -56
View File
@@ -21,7 +21,6 @@ import { delegateDelayedLeave, getSFUConfig } from ".";
import { mocked } from "storybook/test"; import { mocked } from "storybook/test";
import { ConnectionError, MatrixError } from "matrix-js-sdk"; import { ConnectionError, MatrixError } from "matrix-js-sdk";
import { NoMatrix2AuthorizationService } from "../../utils/errors"; import { NoMatrix2AuthorizationService } from "../../utils/errors";
import { MatrixRTCMode } from "../../config/ConfigOptions";
import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager";
vi.mock("./openID", () => ({ getSFUConfig: vi.fn() })); vi.mock("./openID", () => ({ getSFUConfig: vi.fn() }));
@@ -84,7 +83,6 @@ describe("getSFUConfig", () => {
membership, membership,
serverName: "example.org", serverName: "example.org",
role: "subscriber" as const, role: "subscriber" as const,
matrixRTCMode: MatrixRTCMode.Matrix_2_0,
roomId, roomId,
slotId, slotId,
logger, logger,
@@ -186,12 +184,24 @@ describe("getSFUConfig", () => {
expect(openID.getSFUConfig).not.toHaveBeenCalled(); expect(openID.getSFUConfig).not.toHaveBeenCalled();
}); });
it("uses CS API when publishing with url transport", async () => {
expect(
await getSFUConfig({
...defaultParams,
transport: urlTransport,
role: "publisher",
}),
).toEqual(expect.objectContaining({ jwt: csApiJWTToken }));
expect(client._unstable_getLivekitToken).toHaveBeenCalled();
expect(openID.getSFUConfig).not.toHaveBeenCalled();
});
it("does not fall back to OpenID when publishing", async () => { it("does not fall back to OpenID when publishing", async () => {
client._unstable_getLivekitToken.mockRejectedValueOnce(unsupportedError); client._unstable_getLivekitToken.mockRejectedValueOnce(unsupportedError);
await expect( await expect(
getSFUConfig({ getSFUConfig({
...defaultParams, ...defaultParams,
transport: urlAndServiceUrlTransport, transport: urlTransport,
role: "publisher", role: "publisher",
}), }),
).rejects.toThrow(expect.any(NoMatrix2AuthorizationService)); ).rejects.toThrow(expect.any(NoMatrix2AuthorizationService));
@@ -199,7 +209,7 @@ describe("getSFUConfig", () => {
expect(openID.getSFUConfig).not.toHaveBeenCalled(); expect(openID.getSFUConfig).not.toHaveBeenCalled();
}); });
it("uses OpenID when publishing in compatibility mode with url + livekit_service_url transport", async () => { it("uses OpenID when publishing with url + livekit_service_url transport", async () => {
// Subscribers predating MSC4195 expect a legacy participant identity from // Subscribers predating MSC4195 expect a legacy participant identity from
// anyone advertising a state event, which only the JWT service assigns // anyone advertising a state event, which only the JWT service assigns
expect( expect(
@@ -207,7 +217,6 @@ describe("getSFUConfig", () => {
...defaultParams, ...defaultParams,
transport: urlAndServiceUrlTransport, transport: urlAndServiceUrlTransport,
role: "publisher", role: "publisher",
matrixRTCMode: MatrixRTCMode.Compatibility,
}), }),
).toEqual( ).toEqual(
expect.objectContaining({ expect.objectContaining({
@@ -221,31 +230,6 @@ describe("getSFUConfig", () => {
); );
}); });
it("uses CS API when publishing in compatibility mode with url transport", async () => {
expect(
await getSFUConfig({
...defaultParams,
transport: urlTransport,
role: "publisher",
matrixRTCMode: MatrixRTCMode.Compatibility,
}),
).toEqual(expect.objectContaining({ jwt: csApiJWTToken }));
expect(client._unstable_getLivekitToken).toHaveBeenCalled();
expect(openID.getSFUConfig).not.toHaveBeenCalled();
});
it("uses CS API when subscribing in compatibility mode with url + livekit_service_url transport", async () => {
expect(
await getSFUConfig({
...defaultParams,
transport: urlAndServiceUrlTransport,
matrixRTCMode: MatrixRTCMode.Compatibility,
}),
).toEqual(expect.objectContaining({ jwt: csApiJWTToken }));
expect(client._unstable_getLivekitToken).toHaveBeenCalled();
expect(openID.getSFUConfig).not.toHaveBeenCalled();
});
it("does not fall back to OpenID on connection error", async () => { it("does not fall back to OpenID on connection error", async () => {
const client_ = { const client_ = {
...client, ...client,
@@ -275,7 +259,6 @@ describe("delegateDelayedLeave", () => {
roomId, roomId,
slotId, slotId,
delayId: "delay123", delayId: "delay123",
matrixRTCMode: MatrixRTCMode.Matrix_2_0,
logger, logger,
}; };
@@ -305,21 +288,11 @@ describe("delegateDelayedLeave", () => {
expect(openID.getSFUConfig).toHaveBeenCalled(); expect(openID.getSFUConfig).toHaveBeenCalled();
}); });
it("uses CS API with url + livekit_service_url transport", async () => { it("uses OpenID with url + livekit_service_url transport", async () => {
await delegateDelayedLeave({
...defaultParams,
transport: urlAndServiceUrlTransport,
});
expect(client._unstable_delegateDelayedLeave).toHaveBeenCalled();
expect(openID.getSFUConfig).not.toHaveBeenCalled();
});
it("uses OpenID in compatibility mode with url + livekit_service_url transport", async () => {
// Must match the flow that got the token, so the identities line up // Must match the flow that got the token, so the identities line up
await delegateDelayedLeave({ await delegateDelayedLeave({
...defaultParams, ...defaultParams,
transport: urlAndServiceUrlTransport, transport: urlAndServiceUrlTransport,
matrixRTCMode: MatrixRTCMode.Compatibility,
}); });
expect(client._unstable_delegateDelayedLeave).not.toHaveBeenCalled(); expect(client._unstable_delegateDelayedLeave).not.toHaveBeenCalled();
expect(openID.getSFUConfig).toHaveBeenCalledWith( expect(openID.getSFUConfig).toHaveBeenCalledWith(
@@ -330,18 +303,4 @@ describe("delegateDelayedLeave", () => {
}), }),
); );
}); });
it("does not fall back to OpenID with url + livekit_service_url transport", async () => {
client._unstable_delegateDelayedLeave.mockRejectedValueOnce(
unsupportedError,
);
await expect(
delegateDelayedLeave({
...defaultParams,
transport: urlAndServiceUrlTransport,
}),
).rejects.toThrow();
expect(client._unstable_delegateDelayedLeave).toHaveBeenCalled();
expect(openID.getSFUConfig).not.toHaveBeenCalled();
});
}); });
+6 -24
View File
@@ -14,7 +14,6 @@ import * as openID from "./openID";
import * as csApi from "./csApi"; import * as csApi from "./csApi";
import { type SFUConfig } from "./types"; import { type SFUConfig } from "./types";
import { NoMatrix2AuthorizationService } from "../../utils/errors"; import { NoMatrix2AuthorizationService } from "../../utils/errors";
import { MatrixRTCMode } from "../../config/ConfigOptions";
export type { ClientOpenIDParts } from "./openID"; export type { ClientOpenIDParts } from "./openID";
export type { ClientGetTokenParts, ClientDelegationParts } from "./csApi"; export type { ClientGetTokenParts, ClientDelegationParts } from "./csApi";
@@ -80,11 +79,6 @@ export interface GetSFUConfigParams {
* Whether we want to publish or only subscribe on the {@link transport}. * Whether we want to publish or only subscribe on the {@link transport}.
*/ */
role: "publisher" | "subscriber"; role: "publisher" | "subscriber";
/**
* The MatrixRTC mode, which decides the format of our membership event and
* so the participant identity a publisher must have.
*/
matrixRTCMode: MatrixRTCMode;
logger: Logger; logger: Logger;
} }
@@ -99,7 +93,6 @@ export async function getSFUConfig({
roomId, roomId,
slotId, slotId,
role, role,
matrixRTCMode,
logger, logger,
}: GetSFUConfigParams): Promise<SFUConfig> { }: GetSFUConfigParams): Promise<SFUConfig> {
const viaOpenID = async (serviceUrl: string): Promise<SFUConfig> => const viaOpenID = async (serviceUrl: string): Promise<SFUConfig> =>
@@ -113,7 +106,7 @@ export async function getSFUConfig({
logger, logger,
}); });
const flow = chooseAuthFlow(transport, role, matrixRTCMode); const flow = chooseAuthFlow(transport, role);
if (flow.kind === "openID") return await viaOpenID(flow.serviceUrl); if (flow.kind === "openID") return await viaOpenID(flow.serviceUrl);
try { try {
@@ -174,10 +167,6 @@ export interface DelegateDelayedLeaveParams {
* The delay ID of the leave event to be delegated. * The delay ID of the leave event to be delegated.
*/ */
delayId: string; delayId: string;
/**
* The MatrixRTC mode, which decides the format of our membership event.
*/
matrixRTCMode: MatrixRTCMode;
logger: Logger; logger: Logger;
} }
@@ -192,13 +181,12 @@ export async function delegateDelayedLeave({
roomId, roomId,
slotId, slotId,
delayId, delayId,
matrixRTCMode,
logger, logger,
}: DelegateDelayedLeaveParams): Promise<void> { }: DelegateDelayedLeaveParams): Promise<void> {
// It's important that we use the same flow (CS API or OpenID) as whatever we // It's important that we use the same flow (CS API or OpenID) as whatever we
// would've used to get a JWT token for this transport, since the participant // would've used to get a JWT token for this transport, since the participant
// identity computed by the service needs to match. // identity computed by the service needs to match.
const flow = chooseAuthFlow(transport, "publisher", matrixRTCMode); const flow = chooseAuthFlow(transport, "publisher");
if (flow.kind === "csApi") { if (flow.kind === "csApi") {
try { try {
await csApi.delegateDelayedLeave({ await csApi.delegateDelayedLeave({
@@ -246,25 +234,19 @@ export type AuthFlow =
* *
* Only the JWT service's `/sfu/get` endpoint assigns the legacy participant * Only the JWT service's `/sfu/get` endpoint assigns the legacy participant
* identity that clients predating MSC4195 expect from anyone advertising a * identity that clients predating MSC4195 expect from anyone advertising a
* membership state event, which is what compatibility mode sends. So a * membership state event. So a publisher keeps using the JWT service wherever
* publisher in compatibility mode keeps using the JWT service wherever the * the transport still offers one, even if it also has a `url`. Subscribers may
* transport still offers one, even if it also has a `url`. Subscribers may use * use the CS API regardless, as nobody matches their identity.
* the CS API regardless, as nobody matches their identity.
* @param transport The transport to authenticate against. * @param transport The transport to authenticate against.
* @param role Whether we want to publish or only subscribe on the transport. * @param role Whether we want to publish or only subscribe on the transport.
* @param matrixRTCMode The MatrixRTC mode, which decides the format of our
* membership event.
*/ */
export function chooseAuthFlow( export function chooseAuthFlow(
transport: UnstableLivekitTransport, transport: UnstableLivekitTransport,
role: "publisher" | "subscriber", role: "publisher" | "subscriber",
matrixRTCMode: MatrixRTCMode,
): AuthFlow { ): AuthFlow {
if ("url" in transport) { if ("url" in transport) {
const useCsApi = const useCsApi =
!("livekit_service_url" in transport) || !("livekit_service_url" in transport) || role === "subscriber";
role === "subscriber" ||
matrixRTCMode === MatrixRTCMode.Matrix_2_0;
if (useCsApi) return { kind: "csApi", url: transport.url }; if (useCsApi) return { kind: "csApi", url: transport.url };
} }
return { kind: "openID", serviceUrl: transport.livekit_service_url }; return { kind: "openID", serviceUrl: transport.livekit_service_url };
+1 -8
View File
@@ -531,7 +531,6 @@ export const DeveloperSettingsTab: FC<Props> = ({
roomId, roomId,
slotId: "org.example.fake-slot#room", slotId: "org.example.fake-slot#room",
role: "publisher", role: "publisher",
matrixRTCMode: effectiveMatrixRTCMode,
logger, logger,
}); });
setCustomLivekitUrlUpdateError(null); setCustomLivekitUrlUpdateError(null);
@@ -542,13 +541,7 @@ export const DeveloperSettingsTab: FC<Props> = ({
); );
} }
}, },
[ [customTransportTextBuffer, setCustomTransport, client, roomId],
customTransportTextBuffer,
setCustomTransport,
client,
roomId,
effectiveMatrixRTCMode,
],
)} )}
value={customTransportTextBuffer ?? ""} value={customTransportTextBuffer ?? ""}
onChange={useCallback( onChange={useCallback(
-2
View File
@@ -575,7 +575,6 @@ export function createCallViewModel$(
client, client,
matrixRoom.roomId, matrixRoom.roomId,
matrixRTCSession.slotId, matrixRTCSession.slotId,
matrixRTCMode,
mediaDevices, mediaDevices,
trackProcessorState$, trackProcessorState$,
livekitKeyProvider, livekitKeyProvider,
@@ -666,7 +665,6 @@ export function createCallViewModel$(
).pipe(map(([delayId]) => delayId ?? null)), ).pipe(map(([delayId]) => delayId ?? null)),
matrixRTCSession.delayId ?? null, matrixRTCSession.delayId ?? null,
), ),
matrixRTCMode,
logger: logger.getChild(`[${Date.now()}]`), logger: logger.getChild(`[${Date.now()}]`),
}); });
@@ -230,7 +230,6 @@ export function withCallViewModel(mode: MatrixRTCMode) {
client: room.client, client: room.client,
roomId: room.roomId, roomId: room.roomId,
slotId: "m.call#ROOM", slotId: "m.call#ROOM",
matrixRTCMode: mode,
livekitRoomFactory, livekitRoomFactory,
}, },
logger, logger,
@@ -346,27 +346,31 @@ describe("LocalMembership", () => {
.mockResolvedValue(); .mockResolvedValue();
afterEach(() => delegationSpy.mockClear()); afterEach(() => delegationSpy.mockClear());
// The transport has both a `url` and a `livekit_service_url`. In Matrix 2.0 const urlOnlyTransport: UnstableLivekitTransport = {
// mode we publish through the CS API, so the homeserver delegates; in type: "livekit",
// compatibility mode we publish through the JWT service, so that delegates. url: "https://sfu.example.org",
};
// With a `url` only we publish through the CS API, so the homeserver
// delegates. With a `livekit_service_url` we publish through the JWT
// service, so that delegates.
it.each([ it.each([
["no", MatrixRTCMode.Compatibility, null, timings], ["no", mockTransport, null, timings],
["no", MatrixRTCMode.Matrix_2_0, null, timings],
[ [
"homeserver", "homeserver",
MatrixRTCMode.Matrix_2_0, urlOnlyTransport,
"https://matrix.example.org/_matrix/client/unstable/io.element.msc4195/rtc/livekit/delegate_delayed_leave", "https://matrix.example.org/_matrix/client/unstable/io.element.msc4195/rtc/livekit/delegate_delayed_leave",
delegatedTimings, delegatedTimings,
], ],
[ [
"transport", "transport",
MatrixRTCMode.Compatibility, mockTransport,
"https://jwt.example.org/delegate_delayed_leave", "https://jwt.example.org/delegate_delayed_leave",
delegatedTimings, delegatedTimings,
], ],
])( ])(
"joins session with %s delegation support in %s mode", "joins session with %s delegation support",
async (_serviceName, matrixRTCMode, delegationUrl, delayedLeaveTimings) => { async (_serviceName, transport, delegationUrl, delayedLeaveTimings) => {
const scope = testScope(); const scope = testScope();
const joinMatrixRTC = vi.fn(); const joinMatrixRTC = vi.fn();
const delayId$ = new BehaviorSubject<string | null>(null); const delayId$ = new BehaviorSubject<string | null>(null);
@@ -375,15 +379,17 @@ describe("LocalMembership", () => {
fetchMock.post(delegationUrl, () => ({ status: 401, body: {} })); fetchMock.post(delegationUrl, () => ({ status: 401, body: {} }));
const connectionMap = new ConnectionMap(); const connectionMap = new ConnectionMap();
connectionMap.add(connectionTransportAConnected, []); connectionMap.add(
{ ...connectionTransportAConnected, transport } as Connection,
[],
);
const localMembership = createLocalMembership$({ const localMembership = createLocalMembership$({
scope, scope,
...defaultCreateLocalMemberValues, ...defaultCreateLocalMemberValues,
connectionMap$: constant(new Epoch(connectionMap)), connectionMap$: constant(new Epoch(connectionMap)),
joinMatrixRTC, joinMatrixRTC,
localTransport$: constant(mockTransportLocator), localTransport$: constant({ transport, serverName: "example.org" }),
delayId$, delayId$,
matrixRTCMode,
}); });
localMembership.requestJoinAndPublish(); localMembership.requestJoinAndPublish();
@@ -391,7 +397,7 @@ describe("LocalMembership", () => {
await flushPromises(); await flushPromises();
// Joins with timings appropriate for the level of delegation support // Joins with timings appropriate for the level of delegation support
expect(joinMatrixRTC).toHaveBeenCalledWith( expect(joinMatrixRTC).toHaveBeenCalledWith(
mockTransport, transport,
delayedLeaveTimings, delayedLeaveTimings,
); );
@@ -407,10 +413,9 @@ describe("LocalMembership", () => {
expect(delegationSpy).toHaveBeenLastCalledWith({ expect(delegationSpy).toHaveBeenLastCalledWith({
client: mockedClient, client: mockedClient,
membership: ownMemberMock, membership: ownMemberMock,
transport: mockTransport, transport,
roomId: "!test-room-id:example.org", roomId: "!test-room-id:example.org",
delayId, delayId,
matrixRTCMode,
logger: expect.anything(), logger: expect.anything(),
}); });
@@ -165,8 +165,6 @@ interface Props {
hostBridge: HostBridge; hostBridge: HostBridge;
baseUrl: string; baseUrl: string;
delayId$: Behavior<string | null>; delayId$: Behavior<string | null>;
/** The MatrixRTC mode, which decides the format of our membership event. */
matrixRTCMode: MatrixRTCMode;
logger: Logger; logger: Logger;
} }
@@ -214,7 +212,6 @@ export const createLocalMembership$ = ({
hostBridge, hostBridge,
ownMembershipIdentity, ownMembershipIdentity,
delayId$, delayId$,
matrixRTCMode,
}: Props): { }: Props): {
/** /**
* This request to start audio and video tracks. * This request to start audio and video tracks.
@@ -318,7 +315,7 @@ export const createLocalMembership$ = ({
switchMap(async ({ transport }) => { switchMap(async ({ transport }) => {
// Delegation goes through whichever service authenticates us as a // Delegation goes through whichever service authenticates us as a
// publisher, so only that service's support counts // publisher, so only that service's support counts
const flow = chooseAuthFlow(transport, "publisher", matrixRTCMode); const flow = chooseAuthFlow(transport, "publisher");
const delegationSupported = const delegationSupported =
flow.kind === "openID" flow.kind === "openID"
? await checkDelegationSupport( ? await checkDelegationSupport(
@@ -735,7 +732,6 @@ export const createLocalMembership$ = ({
slotId: matrixRTCSession.slotId, slotId: matrixRTCSession.slotId,
roomId, roomId,
delayId, delayId,
matrixRTCMode,
logger, logger,
}); });
logger.info("Delayed leave successfully delegated"); logger.info("Delayed leave successfully delegated");
@@ -42,7 +42,6 @@ import {
} from "./Connection.ts"; } from "./Connection.ts";
import { ObservableScope } from "../../ObservableScope.ts"; import { ObservableScope } from "../../ObservableScope.ts";
import { FailToGetOpenIdToken } from "../../../utils/errors.ts"; import { FailToGetOpenIdToken } from "../../../utils/errors.ts";
import { MatrixRTCMode } from "../../../config/ConfigOptions.ts";
import { testJWTToken } from "../../../utils/test-fixtures.ts"; import { testJWTToken } from "../../../utils/test-fixtures.ts";
import { mockRemoteParticipant, ownMemberMock } from "../../../utils/test.ts"; import { mockRemoteParticipant, ownMemberMock } from "../../../utils/test.ts";
import { import {
@@ -124,7 +123,6 @@ function setupRemoteConnection(): Connection {
client, client,
roomId: ROOM_ID, roomId: ROOM_ID,
slotId: SLOT_ID, slotId: SLOT_ID,
matrixRTCMode: MatrixRTCMode.Matrix_2_0,
role: "subscriber", role: "subscriber",
transport, transport,
serverName: "m.localhost", serverName: "m.localhost",
@@ -174,7 +172,6 @@ describe("Start connection states", () => {
client, client,
roomId: ROOM_ID, roomId: ROOM_ID,
slotId: SLOT_ID, slotId: SLOT_ID,
matrixRTCMode: MatrixRTCMode.Matrix_2_0,
role: "subscriber", role: "subscriber",
transport, transport,
serverName: "m.localhost", serverName: "m.localhost",
@@ -195,7 +192,6 @@ describe("Start connection states", () => {
client, client,
roomId: ROOM_ID, roomId: ROOM_ID,
slotId: SLOT_ID, slotId: SLOT_ID,
matrixRTCMode: MatrixRTCMode.Matrix_2_0,
role: "subscriber", role: "subscriber",
transport, transport,
serverName: "m.localhost", serverName: "m.localhost",
@@ -251,7 +247,6 @@ describe("Start connection states", () => {
client, client,
roomId: ROOM_ID, roomId: ROOM_ID,
slotId: SLOT_ID, slotId: SLOT_ID,
matrixRTCMode: MatrixRTCMode.Matrix_2_0,
role: "subscriber", role: "subscriber",
transport, transport,
serverName: "m.localhost", serverName: "m.localhost",
@@ -316,7 +311,6 @@ describe("Start connection states", () => {
client, client,
roomId: ROOM_ID, roomId: ROOM_ID,
slotId: SLOT_ID, slotId: SLOT_ID,
matrixRTCMode: MatrixRTCMode.Matrix_2_0,
role: "subscriber", role: "subscriber",
transport, transport,
serverName: "m.localhost", serverName: "m.localhost",
@@ -567,7 +561,6 @@ describe("remote track logging", () => {
client, client,
roomId: ROOM_ID, roomId: ROOM_ID,
slotId: SLOT_ID, slotId: SLOT_ID,
matrixRTCMode: MatrixRTCMode.Matrix_2_0,
role: "subscriber", role: "subscriber",
transport, transport,
serverName: "m.localhost", serverName: "m.localhost",
@@ -44,15 +44,12 @@ import {
type ClientOpenIDParts, type ClientOpenIDParts,
type SFUConfig, type SFUConfig,
} from "../../../livekit/auth"; } from "../../../livekit/auth";
import { type MatrixRTCMode } from "../../../config/ConfigOptions.ts";
export interface ConnectionOpts { export interface ConnectionOpts {
/** The identity parts to use on this connection */ /** The identity parts to use on this connection */
ownMembershipIdentity: CallMembershipIdentityParts; ownMembershipIdentity: CallMembershipIdentityParts;
/** Whether we want to publish or only subscribe on this connection. */ /** Whether we want to publish or only subscribe on this connection. */
role: "publisher" | "subscriber"; role: "publisher" | "subscriber";
/** The MatrixRTC mode, which decides the format of our membership event. */
matrixRTCMode: MatrixRTCMode;
/** The media transport to connect to. */ /** The media transport to connect to. */
transport: UnstableLivekitTransport; transport: UnstableLivekitTransport;
/** The name of the homeserver to which the {@link transport} belongs. */ /** The name of the homeserver to which the {@link transport} belongs. */
@@ -141,7 +138,6 @@ export class Connection {
private readonly client: ClientGetTokenParts & ClientOpenIDParts; private readonly client: ClientGetTokenParts & ClientOpenIDParts;
private readonly roomId: string; private readonly roomId: string;
private readonly slotId: string; private readonly slotId: string;
private readonly matrixRTCMode: MatrixRTCMode;
private readonly logger: Logger; private readonly logger: Logger;
private readonly ownMembershipIdentity: CallMembershipIdentityParts; private readonly ownMembershipIdentity: CallMembershipIdentityParts;
/** /**
@@ -155,7 +151,6 @@ export class Connection {
this.ownMembershipIdentity = opts.ownMembershipIdentity; this.ownMembershipIdentity = opts.ownMembershipIdentity;
this.roomId = opts.roomId; this.roomId = opts.roomId;
this.slotId = opts.slotId; this.slotId = opts.slotId;
this.matrixRTCMode = opts.matrixRTCMode;
this.logger = logger.getChild( this.logger = logger.getChild(
`[Connection ${JSON.stringify(opts.transport)}]`, `[Connection ${JSON.stringify(opts.transport)}]`,
); );
@@ -399,7 +394,6 @@ export class Connection {
serverName: this.serverName, serverName: this.serverName,
roomId: this.roomId, roomId: this.roomId,
slotId: this.slotId, slotId: this.slotId,
matrixRTCMode: this.matrixRTCMode,
logger: this.logger, logger: this.logger,
}); });
} }
@@ -39,7 +39,6 @@ import {
type ClientGetTokenParts, type ClientGetTokenParts,
type ClientOpenIDParts, type ClientOpenIDParts,
} from "../../../livekit/auth"; } from "../../../livekit/auth";
import { type MatrixRTCMode } from "../../../config/ConfigOptions.ts";
// TODO evaluate if this should be done like the Publisher Factory // TODO evaluate if this should be done like the Publisher Factory
export interface ConnectionFactory { export interface ConnectionFactory {
@@ -62,7 +61,6 @@ export class ECConnectionFactory implements ConnectionFactory {
* @param client - The OpenID client parts for authentication, needed to get openID and JWT tokens. * @param client - The OpenID client parts for authentication, needed to get openID and JWT tokens.
* @param roomId - The ID of the Matrix room in which the session takes place. * @param roomId - The ID of the Matrix room in which the session takes place.
* @param slotId - The ID of the MatrixRTC slot in which the session takes place. * @param slotId - The ID of the MatrixRTC slot in which the session takes place.
* @param matrixRTCMode - The MatrixRTC mode, which decides the format of our membership event.
* @param devices - Used for video/audio out/in capture options. * @param devices - Used for video/audio out/in capture options.
* @param processorState$ - Effects like background blur (only for publishing connection?) * @param processorState$ - Effects like background blur (only for publishing connection?)
* @param livekitKeyProvider - Optional key provider for end-to-end encryption. * @param livekitKeyProvider - Optional key provider for end-to-end encryption.
@@ -73,7 +71,6 @@ export class ECConnectionFactory implements ConnectionFactory {
private client: ClientGetTokenParts & ClientOpenIDParts, private client: ClientGetTokenParts & ClientOpenIDParts,
private readonly roomId: string, private readonly roomId: string,
private readonly slotId: string, private readonly slotId: string,
private readonly matrixRTCMode: MatrixRTCMode,
private devices: MediaDevices, private devices: MediaDevices,
private processorState$: Behavior<ProcessorState>, private processorState$: Behavior<ProcessorState>,
livekitKeyProvider: BaseKeyProvider | undefined, livekitKeyProvider: BaseKeyProvider | undefined,
@@ -120,7 +117,6 @@ export class ECConnectionFactory implements ConnectionFactory {
{ {
roomId: this.roomId, roomId: this.roomId,
slotId: this.slotId, slotId: this.slotId,
matrixRTCMode: this.matrixRTCMode,
role, role,
transport, transport,
serverName, serverName,
@@ -36,7 +36,6 @@ import {
cameraCodec, cameraCodec,
} from "../../../settings/settings.ts"; } from "../../../settings/settings.ts";
import { testJWTToken } from "../../../utils/test-fixtures.ts"; import { testJWTToken } from "../../../utils/test-fixtures.ts";
import { MatrixRTCMode } from "../../../config/ConfigOptions.ts";
// At the top of your test file, after imports // At the top of your test file, after imports
vi.mock("livekit-client", async (importOriginal) => { vi.mock("livekit-client", async (importOriginal) => {
@@ -85,7 +84,6 @@ describe("ECConnectionFactory - Audio inputs options", () => {
mockClient, mockClient,
"!roomid:example.org", "!roomid:example.org",
"m.call#ROOM", "m.call#ROOM",
MatrixRTCMode.Matrix_2_0,
mockMediaDevices({}), mockMediaDevices({}),
new BehaviorSubject<ProcessorState>({ new BehaviorSubject<ProcessorState>({
supported: true, supported: true,
@@ -131,7 +129,6 @@ describe("ECConnectionFactory - ControlledAudioDevice", () => {
mockClient, mockClient,
"!roomid:example.org", "!roomid:example.org",
"m.call#ROOM", "m.call#ROOM",
MatrixRTCMode.Matrix_2_0,
mockMediaDevices({ mockMediaDevices({
audioOutput: { audioOutput: {
available$: constant(new Map<never, never>()), available$: constant(new Map<never, never>()),
@@ -176,7 +173,6 @@ describe("ECConnectionFactory - Camera quality settings", () => {
mockClient, mockClient,
"!roomid:example.org", "!roomid:example.org",
"m.call#ROOM", "m.call#ROOM",
MatrixRTCMode.Matrix_2_0,
mockMediaDevices({}), mockMediaDevices({}),
new BehaviorSubject<ProcessorState>({ new BehaviorSubject<ProcessorState>({
supported: true, supported: true,
@@ -217,7 +213,6 @@ describe("ECConnectionFactory - Camera quality settings", () => {
mockClient, mockClient,
"!roomid:example.org", "!roomid:example.org",
"m.call#ROOM", "m.call#ROOM",
MatrixRTCMode.Matrix_2_0,
mockMediaDevices({}), mockMediaDevices({}),
new BehaviorSubject<ProcessorState>({ new BehaviorSubject<ProcessorState>({
supported: true, supported: true,
@@ -259,7 +254,6 @@ describe("ECConnectionFactory - Camera quality settings", () => {
mockClient, mockClient,
"!roomid:example.org", "!roomid:example.org",
"m.call#ROOM", "m.call#ROOM",
MatrixRTCMode.Matrix_2_0,
mockMediaDevices({}), mockMediaDevices({}),
new BehaviorSubject<ProcessorState>({ new BehaviorSubject<ProcessorState>({
supported: true, supported: true,
@@ -38,7 +38,6 @@ import { createConnectionMap$ } from "./ConnectionMap.ts";
import { membershipsAndTransports$ } from "../../SessionBehaviors.ts"; import { membershipsAndTransports$ } from "../../SessionBehaviors.ts";
import { localRtcMember, testJWTToken } from "../../../utils/test-fixtures.ts"; import { localRtcMember, testJWTToken } from "../../../utils/test-fixtures.ts";
import { deepCompare } from "matrix-js-sdk/lib/utils"; import { deepCompare } from "matrix-js-sdk/lib/utils";
import { MatrixRTCMode } from "../../../config/ConfigOptions.ts";
// Test the integration of ConnectionMap and MatrixLivekitMembers // Test the integration of ConnectionMap and MatrixLivekitMembers
@@ -76,7 +75,6 @@ beforeEach(() => {
mockClient, mockClient,
"!roomid:example.org", "!roomid:example.org",
"m.call#ROOM", "m.call#ROOM",
MatrixRTCMode.Matrix_2_0,
mockMediaDevices({}), mockMediaDevices({}),
new BehaviorSubject<ProcessorState>({ new BehaviorSubject<ProcessorState>({
supported: true, supported: true,