mirror of
https://github.com/vector-im/element-call.git
synced 2026-09-22 22:29:30 +00:00
simplefy call participation transport driver impl
This commit is contained in:
@@ -22,23 +22,12 @@ import {
|
|||||||
FfiStatus,
|
FfiStatus,
|
||||||
type FfiConnectionWithMembers,
|
type FfiConnectionWithMembers,
|
||||||
type FfiJoinParams,
|
type FfiJoinParams,
|
||||||
type FfiLivekitToken,
|
|
||||||
type FfiLivekitTokenRequest,
|
|
||||||
type FfiMediaKey,
|
type FfiMediaKey,
|
||||||
type FfiMembership,
|
type FfiMembership,
|
||||||
type FfiParticipationConfig,
|
type FfiParticipationConfig,
|
||||||
type FfiRtcTransport,
|
type FfiRtcTransport,
|
||||||
type FfiSendEventResponse,
|
|
||||||
type FfiSessionSnapshot,
|
type FfiSessionSnapshot,
|
||||||
type FfiToDeviceDelivery,
|
|
||||||
type FfiToDeviceRecipient,
|
|
||||||
type FfiHomeserverDelegationRequest,
|
|
||||||
type FfiTransportDelegationRequest,
|
|
||||||
type FfiTransportIntent,
|
type FfiTransportIntent,
|
||||||
type ConnectivitySinkLike,
|
|
||||||
type RoomEventSinkLike,
|
|
||||||
type StateUpdateSinkLike,
|
|
||||||
type ToDeviceSinkLike,
|
|
||||||
} from "../../matrix-rtc-sdk";
|
} from "../../matrix-rtc-sdk";
|
||||||
import { type Behavior } from "../Behavior";
|
import { type Behavior } from "../Behavior";
|
||||||
import { Epoch, type ObservableScope, trackEpoch } from "../ObservableScope";
|
import { Epoch, type ObservableScope, trackEpoch } from "../ObservableScope";
|
||||||
@@ -103,6 +92,7 @@ export interface CallParticipationOptions {
|
|||||||
* keeps it current from the manager's listener, and ends the participation
|
* keeps it current from the manager's listener, and ends the participation
|
||||||
* (leaving if still joined) when the scope ends.
|
* (leaving if still joined) when the scope ends.
|
||||||
*/
|
*/
|
||||||
|
// TODO-RENAME: the call participationmanager wrapper represents the RtcParticipationManager
|
||||||
export class CallParticipation {
|
export class CallParticipation {
|
||||||
private readonly logger: Logger;
|
private readonly logger: Logger;
|
||||||
private readonly matrixDriver: FfiMatrixDriver;
|
private readonly matrixDriver: FfiMatrixDriver;
|
||||||
@@ -158,7 +148,7 @@ export class CallParticipation {
|
|||||||
const rtcDriver =
|
const rtcDriver =
|
||||||
options.transportFallbackUrl === undefined
|
options.transportFallbackUrl === undefined
|
||||||
? driver
|
? driver
|
||||||
: new TransportFallbackDriver(
|
: withTransportFallback(
|
||||||
driver,
|
driver,
|
||||||
options.transportFallbackUrl,
|
options.transportFallbackUrl,
|
||||||
this.logger,
|
this.logger,
|
||||||
@@ -402,155 +392,62 @@ function joinedOnly(memberships: FfiMembership[]): FfiMembership[] {
|
|||||||
return memberships.filter((m) => m.state === FfiMembershipState.Joined);
|
return memberships.filter((m) => m.state === FfiMembershipState.Joined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A driver that behaves like `inner` except for the methods in `overrides`.
|
||||||
|
* Everything else reaches `inner` untouched — every argument, including the
|
||||||
|
* `asyncOpts_` abort signal the bindings pass last, and any method the
|
||||||
|
* driver contract grows later — called on `inner` itself so that a method
|
||||||
|
* reading its own fields still works.
|
||||||
|
*/
|
||||||
|
function overrideDriver(
|
||||||
|
inner: RtcMatrixDriver,
|
||||||
|
overrides: Partial<RtcMatrixDriver>,
|
||||||
|
): RtcMatrixDriver {
|
||||||
|
return new Proxy(inner, {
|
||||||
|
get: (target, property): unknown => {
|
||||||
|
if (Object.hasOwn(overrides, property))
|
||||||
|
return Reflect.get(overrides, property);
|
||||||
|
const value: unknown = Reflect.get(target, property, target);
|
||||||
|
return typeof value === "function" ? value.bind(target) : value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Answers transport discovery with a configured LiveKit service URL when the
|
* Answers transport discovery with a configured LiveKit service URL when the
|
||||||
* host's homeserver advertises none or cannot be asked — the precedence
|
* host's homeserver advertises none or cannot be asked — the precedence
|
||||||
* Element Call has always had (homeserver first, `config.json` second) —
|
* Element Call has always had (homeserver first, `config.json` second) —
|
||||||
* and delegates everything else to the host's driver untouched.
|
* and delegates everything else to the host's driver untouched.
|
||||||
*/
|
*/
|
||||||
class TransportFallbackDriver implements RtcMatrixDriver {
|
function withTransportFallback(
|
||||||
public constructor(
|
inner: RtcMatrixDriver,
|
||||||
private readonly inner: RtcMatrixDriver,
|
fallbackUrl: string,
|
||||||
private readonly fallbackUrl: string,
|
logger: Logger,
|
||||||
private readonly logger: Logger,
|
): RtcMatrixDriver {
|
||||||
) {}
|
return overrideDriver(inner, {
|
||||||
|
async getRtcTransports(): Promise<FfiRtcTransport[]> {
|
||||||
public async getRtcTransports(): Promise<FfiRtcTransport[]> {
|
let transports: FfiRtcTransport[] = [];
|
||||||
let transports: FfiRtcTransport[] = [];
|
try {
|
||||||
try {
|
transports = await inner.getRtcTransports();
|
||||||
transports = await this.inner.getRtcTransports();
|
} catch (e) {
|
||||||
} catch (e) {
|
logger.info(
|
||||||
this.logger.info(
|
"Transport discovery failed; falling back to the configured LiveKit service",
|
||||||
"Transport discovery failed; falling back to the configured LiveKit service",
|
e,
|
||||||
e,
|
);
|
||||||
|
}
|
||||||
|
if (transports.some((t) => t.transportType === LIVEKIT_TRANSPORT_TYPE))
|
||||||
|
return transports;
|
||||||
|
logger.info(
|
||||||
|
"The homeserver advertises no LiveKit transport; using the configured one",
|
||||||
);
|
);
|
||||||
}
|
return [
|
||||||
if (transports.some((t) => t.transportType === LIVEKIT_TRANSPORT_TYPE))
|
{
|
||||||
return transports;
|
transportType: LIVEKIT_TRANSPORT_TYPE,
|
||||||
this.logger.info(
|
propertiesJson: JSON.stringify({
|
||||||
"The homeserver advertises no LiveKit transport; using the configured one",
|
livekit_service_url: fallbackUrl,
|
||||||
);
|
}),
|
||||||
return [
|
},
|
||||||
{
|
];
|
||||||
transportType: LIVEKIT_TRANSPORT_TYPE,
|
},
|
||||||
propertiesJson: JSON.stringify({
|
});
|
||||||
livekit_service_url: this.fallbackUrl,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public async sendStickyEvent(
|
|
||||||
roomId: string,
|
|
||||||
eventType: string,
|
|
||||||
contentJson: string,
|
|
||||||
durationMs: bigint,
|
|
||||||
): Promise<FfiSendEventResponse> {
|
|
||||||
return this.inner.sendStickyEvent(
|
|
||||||
roomId,
|
|
||||||
eventType,
|
|
||||||
contentJson,
|
|
||||||
durationMs,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
public async sendStateEvent(
|
|
||||||
roomId: string,
|
|
||||||
eventType: string,
|
|
||||||
stateKey: string,
|
|
||||||
contentJson: string,
|
|
||||||
): Promise<FfiSendEventResponse> {
|
|
||||||
return this.inner.sendStateEvent(roomId, eventType, stateKey, contentJson);
|
|
||||||
}
|
|
||||||
public async sendDelayedEvent(
|
|
||||||
roomId: string,
|
|
||||||
eventType: string,
|
|
||||||
contentJson: string,
|
|
||||||
delayMs: bigint,
|
|
||||||
stickyDurationMs: bigint | undefined,
|
|
||||||
): Promise<string> {
|
|
||||||
return this.inner.sendDelayedEvent(
|
|
||||||
roomId,
|
|
||||||
eventType,
|
|
||||||
contentJson,
|
|
||||||
delayMs,
|
|
||||||
stickyDurationMs,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
public async sendDelayedStateEvent(
|
|
||||||
roomId: string,
|
|
||||||
eventType: string,
|
|
||||||
stateKey: string,
|
|
||||||
contentJson: string,
|
|
||||||
delayMs: bigint,
|
|
||||||
): Promise<string> {
|
|
||||||
return this.inner.sendDelayedStateEvent(
|
|
||||||
roomId,
|
|
||||||
eventType,
|
|
||||||
stateKey,
|
|
||||||
contentJson,
|
|
||||||
delayMs,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
public async restartDelayedEvent(
|
|
||||||
roomId: string,
|
|
||||||
delayId: string,
|
|
||||||
): Promise<void> {
|
|
||||||
return this.inner.restartDelayedEvent(roomId, delayId);
|
|
||||||
}
|
|
||||||
public async cancelDelayedEvent(
|
|
||||||
roomId: string,
|
|
||||||
delayId: string,
|
|
||||||
): Promise<void> {
|
|
||||||
return this.inner.cancelDelayedEvent(roomId, delayId);
|
|
||||||
}
|
|
||||||
public async delegateDelayedLeaveViaHomeserver(
|
|
||||||
request: FfiHomeserverDelegationRequest,
|
|
||||||
): Promise<void> {
|
|
||||||
return this.inner.delegateDelayedLeaveViaHomeserver(request);
|
|
||||||
}
|
|
||||||
public async delegateDelayedLeaveViaTransport(
|
|
||||||
request: FfiTransportDelegationRequest,
|
|
||||||
): Promise<void> {
|
|
||||||
return this.inner.delegateDelayedLeaveViaTransport(request);
|
|
||||||
}
|
|
||||||
public async sendToDevice(
|
|
||||||
recipients: FfiToDeviceRecipient[],
|
|
||||||
eventType: string,
|
|
||||||
contentJson: string,
|
|
||||||
): Promise<FfiToDeviceDelivery[]> {
|
|
||||||
return this.inner.sendToDevice(recipients, eventType, contentJson);
|
|
||||||
}
|
|
||||||
public async getLivekitToken(
|
|
||||||
request: FfiLivekitTokenRequest,
|
|
||||||
): Promise<FfiLivekitToken> {
|
|
||||||
return this.inner.getLivekitToken(request);
|
|
||||||
}
|
|
||||||
public async readEvents(
|
|
||||||
eventType: string,
|
|
||||||
stateKey: string | undefined,
|
|
||||||
limit: number,
|
|
||||||
): Promise<string[]> {
|
|
||||||
return this.inner.readEvents(eventType, stateKey, limit);
|
|
||||||
}
|
|
||||||
public async readState(
|
|
||||||
eventType: string,
|
|
||||||
stateKey: string | undefined,
|
|
||||||
): Promise<string[]> {
|
|
||||||
return this.inner.readState(eventType, stateKey);
|
|
||||||
}
|
|
||||||
public subscribeRoomEvents(sink: RoomEventSinkLike): void {
|
|
||||||
this.inner.subscribeRoomEvents(sink);
|
|
||||||
}
|
|
||||||
public subscribeToDeviceEvents(sink: ToDeviceSinkLike): void {
|
|
||||||
this.inner.subscribeToDeviceEvents(sink);
|
|
||||||
}
|
|
||||||
public subscribeStateUpdates(sink: StateUpdateSinkLike): void {
|
|
||||||
this.inner.subscribeStateUpdates(sink);
|
|
||||||
}
|
|
||||||
public subscribeConnectivity(sink: ConnectivitySinkLike): void {
|
|
||||||
this.inner.subscribeConnectivity(sink);
|
|
||||||
}
|
|
||||||
public isHomeserverConnected(): boolean {
|
|
||||||
return this.inner.isHomeserverConnected();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user