From 32197ea903d955e036c58d6e6d8e5e9575fb0e00 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Wed, 19 May 2021 15:45:21 +0100 Subject: [PATCH 1/3] Change call event handlers to adapt to undecrypted events --- src/client.js | 4 ++++ src/webrtc/callEventHandler.ts | 28 +++++----------------------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/client.js b/src/client.js index 12bfc6a33..b084c21fc 100644 --- a/src/client.js +++ b/src/client.js @@ -353,6 +353,10 @@ export function MatrixClient(opts) { if (call) { this._callEventHandler = new CallEventHandler(this); this._supportsVoip = true; + // Start listening for calls after the initial sync is done + // We do not need to backfill the call event buffer + // with encrypted events that might never get decrypted + this.once("sync", () => this._callEventHandler.start()); } else { this._callEventHandler = null; } diff --git a/src/webrtc/callEventHandler.ts b/src/webrtc/callEventHandler.ts index 9c4c38b26..0d35f55e3 100644 --- a/src/webrtc/callEventHandler.ts +++ b/src/webrtc/callEventHandler.ts @@ -43,6 +43,9 @@ export class CallEventHandler { // after loading and after we've been offline for a bit. this.callEventBuffer = []; this.candidateEventsByCall = new Map>(); + } + + public start() { this.client.on("sync", this.evaluateEventBuffer); this.client.on("event", this.onEvent); } @@ -85,37 +88,16 @@ export class CallEventHandler { } } - private onEvent = (event: MatrixEvent) => { - // any call events or ones that might be once they're decrypted + private onEvent = async (event: MatrixEvent) => { + await this.client.decryptEventIfNeeded(event); if ( event.getType().indexOf("m.call.") === 0 || event.getType().indexOf("org.matrix.call.") === 0 - || event.isBeingDecrypted() ) { // queue up for processing once all events from this sync have been // processed (see above). this.callEventBuffer.push(event); } - - if (event.isBeingDecrypted() || event.isDecryptionFailure()) { - // add an event listener for once the event is decrypted. - event.once("Event.decrypted", () => { - if (event.getType().indexOf("m.call.") === -1) return; - - if (this.callEventBuffer.includes(event)) { - // we were waiting for that event to decrypt, so recheck the buffer - this.evaluateEventBuffer(); - } else { - // This one wasn't buffered so just run the event handler for it - // straight away - try { - this.handleCallEvent(event); - } catch (e) { - logger.error("Caught exception handling call event", e); - } - } - }); - } } private handleCallEvent(event: MatrixEvent) { From ea1ef3dbec38ff708b63f6d240c7cfececc01c0b Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Wed, 19 May 2021 17:05:20 +0100 Subject: [PATCH 2/3] listen to call event handlers when sync is prepared --- src/client.js | 8 +++++++- src/webrtc/callEventHandler.ts | 33 ++++++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/client.js b/src/client.js index 35493acfe..74ac0d2c1 100644 --- a/src/client.js +++ b/src/client.js @@ -356,7 +356,13 @@ export function MatrixClient(opts) { // Start listening for calls after the initial sync is done // We do not need to backfill the call event buffer // with encrypted events that might never get decrypted - this.once("sync", () => this._callEventHandler.start()); + function startCallEventHandler() { + if (this.isInitialSyncComplete()) { + this._callEventHandler.start(); + this.off("sync", startCallEventHandler); + } + } + this.on("sync", startCallEventHandler); } else { this._callEventHandler = null; } diff --git a/src/webrtc/callEventHandler.ts b/src/webrtc/callEventHandler.ts index 0d35f55e3..c6396bed7 100644 --- a/src/webrtc/callEventHandler.ts +++ b/src/webrtc/callEventHandler.ts @@ -55,10 +55,11 @@ export class CallEventHandler { this.client.removeListener("event", this.onEvent); } - private evaluateEventBuffer = () => { + private evaluateEventBuffer = async () => { if (this.client.getSyncState() === "SYNCING") { - // don't process any events until they are all decrypted - if (this.callEventBuffer.some((e) => e.isBeingDecrypted())) return; + await Promise.all(this.callEventBuffer.map(event => { + this.client.decryptEventIfNeeded(event); + })); const ignoreCallIds = new Set(); // inspect the buffer and mark all calls which have been answered @@ -88,16 +89,38 @@ export class CallEventHandler { } } - private onEvent = async (event: MatrixEvent) => { - await this.client.decryptEventIfNeeded(event); + private onEvent = (event: MatrixEvent) => { + this.client.decryptEventIfNeeded(event); + // any call events or ones that might be once they're decrypted if ( event.getType().indexOf("m.call.") === 0 || event.getType().indexOf("org.matrix.call.") === 0 + || event.isBeingDecrypted() ) { // queue up for processing once all events from this sync have been // processed (see above). this.callEventBuffer.push(event); } + + if (event.isBeingDecrypted() || event.isDecryptionFailure()) { + // add an event listener for once the event is decrypted. + event.once("Event.decrypted", () => { + if (event.getType().indexOf("m.call.") === -1) return; + + if (this.callEventBuffer.includes(event)) { + // we were waiting for that event to decrypt, so recheck the buffer + this.evaluateEventBuffer(); + } else { + // This one wasn't buffered so just run the event handler for it + // straight away + try { + this.handleCallEvent(event); + } catch (e) { + logger.error("Caught exception handling call event", e); + } + } + }); + } } private handleCallEvent(event: MatrixEvent) { From 0c47412c757ec0f51e075af69e44e7d6bdd8446e Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Wed, 19 May 2021 17:15:44 +0100 Subject: [PATCH 3/3] move startEventCallHandler to MatrixClient prototype --- src/client.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/client.js b/src/client.js index 74ac0d2c1..f1074f5b9 100644 --- a/src/client.js +++ b/src/client.js @@ -356,13 +356,7 @@ export function MatrixClient(opts) { // Start listening for calls after the initial sync is done // We do not need to backfill the call event buffer // with encrypted events that might never get decrypted - function startCallEventHandler() { - if (this.isInitialSyncComplete()) { - this._callEventHandler.start(); - this.off("sync", startCallEventHandler); - } - } - this.on("sync", startCallEventHandler); + this.on("sync", this._startCallEventHandler); } else { this._callEventHandler = null; } @@ -4996,6 +4990,13 @@ MatrixClient.prototype.getOpenIdToken = function() { // VoIP operations // =============== +MatrixClient.prototype._startCallEventHandler = function() { + if (this.isInitialSyncComplete()) { + this._callEventHandler.start(); + this.off("sync", this._startCallEventHandler); + } +}; + /** * @param {module:client.callback} callback Optional. * @return {Promise} Resolves: TODO