From edf6d138184d533e44737c3659ea9da8298e9f6a Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 2 Sep 2021 14:41:10 +0100 Subject: [PATCH 1/5] Prevent multiple calls for the same room --- src/CallHandler.tsx | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index 8fd45c49ae..aa0a037423 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -485,9 +485,8 @@ export default class CallHandler extends EventEmitter { this.pause(AudioID.Ringback); } - this.calls.set(mappedRoomId, newCall); - this.emit(CallHandlerEvent.CallsChanged, this.calls); - this.setCallListeners(newCall); + this.addCallForRoom(mappedRoomId, newCall); + this.setCallListeners(call); this.setCallState(newCall, newCall.state); }); call.on(CallEvent.AssertedIdentityChanged, async () => { @@ -521,8 +520,7 @@ export default class CallHandler extends EventEmitter { this.removeCallForRoom(mappedRoomId); mappedRoomId = newMappedRoomId; console.log("Moving call to room " + mappedRoomId); - this.calls.set(mappedRoomId, call); - this.emit(CallHandlerEvent.CallChangeRoom, call); + this.addCallForRoom(mappedRoomId, call, true); } } }); @@ -756,9 +754,7 @@ export default class CallHandler extends EventEmitter { console.log("Current turn creds expire in " + timeUntilTurnCresExpire + " ms"); const call = MatrixClientPeg.get().createCall(mappedRoomId); - console.log("Adding call for room ", roomId); - this.calls.set(roomId, call); - this.emit(CallHandlerEvent.CallsChanged, this.calls); + this.addCallForRoom(roomId, call); if (transferee) { this.transferees[call.callId] = transferee; } @@ -810,6 +806,7 @@ export default class CallHandler extends EventEmitter { return; } + console.log("getting call for room " + room.roomId); if (this.getCallForRoom(room.roomId)) { Modal.createTrackedDialog('Call Handler', 'Existing Call with user', ErrorDialog, { title: _t('Already in call'), @@ -870,9 +867,8 @@ export default class CallHandler extends EventEmitter { } Analytics.trackEvent('voip', 'receiveCall', 'type', call.type); - console.log("Adding call for room ", mappedRoomId); - this.calls.set(mappedRoomId, call); - this.emit(CallHandlerEvent.CallsChanged, this.calls); + + this.addCallForRoom(mappedRoomId, call); this.setCallListeners(call); // Explicitly handle first state change this.onCallStateChanged(call.state, null, call); @@ -1150,4 +1146,21 @@ export default class CallHandler extends EventEmitter { messaging.transport.send(ElementWidgetActions.HangupCall, {}); }); } + + private addCallForRoom(roomId: string, call: MatrixCall, changedRooms=false): void { + if (this.calls.has(roomId)) { + console.log(`Couldn't add call to room ${roomId}: already have a call for this room`); + throw new Error("Already have a call for room " + roomId); + } + + console.log("setting call for room " + roomId); + this.calls.set(roomId, call); + + // Should we always emit CallsChanged too? + if (changedRooms) { + this.emit(CallHandlerEvent.CallChangeRoom, call); + } else { + this.emit(CallHandlerEvent.CallsChanged, this.calls); + } + } } From cd8e7e3076c3c69d31b56d45b4542fdcf983924e Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 2 Sep 2021 15:51:44 +0100 Subject: [PATCH 2/5] Move error dialog to the new check So we just check for an existing call in one place where it doesn't race --- src/CallHandler.tsx | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index aa0a037423..adcc9024e5 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -754,7 +754,15 @@ export default class CallHandler extends EventEmitter { console.log("Current turn creds expire in " + timeUntilTurnCresExpire + " ms"); const call = MatrixClientPeg.get().createCall(mappedRoomId); - this.addCallForRoom(roomId, call); + try { + this.addCallForRoom(roomId, call); + } catch (e) { + Modal.createTrackedDialog('Call Handler', 'Existing Call with user', ErrorDialog, { + title: _t('Already in call'), + description: _t("You're already in a call with this person."), + }); + return; + } if (transferee) { this.transferees[call.callId] = transferee; } @@ -806,14 +814,8 @@ export default class CallHandler extends EventEmitter { return; } - console.log("getting call for room " + room.roomId); - if (this.getCallForRoom(room.roomId)) { - Modal.createTrackedDialog('Call Handler', 'Existing Call with user', ErrorDialog, { - title: _t('Already in call'), - description: _t("You're already in a call with this person."), - }); - return; - } + // We leave the check for whether there's already a call in this room until later, + // otherwise it can race. const members = room.getJoinedMembers(); if (members.length <= 1) { From f2758f9ce53ef7331e3f88863b32222f02a941d1 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 2 Sep 2021 18:41:26 +0100 Subject: [PATCH 3/5] Fix glare --- src/CallHandler.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index adcc9024e5..002a4f821d 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -485,8 +485,9 @@ export default class CallHandler extends EventEmitter { this.pause(AudioID.Ringback); } + this.removeCallForRoom(mappedRoomId); this.addCallForRoom(mappedRoomId, newCall); - this.setCallListeners(call); + this.setCallListeners(newCall); this.setCallState(newCall, newCall.state); }); call.on(CallEvent.AssertedIdentityChanged, async () => { From 1a0365f528398fd5a79fa5eee487c4c246bfe199 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 2 Sep 2021 19:00:30 +0100 Subject: [PATCH 4/5] i18n --- src/i18n/strings/en_EN.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 2cb0a546aa..0af0b971d2 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -52,12 +52,12 @@ "A microphone and webcam are plugged in and set up correctly": "A microphone and webcam are plugged in and set up correctly", "Permission is granted to use the webcam": "Permission is granted to use the webcam", "No other application is using the webcam": "No other application is using the webcam", + "Already in call": "Already in call", + "You're already in a call with this person.": "You're already in a call with this person.", "VoIP is unsupported": "VoIP is unsupported", "You cannot place VoIP calls in this browser.": "You cannot place VoIP calls in this browser.", "Too Many Calls": "Too Many Calls", "You've reached the maximum number of simultaneous calls.": "You've reached the maximum number of simultaneous calls.", - "Already in call": "Already in call", - "You're already in a call with this person.": "You're already in a call with this person.", "You cannot place a call with yourself.": "You cannot place a call with yourself.", "Unable to look up phone number": "Unable to look up phone number", "There was an error looking up the phone number": "There was an error looking up the phone number", From 7b52cca8d36c2b4e8bc27de84d7c7faa897f003d Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 3 Sep 2021 10:38:39 +0100 Subject: [PATCH 5/5] Formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Šimon Brandner --- src/CallHandler.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index 002a4f821d..fe938c9929 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -1150,7 +1150,7 @@ export default class CallHandler extends EventEmitter { }); } - private addCallForRoom(roomId: string, call: MatrixCall, changedRooms=false): void { + private addCallForRoom(roomId: string, call: MatrixCall, changedRooms = false): void { if (this.calls.has(roomId)) { console.log(`Couldn't add call to room ${roomId}: already have a call for this room`); throw new Error("Already have a call for room " + roomId);