From afd894a3a5320ffe34c8ddd8aaa0456b4c2aab79 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Thu, 20 Jul 2023 15:58:34 +0200 Subject: [PATCH] Calls: Only send relay ICE candidates if p2p is disabled (#3564) --- src/api/gramjs/apiBuilders/calls.ts | 2 +- src/api/types/calls.ts | 1 + src/global/actions/apiUpdaters/calls.async.ts | 7 ++++++- src/lib/secret-sauce/p2p.ts | 14 ++++++++++--- src/lib/secret-sauce/utils.ts | 21 +++++++++++++++++++ 5 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/api/gramjs/apiBuilders/calls.ts b/src/api/gramjs/apiBuilders/calls.ts index 633867acc..066257c5e 100644 --- a/src/api/gramjs/apiBuilders/calls.ts +++ b/src/api/gramjs/apiBuilders/calls.ts @@ -140,7 +140,7 @@ export function buildPhoneCall(call: GramJs.TypePhoneCall): ApiPhoneCall { gAOrB: Array.from(gAOrB), keyFingerprint: keyFingerprint.toString(), startDate, - p2pAllowed, + isP2pAllowed: Boolean(p2pAllowed), connections: connections.map(buildApiCallConnection).filter(Boolean) as ApiPhoneCallConnection[], }; } diff --git a/src/api/types/calls.ts b/src/api/types/calls.ts index 5541bd540..72d33c867 100644 --- a/src/api/types/calls.ts +++ b/src/api/types/calls.ts @@ -45,6 +45,7 @@ export interface ApiPhoneCall { adminId?: string; participantId?: string; isVideo?: boolean; + isP2pAllowed?: boolean; date?: number; startDate?: number; receiveDate?: number; diff --git a/src/global/actions/apiUpdaters/calls.async.ts b/src/global/actions/apiUpdaters/calls.async.ts index b189e3721..4e447e2a7 100644 --- a/src/global/actions/apiUpdaters/calls.async.ts +++ b/src/global/actions/apiUpdaters/calls.async.ts @@ -169,7 +169,12 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => { })(); } void joinPhoneCall( - connections, actions.sendSignalingData, isOutgoing, Boolean(call?.isVideo), actions.apiUpdate, + connections, + actions.sendSignalingData, + isOutgoing, + Boolean(call?.isVideo), + Boolean(call.isP2pAllowed), + actions.apiUpdate, ); } diff --git a/src/lib/secret-sauce/p2p.ts b/src/lib/secret-sauce/p2p.ts index d809f1ef3..d05063f4f 100644 --- a/src/lib/secret-sauce/p2p.ts +++ b/src/lib/secret-sauce/p2p.ts @@ -5,8 +5,8 @@ import type { MediaContent, MediaStateMessage, P2pMessage } from './p2pMessage'; import { fromTelegramSource, IS_ECHO_CANCELLATION_SUPPORTED, - IS_NOISE_SUPPRESSION_SUPPORTED, - p2pPayloadTypeToConference, + IS_NOISE_SUPPRESSION_SUPPORTED, isRelayAddress, + p2pPayloadTypeToConference, removeRelatedAddress, } from './utils'; import buildSdp, { Conference } from './buildSdp'; import { getUserStreams, StreamType } from './secretsauce'; @@ -174,6 +174,7 @@ export async function joinPhoneCall( emitSignalingData: (data: P2pMessage) => void, isOutgoing: boolean, shouldStartVideo: boolean, + isP2p: boolean, onUpdate: (...args: any[]) => void, ) { const conn = new RTCPeerConnection({ @@ -200,10 +201,17 @@ export async function joinPhoneCall( conn.onicecandidate = (e) => { if (!e.candidate) return; + const { candidate } = e.candidate; + if(!isP2p && !isRelayAddress(candidate)) { + return; + } + + const candidateWithoutRelatedAddress = !isP2p ? removeRelatedAddress(candidate) : candidate; + emitSignalingData({ '@type': 'Candidates', candidates: [{ - sdpString: e.candidate.candidate, + sdpString: candidateWithoutRelatedAddress, }], }); }; diff --git a/src/lib/secret-sauce/utils.ts b/src/lib/secret-sauce/utils.ts index 63c73b900..b49e745fe 100644 --- a/src/lib/secret-sauce/utils.ts +++ b/src/lib/secret-sauce/utils.ts @@ -39,6 +39,27 @@ export function p2pPayloadTypeToConference(p: P2PPayloadType): PayloadType { }; } +export function isRelayAddress(candidate: string) { + const parts = candidate.split(' '); + return parts.some((part) => part === 'relay'); +} + +export function removeRelatedAddress(candidate: string) { + const parts = candidate.split(' '); + + const raddrIndex = parts.indexOf('raddr'); + if (raddrIndex !== -1) { + parts.splice(raddrIndex, 2); + } + + const rportIndex = parts.indexOf('rport'); + if (rportIndex !== -1) { + parts.splice(rportIndex, 2); + } + + return parts.join(' '); +} + export const THRESHOLD = 0.1; export const IS_SCREENSHARE_SUPPORTED = 'getDisplayMedia' in (navigator?.mediaDevices || {});