diff --git a/src/webrtc/call.ts b/src/webrtc/call.ts index 0b1fcd42025..bb00a8c9ccc 100644 --- a/src/webrtc/call.ts +++ b/src/webrtc/call.ts @@ -272,6 +272,7 @@ export class MatrixCall extends EventEmitter { public direction: CallDirection; public ourPartyId: string; public peerConn?: RTCPeerConnection; + public toDeviceSeq = 0; private client: MatrixClient; private forceTURN: boolean; @@ -1984,6 +1985,8 @@ export class MatrixCall extends EventEmitter { }); if (this.opponentDeviceId) { + const toDeviceSeq = this.toDeviceSeq++; + this.emit(CallEvent.SendVoipEvent, { type: "toDevice", eventType, @@ -1994,6 +1997,7 @@ export class MatrixCall extends EventEmitter { device_id: this.client.deviceId, sender_session_id: this.client.getSessionId(), dest_session_id: this.opponentSessionId, + seq: toDeviceSeq, }, }); @@ -2004,6 +2008,7 @@ export class MatrixCall extends EventEmitter { device_id: this.client.deviceId, sender_session_id: this.client.getSessionId(), dest_session_id: this.opponentSessionId, + seq: toDeviceSeq, }, }, }); diff --git a/src/webrtc/callEventHandler.ts b/src/webrtc/callEventHandler.ts index ecbbd51f94f..ea454a4bd97 100644 --- a/src/webrtc/callEventHandler.ts +++ b/src/webrtc/callEventHandler.ts @@ -31,6 +31,8 @@ export class CallEventHandler { calls: Map; callEventBuffer: MatrixEvent[]; candidateEventsByCall: Map>; + nextSeqByCall: Map = new Map(); + toDeviceEventBuffers: Map> = new Map(); private eventBufferPromiseChain?: Promise; @@ -80,7 +82,45 @@ export class CallEventHandler { }; private onToDeviceEvent = (event: MatrixEvent): void => { - this.callEventBuffer.push(event); + const content = event.getContent(); + + if (!content.call_id) { + this.callEventBuffer.push(event); + return; + } + + if (!this.nextSeqByCall.has(content.call_id)) { + this.nextSeqByCall.set(content.call_id, 0); + } + + if (content.seq === undefined) { + this.callEventBuffer.push(event); + return; + } + + const nextSeq = this.nextSeqByCall.get(content.call_id) || 0; + + if (content.seq !== nextSeq) { + if (!this.toDeviceEventBuffers.has(content.call_id)) { + this.toDeviceEventBuffers.set(content.call_id, []); + } + + const buffer = this.toDeviceEventBuffers.get(content.call_id); + const index = buffer.findIndex((e) => e.getContent().seq > content.seq); + buffer.splice(index, 0, event); + } else { + const callId = content.call_id; + this.callEventBuffer.push(event); + this.nextSeqByCall.set(callId, content.seq + 1); + + const buffer = this.toDeviceEventBuffers.get(callId); + + while (buffer.length > 0 && buffer[0].getContent().seq === content.seq + 1) { + const nextEvent = buffer.pop(); + this.callEventBuffer.push(nextEvent); + this.nextSeqByCall.set(callId, nextEvent.getContent().seq + 1); + } + } }; private async evaluateEventBuffer(eventBuffer: MatrixEvent[]) { @@ -122,6 +162,8 @@ export class CallEventHandler { } private async handleCallEvent(event: MatrixEvent) { + this.client.emit("received_voip_event", event); + const content = event.getContent(); const callRoomId = ( event.getRoomId() ||