From b1482d2cd79698c7849bb406a1c8ca21f1901e62 Mon Sep 17 00:00:00 2001 From: lukasIO Date: Mon, 5 Jan 2026 20:46:24 +0100 Subject: [PATCH 1/2] Cache v0 signal path usage on SignalClient --- src/api/SignalClient.ts | 32 +++++++++++++++++++++----------- src/room/RTCEngine.ts | 8 ++++---- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/api/SignalClient.ts b/src/api/SignalClient.ts index 04530c9271..7f8cf359fb 100644 --- a/src/api/SignalClient.ts +++ b/src/api/SignalClient.ts @@ -225,6 +225,8 @@ export class SignalClient { private streamWriter: WritableStreamDefaultWriter | undefined; + private useV0SignalPath = false; + constructor(useJSON: boolean = false, loggerOptions: LoggerOptions = {}) { this.log = getLogger(loggerOptions.loggerName ?? LoggerNames.Signal); this.loggerContextCb = loggerOptions.loggerContextCb; @@ -245,13 +247,13 @@ export class SignalClient { token: string, opts: SignalOptions, abortSignal?: AbortSignal, - forceV0Path?: boolean, + useV0Path: boolean = false, ): Promise { // during a full reconnect, we'd want to start the sequence even if currently // connected this.state = SignalConnectionState.CONNECTING; this.options = opts; - const res = await this.connect(url, token, opts, abortSignal, forceV0Path); + const res = await this.connect(url, token, opts, abortSignal, useV0Path); return res as JoinResponse; } @@ -272,12 +274,18 @@ export class SignalClient { // clear ping interval and restart it once reconnected this.clearPingInterval(); - const res = (await this.connect(url, token, { - ...this.options, - reconnect: true, - sid, - reconnectReason: reason, - })) as ReconnectResponse | undefined; + const res = (await this.connect( + url, + token, + { + ...this.options, + reconnect: true, + sid, + reconnectReason: reason, + }, + undefined, + this.useV0SignalPath, + )) as ReconnectResponse | undefined; return res; } @@ -287,16 +295,18 @@ export class SignalClient { opts: ConnectOpts, abortSignal?: AbortSignal, /** setting this to true results in dual peer connection mode being used */ - forceV0Path?: boolean, + useV0Path: boolean = false, ): Promise { const unlock = await this.connectionLock.lock(); this.connectOptions = opts; + this.useV0SignalPath = !!useV0Path; + const clientInfo = getClientInfo(); - const params = forceV0Path + const params = useV0Path ? createConnectionParams(token, clientInfo, opts) : createJoinRequestConnectionParams(token, clientInfo, opts); - const rtcUrl = createRtcUrl(url, params, forceV0Path).toString(); + const rtcUrl = createRtcUrl(url, params, useV0Path).toString(); const validateUrl = createValidateUrl(rtcUrl).toString(); return new Promise(async (resolve, reject) => { diff --git a/src/room/RTCEngine.ts b/src/room/RTCEngine.ts index b435a88127..a0204a10a1 100644 --- a/src/room/RTCEngine.ts +++ b/src/room/RTCEngine.ts @@ -267,7 +267,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit opts: SignalOptions, abortSignal?: AbortSignal, /** setting this to true results in dual peer connection mode being used */ - forceV0Path?: boolean, + useV0Path: boolean = false, ): Promise { this.url = url; this.token = token; @@ -277,13 +277,13 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit this.joinAttempts += 1; this.setupSignalClientCallbacks(); - const joinResponse = await this.client.join(url, token, opts, abortSignal, forceV0Path); + const joinResponse = await this.client.join(url, token, opts, abortSignal, useV0Path); this._isClosed = false; this.latestJoinResponse = joinResponse; this.subscriberPrimary = joinResponse.subscriberPrimary; if (!this.pcManager) { - await this.configure(joinResponse, !forceV0Path); + await this.configure(joinResponse, !useV0Path); } // create offer @@ -305,7 +305,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit this.logContext, ); if (this.joinAttempts < this.maxJoinAttempts) { - return this.join(url, token, opts, abortSignal, forceV0Path); + return this.join(url, token, opts, abortSignal, useV0Path); } } else if (e.reason === ConnectionErrorReason.ServiceNotFound) { this.log.warn(`Initial connection failed: ${e.message} – Retrying`); From 87c5687b5538db3455ab839e05d61331ab65ebcd Mon Sep 17 00:00:00 2001 From: lukasIO Date: Tue, 6 Jan 2026 09:57:03 +0100 Subject: [PATCH 2/2] remove redundant conversion --- src/api/SignalClient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/SignalClient.ts b/src/api/SignalClient.ts index 7f8cf359fb..70a76e09b3 100644 --- a/src/api/SignalClient.ts +++ b/src/api/SignalClient.ts @@ -300,7 +300,7 @@ export class SignalClient { const unlock = await this.connectionLock.lock(); this.connectOptions = opts; - this.useV0SignalPath = !!useV0Path; + this.useV0SignalPath = useV0Path; const clientInfo = getClientInfo(); const params = useV0Path