From 353d6bab47ab928aab089e897f5475942fcfa0ac Mon Sep 17 00:00:00 2001 From: Robert Long Date: Fri, 18 Feb 2022 11:35:56 -0800 Subject: [PATCH] Fix and add a test for toDevice ordering --- spec/unit/webrtc/callEventHandler.spec.ts | 83 +++++++++++++++++++++++ src/webrtc/callEventHandler.ts | 13 +++- 2 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 spec/unit/webrtc/callEventHandler.spec.ts diff --git a/spec/unit/webrtc/callEventHandler.spec.ts b/spec/unit/webrtc/callEventHandler.spec.ts new file mode 100644 index 000000000..f1e9bcbaa --- /dev/null +++ b/spec/unit/webrtc/callEventHandler.spec.ts @@ -0,0 +1,83 @@ +import { TestClient } from '../../TestClient'; +import { CallEventHandler } from '../../../src/webrtc/callEventHandler'; +import { MatrixEvent } from '../../../src/models/event'; +import { EventType } from '../../../src/@types/event'; + +describe('CallEventHandler', function() { + let client; + + beforeEach(function() { + client = new TestClient("@alice:foo", "somedevice", "token", undefined, {}); + }); + + afterEach(function() { + client.stop(); + }); + + it('should enforce inbound toDevice message ordering', async function() { + const callEventHandler = new CallEventHandler(client); + + const event1 = new MatrixEvent({ + type: EventType.CallInvite, + content: { + call_id: "123", + seq: 0, + }, + }); + callEventHandler["onToDeviceEvent"](event1); + + expect(callEventHandler.callEventBuffer.length).toBe(1); + expect(callEventHandler.callEventBuffer[0]).toBe(event1); + + const event2 = new MatrixEvent({ + type: EventType.CallCandidates, + content: { + call_id: "123", + seq: 1, + }, + }); + callEventHandler["onToDeviceEvent"](event2); + + expect(callEventHandler.callEventBuffer.length).toBe(2); + expect(callEventHandler.callEventBuffer[1]).toBe(event2); + + const event3 = new MatrixEvent({ + type: EventType.CallCandidates, + content: { + call_id: "123", + seq: 3, + }, + }); + callEventHandler["onToDeviceEvent"](event3); + + expect(callEventHandler.callEventBuffer.length).toBe(2); + expect(callEventHandler.nextSeqByCall.get("123")).toBe(2); + expect(callEventHandler.toDeviceEventBuffers.get("123").length).toBe(1); + + const event4 = new MatrixEvent({ + type: EventType.CallCandidates, + content: { + call_id: "123", + seq: 4, + }, + }); + callEventHandler["onToDeviceEvent"](event4); + + expect(callEventHandler.callEventBuffer.length).toBe(2); + expect(callEventHandler.nextSeqByCall.get("123")).toBe(2); + expect(callEventHandler.toDeviceEventBuffers.get("123").length).toBe(2); + + const event5 = new MatrixEvent({ + type: EventType.CallCandidates, + content: { + call_id: "123", + seq: 2, + }, + }); + callEventHandler["onToDeviceEvent"](event5); + + expect(callEventHandler.callEventBuffer.length).toBe(5); + expect(callEventHandler.nextSeqByCall.get("123")).toBe(5); + expect(callEventHandler.toDeviceEventBuffers.get("123").length).toBe(0); + }); +}); diff --git a/src/webrtc/callEventHandler.ts b/src/webrtc/callEventHandler.ts index ea454a4bd..6c2c126bb 100644 --- a/src/webrtc/callEventHandler.ts +++ b/src/webrtc/callEventHandler.ts @@ -107,7 +107,12 @@ export class CallEventHandler { const buffer = this.toDeviceEventBuffers.get(content.call_id); const index = buffer.findIndex((e) => e.getContent().seq > content.seq); - buffer.splice(index, 0, event); + + if (index === -1) { + buffer.push(event); + } else { + buffer.splice(index, 0, event); + } } else { const callId = content.call_id; this.callEventBuffer.push(event); @@ -115,10 +120,12 @@ export class CallEventHandler { const buffer = this.toDeviceEventBuffers.get(callId); - while (buffer.length > 0 && buffer[0].getContent().seq === content.seq + 1) { - const nextEvent = buffer.pop(); + let nextEvent = buffer && buffer.shift(); + + while (nextEvent && nextEvent.getContent().seq === this.nextSeqByCall.get(callId)) { this.callEventBuffer.push(nextEvent); this.nextSeqByCall.set(callId, nextEvent.getContent().seq + 1); + nextEvent = buffer.shift(); } } };