From a57d5582f0a93ba52b53b1804ddea5b7f91d277c Mon Sep 17 00:00:00 2001 From: adel-signal Date: Fri, 3 May 2024 09:01:59 -0700 Subject: [PATCH] calling: update setTurnServerOverride to support overriding all ice server fields --- ts/services/calling.ts | 74 +++++++++++++++++++++++++--------------- ts/windows/main/start.ts | 22 ++++++++---- 2 files changed, 61 insertions(+), 35 deletions(-) diff --git a/ts/services/calling.ts b/ts/services/calling.ts index a6c4b7a4a69d..b22fb4ccbf9f 100644 --- a/ts/services/calling.ts +++ b/ts/services/calling.ts @@ -82,6 +82,7 @@ import * as durations from '../util/durations'; import { clearTimeoutIfNecessary } from '../util/clearTimeoutIfNecessary'; import { fetchMembershipProof, getMembershipList } from '../groups'; import type { ProcessedEnvelope } from '../textsecure/Types.d'; +import type { GetIceServersResultType } from '../textsecure/WebAPI'; import { missingCaseError } from '../util/missingCaseError'; import { normalizeGroupCallTimestamp } from '../util/ringrtc/normalizeGroupCallTimestamp'; import { @@ -317,7 +318,7 @@ export class CallingClass { public _sfuUrl?: string; - public _iceServerOverride?: string; + public _iceServerOverride?: GetIceServersResultType | string; private lastMediaDeviceSettings?: MediaDeviceSettings; @@ -2658,12 +2659,39 @@ export class CallingClass { } private async handleStartCall(call: Call): Promise { + type IceServer = { + username?: string; + password?: string; + hostname?: string; + urls: Array; + }; + + function iceServerConfigToList( + iceServerConfig: GetIceServersResultType + ): Array { + return [ + { + hostname: iceServerConfig.hostname ?? '', + username: iceServerConfig.username, + password: iceServerConfig.password, + urls: (iceServerConfig.urlsWithIps ?? []).slice(), + }, + { + hostname: '', + username: iceServerConfig.username, + password: iceServerConfig.password, + urls: (iceServerConfig.urls ?? []).slice(), + }, + ]; + } + if (!window.textsecure.messaging) { log.error('handleStartCall: offline!'); return false; } - const iceServer = await window.textsecure.messaging.server.getIceServers(); + const iceServerConfig = + await window.textsecure.messaging.server.getIceServers(); const shouldRelayCalls = window.Events.getAlwaysRelayCalls(); @@ -2676,33 +2704,23 @@ export class CallingClass { // If the peer is not in the user's system contacts, force IP hiding. const isContactUntrusted = !isInSystemContacts(conversation.attributes); + // proritize ice servers with IPs to avoid DNS // only include hostname with urlsWithIps - const iceServers = this._iceServerOverride - ? [ - { - hostname: ICE_SERVER_IS_IP_LIKE.test(this._iceServerOverride) - ? iceServer.hostname - : '', - username: iceServer.username, - password: iceServer.password, - urls: [this._iceServerOverride.toString()], - }, - ] - : // proritize ice servers with IPs to avoid DNS - [ - { - hostname: iceServer.hostname ?? '', - username: iceServer.username, - password: iceServer.password, - urls: (iceServer.urlsWithIps ?? []).slice(), - }, - { - hostname: '', - username: iceServer.username, - password: iceServer.password, - urls: (iceServer.urls ?? []).slice(), - }, - ]; + let iceServers = iceServerConfigToList(iceServerConfig); + + if (this._iceServerOverride) { + if (typeof this._iceServerOverride === 'string') { + if (ICE_SERVER_IS_IP_LIKE.test(this._iceServerOverride)) { + iceServers[0].urls = [this._iceServerOverride]; + iceServers = [iceServers[0]]; + } else { + iceServers[1].urls = [this._iceServerOverride]; + iceServers = [iceServers[1]]; + } + } else { + iceServers = iceServerConfigToList(this._iceServerOverride); + } + } const callSettings = { iceServers, diff --git a/ts/windows/main/start.ts b/ts/windows/main/start.ts index 789160b7f9d8..c685bb2748ea 100644 --- a/ts/windows/main/start.ts +++ b/ts/windows/main/start.ts @@ -13,7 +13,10 @@ import './phase3-post-signal'; import './phase4-test'; import '../../backbone/reliable_trigger'; -import type { CdsLookupOptionsType } from '../../textsecure/WebAPI'; +import type { + CdsLookupOptionsType, + GetIceServersResultType, +} from '../../textsecure/WebAPI'; import type { FeatureFlagType } from '../../window.d'; import type { StorageAccessType } from '../../types/Storage.d'; import { start as startConversationController } from '../../ConversationController'; @@ -71,13 +74,18 @@ if (!isProduction(window.SignalContext.getVersion())) { setSfuUrl: (url: string) => { window.Signal.Services.calling._sfuUrl = url; }, - setIceServerOverride: (url: string) => { - if (!/(turn|turns|stun):.*]/.test(url)) { - log.warn( - 'Override url should be prefixed with `turn:`, `turns:`, or `stun:` else override may not work' - ); + setIceServerOverride: ( + override: GetIceServersResultType | string | undefined + ) => { + if (typeof override === 'string') { + if (!/(turn|turns|stun):.*/.test(override)) { + log.warn( + 'Override url should be prefixed with `turn:`, `turns:`, or `stun:` else override may not work' + ); + } } - window.Signal.Services.calling._iceServerOverride = url; + + window.Signal.Services.calling._iceServerOverride = override; }, sqlCall: (name: string, ...args: ReadonlyArray) => ipcInvoke(name, args),