diff --git a/app/products/calls/rtcpeer/index.ts b/app/products/calls/rtcpeer/index.ts index 501410d902..54c8c7e307 100644 --- a/app/products/calls/rtcpeer/index.ts +++ b/app/products/calls/rtcpeer/index.ts @@ -7,12 +7,15 @@ import {EventEmitter} from 'events'; import { MediaStream, MediaStreamTrack, + RTCIceCandidate, RTCPeerConnection, RTCPeerConnectionIceEvent, RTCRtpSender, RTCSessionDescription, } from 'react-native-webrtc'; +import {logDebug, logError} from '@utils/log'; + import type {RTCPeerConfig} from './types'; import type RTCTrackEvent from 'react-native-webrtc/lib/typescript/RTCTrackEvent'; @@ -21,6 +24,7 @@ const rtcConnFailedErr = new Error('rtc connection failed'); export default class RTCPeer extends EventEmitter { private pc: RTCPeerConnection | null; private readonly senders: { [key: string]: RTCRtpSender }; + private candidates: RTCIceCandidate[] = []; public connected: boolean; @@ -113,7 +117,17 @@ export default class RTCPeer extends EventEmitter { try { switch (msg.type) { case 'candidate': - await this.pc.addIceCandidate(msg.candidate); + // It's possible that ICE candidates are received moments before + // we set the initial remote description which would cause an + // error. In such case we queue them up to be added later. + if (this.pc.remoteDescription && this.pc.remoteDescription.type) { + this.pc.addIceCandidate(msg.candidate).catch((err) => { + logError('failed to add candidate', err); + }); + } else { + logDebug('received ice candidate before remote description, queuing...'); + this.candidates.push(msg.candidate); + } break; case 'offer': await this.pc.setRemoteDescription(new RTCSessionDescription(msg)); @@ -122,6 +136,12 @@ export default class RTCPeer extends EventEmitter { break; case 'answer': await this.pc.setRemoteDescription(msg); + for (const candidate of this.candidates) { + logDebug('adding queued ice candidate'); + this.pc.addIceCandidate(candidate).catch((err) => { + logError('failed to add candidate', err); + }); + } break; default: this.emit('error', Error('invalid signaling data received'));