Identify transports by server name as well as URLs

A transport with only a LiveKit SFU `url` has to be authenticated through
our own homeserver, which needs to know the name of the server owning the
SFU. Carry that name alongside the transport as a TransportLocator,
derived from the member's user ID for remote transports and from the
client's domain for our own, and key the connection map on the SFU URL,
the service URL and the server name together so that `url`, service URL
and combined transport shapes are deduplicated consistently.
This commit is contained in:
Robin
2026-10-12 10:31:36 +02:00
committed by Johannes Marbach
parent 83e1396bdd
commit 53a0e273d6
21 changed files with 257 additions and 182 deletions
@@ -17,12 +17,7 @@ import {
type RemoteMatrixLivekitMember,
createRemoteMatrixLivekitMembers$,
} from "./MatrixLivekitMembers.ts";
import {
Epoch,
mapEpoch,
ObservableScope,
trackEpoch,
} from "../../ObservableScope.ts";
import { Epoch, ObservableScope, trackEpoch } from "../../ObservableScope.ts";
import { ConnectionMap } from "./ConnectionMap.ts";
import {
flushPromises,
@@ -32,6 +27,8 @@ import {
import { type Connection } from "./Connection.ts";
import { constant } from "../../Behavior.ts";
import { localRtcMember } from "../../../utils/test-fixtures.ts";
import { type TransportLocator } from "../../../livekit/auth";
import { membershipsAndTransports$ } from "../../SessionBehaviors.ts";
let testScope: ObservableScope;
@@ -112,24 +109,14 @@ function createEpochedMemberships$(m$: Observable<CallMembership[]>): {
memberships$: Observable<Epoch<CallMembership[]>>;
membershipsWithTransport$: Observable<
Epoch<
{ membership: CallMembership; transport?: UnstableLivekitTransport }[]
{ membership: CallMembership; transport: TransportLocator | undefined }[]
>
>;
} {
const memberships$ = m$.pipe(trackEpoch());
const membershipsWithTransport$ = memberships$.pipe(
mapEpoch((members) => {
return members.map((m) => {
const tr = m.getTransport();
return {
membership: m,
transport:
tr?.type === "livekit"
? (tr as UnstableLivekitTransport)
: undefined,
};
});
}),
const memberships$ = testScope.behavior(m$.pipe(trackEpoch()));
const { membershipsWithTransport$ } = membershipsAndTransports$(
testScope,
memberships$,
);
return {
memberships$,
@@ -149,6 +136,7 @@ test("should signal participant on a connection that is publishing", async () =>
const connection = {
transport: bobMembership.getTransport(),
serverName: "example.org",
} as unknown as Connection;
const dataWithPublisher = new ConnectionMap();
dataWithPublisher.add(connection, [
@@ -189,6 +177,7 @@ test("should signal participant on a connection that is not publishing", async (
const connection = {
transport: bobMembership.getTransport(),
serverName: "example.org",
} as unknown as Connection;
const dataWithPublisher = new ConnectionMap();
dataWithPublisher.add(connection, []);
@@ -227,9 +216,11 @@ describe("Publication edge case", () => {
);
const connectionA = {
transport: transportA,
serverName: "example.org",
} as unknown as Connection;
const connectionB = {
transport: transportB,
serverName: "sample.com",
} as unknown as Connection;
connectionWithPublisher.add(connectionA, [
@@ -282,8 +273,14 @@ test("bob is publishing in the wrong connection", async () => {
bobMembership.userId,
bobMembership.deviceId,
);
const connectionA = { transport: transportA } as unknown as Connection;
const connectionB = { transport: transportB } as unknown as Connection;
const connectionA = {
transport: transportA,
serverName: "example.org",
} as unknown as Connection;
const connectionB = {
transport: transportB,
serverName: "sample.com",
} as unknown as Connection;
// Bob is not publishing on A
connectionWithPublisher.add(connectionA, []);