Make use of the new jwt service endpoint (with delayed event delegation)
This also does all the compatibility work. When to use which endpoint to authenticate agains a jwt service.
This commit is contained in:
@@ -24,6 +24,7 @@ import {
|
||||
mockLivekitRoom,
|
||||
mockMuteStates,
|
||||
withTestScheduler,
|
||||
ownMemberMock,
|
||||
} from "../../../utils/test";
|
||||
import {
|
||||
TransportState,
|
||||
@@ -108,6 +109,7 @@ describe("LocalMembership", () => {
|
||||
|
||||
enterRTCSession(
|
||||
mockedSession,
|
||||
ownMemberMock,
|
||||
{
|
||||
livekit_alias: "roomId",
|
||||
livekit_service_url: "http://my-well-known-service-url.com",
|
||||
@@ -166,6 +168,7 @@ describe("LocalMembership", () => {
|
||||
|
||||
enterRTCSession(
|
||||
mockedSession,
|
||||
ownMemberMock,
|
||||
{
|
||||
livekit_alias: "roomId",
|
||||
livekit_service_url: "http://my-well-known-service-url.com",
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
} from "rxjs";
|
||||
import { type Logger } from "matrix-js-sdk/lib/logger";
|
||||
import { deepCompare } from "matrix-js-sdk/lib/utils";
|
||||
import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager";
|
||||
|
||||
import { constant, type Behavior } from "../../Behavior.ts";
|
||||
import { type IConnectionManager } from "../remoteMembers/ConnectionManager.ts";
|
||||
@@ -657,6 +658,7 @@ interface EnterRTCSessionOptions {
|
||||
// Exported for unit testing
|
||||
export function enterRTCSession(
|
||||
rtcSession: MatrixRTCSession,
|
||||
ownMembershipIdentity: CallMembershipIdentityParts,
|
||||
transport: LivekitTransport,
|
||||
{ encryptMedia, matrixRTCMode }: EnterRTCSessionOptions,
|
||||
): void {
|
||||
@@ -674,7 +676,8 @@ export function enterRTCSession(
|
||||
const multiSFU = matrixRTCMode !== MatrixRTCMode.Legacy;
|
||||
// Multi-sfu does not need a preferred foci list. just the focus that is actually used.
|
||||
// TODO where/how do we track errors originating from the ongoing rtcSession?
|
||||
rtcSession.joinRoomSession(
|
||||
rtcSession.joinRTCSession(
|
||||
ownMembershipIdentity,
|
||||
multiSFU ? [] : [transport],
|
||||
multiSFU ? transport : undefined,
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { type CallMembership } from "matrix-js-sdk/lib/matrixrtc";
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
|
||||
import { mockConfig, flushPromises } from "../../../utils/test";
|
||||
import { mockConfig, flushPromises, ownMemberMock } from "../../../utils/test";
|
||||
import { createLocalTransport$ } from "./LocalTransport";
|
||||
import { constant } from "../../Behavior";
|
||||
import { Epoch, ObservableScope } from "../../ObservableScope";
|
||||
@@ -32,10 +32,14 @@ describe("LocalTransport", () => {
|
||||
memberships$: constant(new Epoch<CallMembership[]>([])),
|
||||
client: {
|
||||
getDomain: () => "",
|
||||
baseUrl: "example.org",
|
||||
// These won't be called in this error path but satisfy the type
|
||||
getOpenIdToken: vi.fn(),
|
||||
getDeviceId: vi.fn(),
|
||||
},
|
||||
ownMembershipIdentity: ownMemberMock,
|
||||
useMatrix2$: constant(false),
|
||||
delayId$: constant("delay_id_mock"),
|
||||
});
|
||||
await flushPromises();
|
||||
|
||||
@@ -65,11 +69,15 @@ describe("LocalTransport", () => {
|
||||
useOldestMember$: constant(false),
|
||||
memberships$: constant(new Epoch<CallMembership[]>([])),
|
||||
client: {
|
||||
baseUrl: "https://lk.example.org",
|
||||
// Use empty domain to skip .well-known and use config directly
|
||||
getDomain: () => "",
|
||||
getOpenIdToken: vi.fn(),
|
||||
getDeviceId: vi.fn(),
|
||||
},
|
||||
ownMembershipIdentity: ownMemberMock,
|
||||
useMatrix2$: constant(false),
|
||||
delayId$: constant("delay_id_mock"),
|
||||
});
|
||||
localTransport$.subscribe(
|
||||
(o) => observations.push(o),
|
||||
@@ -105,7 +113,11 @@ describe("LocalTransport", () => {
|
||||
getDomain: () => "",
|
||||
getOpenIdToken: vi.fn(),
|
||||
getDeviceId: vi.fn(),
|
||||
baseUrl: "https://lk.example.org",
|
||||
},
|
||||
ownMembershipIdentity: ownMemberMock,
|
||||
useMatrix2$: constant(false),
|
||||
delayId$: constant("delay_id_mock"),
|
||||
});
|
||||
|
||||
openIdResolver.resolve?.({ url: "https://lk.example.org", jwt: "jwt" });
|
||||
@@ -140,7 +152,11 @@ describe("LocalTransport", () => {
|
||||
getDomain: () => "",
|
||||
getOpenIdToken: vi.fn(),
|
||||
getDeviceId: vi.fn(),
|
||||
baseUrl: "https://lk.example.org",
|
||||
},
|
||||
ownMembershipIdentity: ownMemberMock,
|
||||
useMatrix2$: constant(false),
|
||||
delayId$: constant("delay_id_mock"),
|
||||
});
|
||||
|
||||
openIdResolver.resolve?.({ url: "https://lk.example.org", jwt: "jwt" });
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
} from "rxjs";
|
||||
import { logger as rootLogger } from "matrix-js-sdk/lib/logger";
|
||||
import { AutoDiscovery } from "matrix-js-sdk/lib/autodiscovery";
|
||||
import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager";
|
||||
|
||||
import { type Behavior } from "../../Behavior.ts";
|
||||
import { type Epoch, type ObservableScope } from "../../ObservableScope.ts";
|
||||
@@ -34,6 +35,7 @@ import {
|
||||
} from "../../../livekit/openIDSFU.ts";
|
||||
import { areLivekitTransportsEqual } from "../remoteMembers/MatrixLivekitMembers.ts";
|
||||
import { customLivekitUrl } from "../../../settings/settings.ts";
|
||||
import { type LivekitTransportWithVersion } from "../remoteMembers/ConnectionManager.ts";
|
||||
|
||||
const logger = rootLogger.getChild("[LocalTransport]");
|
||||
|
||||
@@ -44,10 +46,13 @@ const logger = rootLogger.getChild("[LocalTransport]");
|
||||
*/
|
||||
interface Props {
|
||||
scope: ObservableScope;
|
||||
ownMembershipIdentity: CallMembershipIdentityParts;
|
||||
memberships$: Behavior<Epoch<CallMembership[]>>;
|
||||
client: Pick<MatrixClient, "getDomain"> & OpenIDClientParts;
|
||||
client: Pick<MatrixClient, "getDomain" | "baseUrl"> & OpenIDClientParts;
|
||||
roomId: string;
|
||||
useOldestMember$: Behavior<boolean>;
|
||||
useMatrix2$: Behavior<boolean>;
|
||||
delayId$: Behavior<string | null>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,20 +67,26 @@ interface Props {
|
||||
export const createLocalTransport$ = ({
|
||||
scope,
|
||||
memberships$,
|
||||
ownMembershipIdentity,
|
||||
client,
|
||||
roomId,
|
||||
useOldestMember$,
|
||||
}: Props): Behavior<LivekitTransport | null> => {
|
||||
useMatrix2$,
|
||||
delayId$,
|
||||
}: Props): Behavior<LivekitTransportWithVersion | null> => {
|
||||
/**
|
||||
* The transport over which we should be actively publishing our media.
|
||||
* undefined when not joined.
|
||||
*/
|
||||
const oldestMemberTransport$ = scope.behavior(
|
||||
memberships$.pipe(
|
||||
map(
|
||||
(memberships) =>
|
||||
memberships.value[0]?.getTransport(memberships.value[0]) ?? null,
|
||||
),
|
||||
map((memberships) => {
|
||||
const oldestMember = memberships.value[0];
|
||||
const t = oldestMember?.getTransport(memberships.value[0]);
|
||||
if (!t) return null;
|
||||
// Here we will use the matrix2 information from the oldest member transport.
|
||||
return { ...t, useMatrix2: oldestMember.kind === "rtc" };
|
||||
}),
|
||||
first((t) => t != null && isLivekitTransport(t)),
|
||||
),
|
||||
null,
|
||||
@@ -87,12 +98,24 @@ export const createLocalTransport$ = ({
|
||||
*
|
||||
* @throws MatrixRTCTransportMissingError | FailToGetOpenIdToken
|
||||
*/
|
||||
const preferredTransport$: Behavior<LivekitTransport | null> = scope.behavior(
|
||||
customLivekitUrl.value$.pipe(
|
||||
switchMap((customUrl) => from(makeTransport(client, roomId, customUrl))),
|
||||
),
|
||||
null,
|
||||
);
|
||||
const preferredTransport$: Behavior<LivekitTransportWithVersion | null> =
|
||||
scope.behavior(
|
||||
combineLatest([customLivekitUrl.value$, useMatrix2$, delayId$]).pipe(
|
||||
switchMap(([customUrl, useMatrix2, delayId]) =>
|
||||
from(
|
||||
makeTransport(
|
||||
client,
|
||||
ownMembershipIdentity,
|
||||
roomId,
|
||||
customUrl,
|
||||
useMatrix2,
|
||||
delayId ?? undefined,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
null,
|
||||
);
|
||||
|
||||
/**
|
||||
* The chosen transport we should advertise in our MatrixRTC membership.
|
||||
@@ -123,10 +146,13 @@ const FOCI_WK_KEY = "org.matrix.msc4143.rtc_foci";
|
||||
* @throws MatrixRTCTransportMissingError | FailToGetOpenIdToken
|
||||
*/
|
||||
async function makeTransport(
|
||||
client: Pick<MatrixClient, "getDomain"> & OpenIDClientParts,
|
||||
client: Pick<MatrixClient, "getDomain" | "baseUrl"> & OpenIDClientParts,
|
||||
membership: CallMembershipIdentityParts,
|
||||
roomId: string,
|
||||
urlFromDevSettings: string | null,
|
||||
): Promise<LivekitTransport> {
|
||||
matrix2jwt = false,
|
||||
delayId?: string,
|
||||
): Promise<LivekitTransportWithVersion> {
|
||||
let transport: LivekitTransport | undefined;
|
||||
logger.trace("Searching for a preferred transport");
|
||||
//TODO refactor this to use the jwt service returned alias.
|
||||
@@ -176,13 +202,18 @@ async function makeTransport(
|
||||
transport = transportFromConf;
|
||||
}
|
||||
|
||||
if (!transport) throw new MatrixRTCTransportMissingError(domain ?? ""); // this will call the jwt/sfu/get endpoint to pre create the livekit room.
|
||||
if (!transport) throw new MatrixRTCTransportMissingError(domain ?? "");
|
||||
|
||||
// this will call the jwt/sfu/get endpoint to pre create the livekit room.
|
||||
await getSFUConfigWithOpenID(
|
||||
client,
|
||||
membership,
|
||||
transport.livekit_service_url,
|
||||
transport.livekit_alias,
|
||||
matrix2jwt,
|
||||
client.baseUrl,
|
||||
delayId,
|
||||
);
|
||||
|
||||
return transport;
|
||||
return { ...transport, useMatrix2: matrix2jwt };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user