From c6be52f3c43a98b92eaa5917471a80cb787b5a75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Calvi=C3=B1o=20S=C3=A1nchez?= Date: Wed, 24 Aug 2022 04:27:26 +0200 Subject: [PATCH 1/4] Emit "leaveCall" event even if the request to leave the call fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a call is left the UI always changes to the "not-in-a-call" state. However, if leaving the call fails the signaling did not emit the "leaveCall" event, so the WebRTC connections were not stopped due to leaving the call, nor they were left later when the signaling sent the updated list of participants, as the participant did not leave the call from the point of view of the server. Even if leaving the call fails in the server the call should be locally left when the user requests it, so now "leaveCall" is emitted even if leaving the call failed. Signed-off-by: Daniel Calviño Sánchez --- src/utils/signaling.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/utils/signaling.js b/src/utils/signaling.js index 56c98faafaf..31e8ecb56c2 100644 --- a/src/utils/signaling.js +++ b/src/utils/signaling.js @@ -338,8 +338,14 @@ Signaling.Base.prototype.leaveCall = function(token, keepToken, all = false) { } }.bind(this)) .catch(function() { + this._trigger('leaveCall', [token, keepToken]) reject(new Error()) - }) + // We left the current call. + if (!keepToken && token === this.currentCallToken) { + this.currentCallToken = null + this.currentCallFlags = null + } + }.bind(this)) }) } From b8df78c80a1c281c1759968fa80aa69a58bec6fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Calvi=C3=B1o=20S=C3=A1nchez?= Date: Wed, 24 Aug 2022 17:15:34 +0200 Subject: [PATCH 2/4] Remove unneeded assignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When "usersChanged(signaling, [], previousUsersInRoom)" is called "previousUsersInRoom" is assigned to the difference with itself and, therefore, to an empty array, so there is no need to explicitly do it afterwards. Signed-off-by: Daniel Calviño Sánchez --- src/utils/webrtc/webrtc.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/utils/webrtc/webrtc.js b/src/utils/webrtc/webrtc.js index 2b6ae2dbad8..b6f21db60b5 100644 --- a/src/utils/webrtc/webrtc.js +++ b/src/utils/webrtc/webrtc.js @@ -926,7 +926,6 @@ export default function initWebRtc(signaling, _callParticipantCollection, _local usersChanged(signaling, [], previousUsersInRoom) usersInCallMapping = {} - previousUsersInRoom = [] // Reconnects with a new session id will trigger "usersChanged" // with the users in the room and that will re-establish the @@ -1710,7 +1709,6 @@ export default function initWebRtc(signaling, _callParticipantCollection, _local usersChanged(signaling, [], previousUsersInRoom) usersInCallMapping = {} - previousUsersInRoom = [] }) return webrtc From aa22e6bd5e0b459450a987e96802541f7145b012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Calvi=C3=B1o=20S=C3=A1nchez?= Date: Wed, 24 Aug 2022 17:24:56 +0200 Subject: [PATCH 3/4] Clear call related data immediately when leaving call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a call is left the peer connections are immediately ended. However, the data of the participants (like the call state), the CallParticipantModels as well as the timers to retry failed connections were cleared once the signaling message updating the current participant state to disconnected was received. If leaving the call failed in the server that message will not be received, so pending connections were retried even if no longer in the call, and when joining again a previous model could be reused, leading to different issues. Due to that the call related data is now immediately cleared when the call is left, no matter if the signaling message about leaving the call is then received or not (and, if it is, nothing will happen as the data was already cleared). Signed-off-by: Daniel Calviño Sánchez --- src/utils/webrtc/webrtc.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/utils/webrtc/webrtc.js b/src/utils/webrtc/webrtc.js index b6f21db60b5..f4894f14aa0 100644 --- a/src/utils/webrtc/webrtc.js +++ b/src/utils/webrtc/webrtc.js @@ -604,13 +604,21 @@ export default function initWebRtc(signaling, _callParticipantCollection, _local // stopped, as the current own session is not passed along with the // sessions of the other participants as "disconnected" to // "usersChanged" when a call is left. - // The peer, on the other hand, is automatically ended by "leaveCall" - // below. + // The peer, on the other hand, is ended by the calls below. if (ownPeer && delayedConnectionToPeer[ownPeer.id]) { clearInterval(delayedConnectionToPeer[ownPeer.id]) delete delayedConnectionToPeer[ownPeer.id] } + // Besides stopping the media "leaveCall" would end the peers, but it + // does not stop the timers for pending connections, removes models or + // clears the call data, so this needs to be explicitly done here + // instead. + selfInCall = PARTICIPANT.CALL_FLAG.DISCONNECTED + + usersChanged(signaling, [], previousUsersInRoom) + usersInCallMapping = {} + webrtc.leaveCall() }) From 4c8d16a3f48c6f7b77c94771c6aee6970578fa0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Calvi=C3=B1o=20S=C3=A1nchez?= Date: Wed, 24 Aug 2022 17:26:38 +0200 Subject: [PATCH 4/4] Ignore call signaling messages when not in a call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a participant was not in the call but received an offer it was ignored to avoid establishing a connection. However, all the other call signaling messages were still processed. Due to this, if a participant leaves the call but that fails in the server that participant still receives all the participant updates (which also list that participant as still in the call) and therefore that participant tries to establish a connection with the other participants. To prevent that now all call signaling messages are ignored when the local participant is not in the call. Due to this the call signaling message that changes the state from the local participant to disconnected is now ignored as well, although that should not be a problem given that (since the previous commmit) the call related data is immediately cleared when the call is left, without waiting for the signaling message. Signed-off-by: Daniel Calviño Sánchez --- src/utils/webrtc/webrtc.js | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/utils/webrtc/webrtc.js b/src/utils/webrtc/webrtc.js index f4894f14aa0..c84e83ce555 100644 --- a/src/utils/webrtc/webrtc.js +++ b/src/utils/webrtc/webrtc.js @@ -52,7 +52,7 @@ let ownScreenPeer = null let selfInCall = PARTICIPANT.CALL_FLAG.DISCONNECTED // Special variable to know when the local user explicitly joined and left the // call; this is needed to know when the user was kicked out from the call by a -// moderator. +// moderator and discard signaling events if received when not in the call. let localUserInCall = false const delayedConnectionToPeer = [] let callParticipantCollection = null @@ -531,12 +531,20 @@ export default function initWebRtc(signaling, _callParticipantCollection, _local localCallParticipantModel = _localCallParticipantModel signaling.on('usersLeft', function(users) { + if (!localUserInCall) { + return + } + users.forEach(function(user) { delete usersInCallMapping[user] }) usersChanged(signaling, [], users) }) signaling.on('usersChanged', function(users) { + if (!localUserInCall) { + return + } + users.forEach(function(user) { const sessionId = user.sessionId || user.sessionid usersInCallMapping[sessionId] = user @@ -544,11 +552,19 @@ export default function initWebRtc(signaling, _callParticipantCollection, _local usersInCallChanged(signaling, usersInCallMapping) }) signaling.on('allUsersChangedInCallToDisconnected', function() { + if (!localUserInCall) { + return + } + // "End meeting for all" was used, we don't have a user list but everyone disconnects from the call usersInCallMapping = {} usersInCallChanged(signaling, usersInCallMapping) }) signaling.on('participantFlagsChanged', function(event) { + if (!localUserInCall) { + return + } + /** * event { * roomid: "1609407087", @@ -567,6 +583,10 @@ export default function initWebRtc(signaling, _callParticipantCollection, _local } }) signaling.on('usersInRoom', function(users) { + if (!localUserInCall) { + return + } + usersInCallMapping = {} users.forEach(function(user) { const sessionId = user.sessionId || user.sessionid @@ -623,6 +643,14 @@ export default function initWebRtc(signaling, _callParticipantCollection, _local }) signaling.on('message', function(message) { + if (!localUserInCall) { + console.debug('Message received when not in the call, ignore', message.type, message) + + message.type = 'message-to-ignore' + + return + } + if (message.type === 'answer' && message.roomType === 'video' && delayedConnectionToPeer[message.from]) { clearInterval(delayedConnectionToPeer[message.from]) delete delayedConnectionToPeer[message.from] @@ -652,12 +680,6 @@ export default function initWebRtc(signaling, _callParticipantCollection, _local delete delayedConnectionToPeer[message.from] } - if (!selfInCall) { - console.debug('Offer received when not in the call, ignore') - - message.type = 'offer-to-ignore' - } - // MCU screen offers do not include the "broadcaster" property, // which is expected by SimpleWebRTC in screen offers from a remote // peer, so it needs to be explicitly added.