diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index 6ef494cd9..e41901b1f 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -170,7 +170,7 @@ export const createLocalMembership$ = ({ logger: parentLogger, muteStates, matrixRTCSession, - roomId: roomId, + roomId, }: Props): { /** * This request to start audio and video tracks. diff --git a/src/state/CallViewModel/localMember/LocalTransport.ts b/src/state/CallViewModel/localMember/LocalTransport.ts index 10ea79c44..c189044f4 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.ts @@ -180,9 +180,28 @@ export const createLocalTransport$ = ({ distinctUntilChanged(areLivekitTransportsEqual), ); + let lockedTransportAddress: string | undefined = undefined; const preferredTransport$ = combineLatest([preferredConfig$, delayId$]).pipe( switchMap(async ([transport, delayId]) => { try { + // We want to copy over the address from the first member on the same sfu. + if (lockedTransportAddress === undefined) { + const firstMemberOnSameSfu = memberships$.value.value.find( + (m) => + m.transports[0].type === "livekit" && + m.transports[0].livekit_service_url === + transport.livekit_service_url, + ); + const copiedFromMemberOnSameSfuAddress = ( + firstMemberOnSameSfu?.transports[0] as LivekitTransportConfig + )?.address; + const defaultAddress = roomId + ownMembershipIdentity.memberId; + lockedTransportAddress = copiedFromMemberOnSameSfuAddress ?? defaultAddress; + } + transport.address = lockedTransportAddress; + logger.info( + `Update preferredTransport$ ${transport.livekit_service_url} ${transport.address} with delayId ${delayId}`, + ); return await doOpenIdAndJWTFromUrl( transport, forceJwtEndpoint, @@ -308,11 +327,12 @@ async function doOpenIdAndJWTFromUrl( OpenIDClientParts, delayId?: string, ): Promise { + const sfuAddress = transport.address ?? roomId; const sfuConfig = await getSFUConfigWithOpenID( client, membership, transport.livekit_service_url, - roomId, + sfuAddress, { forceJwtEndpoint: forceJwtEndpoint, delayEndpointBaseUrl: client.baseUrl, diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index 013bd96c7..d0bb0812f 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -138,7 +138,7 @@ export class Connection { // TODO: can we just keep the ConnectionOpts object instead of spreading? private readonly client: OpenIDClientParts; - private readonly roomId: string; + private readonly sfuAddress: string; private readonly logger: Logger; private readonly ownMembershipIdentity: CallMembershipIdentityParts; private readonly existingSFUConfig?: SFUConfig; @@ -152,12 +152,12 @@ export class Connection { public constructor(opts: ConnectionOpts, logger: Logger) { this.ownMembershipIdentity = opts.ownMembershipIdentity; this.existingSFUConfig = opts.existingSFUConfig; - this.roomId = opts.roomId; + this.sfuAddress = opts.transport.address ?? opts.roomId; this.logger = logger.getChild( "[Connection " + opts.transport.livekit_service_url + "]", ); this.logger.info( - `constructor: ${opts.transport.livekit_service_url} roomId: ${this.roomId} withSfuConfig?: ${opts.existingSFUConfig ? JSON.stringify(opts.existingSFUConfig) : "undefined"}`, + `constructor: ${opts.transport.livekit_service_url} sfuAddress: ${this.sfuAddress} withSfuConfig?: ${opts.existingSFUConfig ? JSON.stringify(opts.existingSFUConfig) : "undefined"}`, ); const { transport, client, scope } = opts; @@ -284,7 +284,7 @@ export class Connection { this.client, this.ownMembershipIdentity, this.transport.livekit_service_url, - this.roomId, + this.sfuAddress, // dont pass any custom opts for the subscribe only connections {}, this.logger, diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index 727f68bcc..83ebdac46 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -45,7 +45,9 @@ export class ConnectionManagerData { private getKey(transport: LivekitTransportConfig): string { // This is enough as a key because the ConnectionManager is already scoped by room. // We also do not need to consider the slotId at this point since each `MatrixRTCSession` is already scoped by `slotDescription: {id, application}`. - return transport.livekit_service_url; + return ( + transport.livekit_service_url +"|"+ (transport.address ?? "default_address") + ); } public getConnections(): Connection[] { @@ -171,6 +173,7 @@ export function createConnectionManager$({ keys: [ transport.transport.livekit_service_url, transport.sfuConfig, + transport.transport.address, ], data: undefined, }; @@ -179,18 +182,20 @@ export function createConnectionManager$({ keys: [ transport.livekit_service_url, undefined as SFUConfig | undefined, + transport.address, ], data: undefined, }; } } }, - (scope, _data$, serviceUrl, sfuConfig) => { + (scope, _data$, serviceUrl, sfuConfig, address) => { const connection = connectionFactory.createConnection( scope, { type: "livekit", livekit_service_url: serviceUrl, + address, }, ownMembershipIdentity, logger, diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts index 0b93a274b..0bbc28013 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts @@ -157,7 +157,10 @@ export function areLivekitTransportsEqual( t2: T | null, ): boolean { if (t1 && t2) { - return t1.livekit_service_url === t2.livekit_service_url; + return ( + t1.livekit_service_url === t2.livekit_service_url && + t1.address === t2.address + ); } return !t1 && !t2; }