From 379ec8eae82a7477dad142cca11bad6c7660981b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Calvi=C3=B1o=20S=C3=A1nchez?= Date: Sun, 20 Nov 2022 01:47:55 +0100 Subject: [PATCH 1/3] Fix call state when join call response is received after signaling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a call is joined the call flags of the local participant change, so this causes a signaling message to be sent by the server. When the HPB is used the signaling message is sent through a WebSocket, which is already connected before joining the call. Therefore, in some cases the signaling message can be received through the WebSocket even before the response to the HTTP "joinCall" request. If there are other participants in the call the call state is changed to "IN_CONVERSATION" when the signaling message is processed. However, in the case described above the call state was then set to "JOINED", which automatically traverses to "CONNECTION_TIMEOUT" if no other call state was set in 45 seconds. Due to all this the call was joined and the connections with the other participants were established, but they were not visible in the UI (although they could be heard) and after 45 seconds the call was left. To prevent that now the call state is changed to "JOINED" if it was not already changed to "IN_CONVERSATION" in the meantime. Signed-off-by: Daniel Calviño Sánchez --- .../main/java/com/nextcloud/talk/activities/CallActivity.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java index 497899e31..a3a3f6d1e 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java +++ b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java @@ -1442,7 +1442,9 @@ public class CallActivity extends CallBaseActivity { @Override public void onNext(@io.reactivex.annotations.NonNull GenericOverall genericOverall) { if (currentCallStatus != CallStatus.LEAVING) { - setCallState(CallStatus.JOINED); + if (currentCallStatus != CallStatus.IN_CONVERSATION) { + setCallState(CallStatus.JOINED); + } ApplicationWideCurrentRoomHolder.getInstance().setInCall(true); ApplicationWideCurrentRoomHolder.getInstance().setDialing(false); From 8cdcc63687a7d7c3fdd8204e7071dfc4fd4df01b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Calvi=C3=B1o=20S=C3=A1nchez?= Date: Sun, 20 Nov 2022 01:48:36 +0100 Subject: [PATCH 2/3] Return without further processing if the call is remotely ended MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the call is hung up with a view shutdown (which finishes the activity) there is no need to do any further processing on the participant list. Signed-off-by: Daniel Calviño Sánchez --- .../main/java/com/nextcloud/talk/activities/CallActivity.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java index a3a3f6d1e..90bd1179b 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java +++ b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java @@ -1879,6 +1879,8 @@ public class CallActivity extends CallBaseActivity { if (inCallFlag == 0 && currentCallStatus != CallStatus.LEAVING && ApplicationWideCurrentRoomHolder.getInstance().isInCall()) { Log.d(TAG, "Most probably a moderator ended the call for all."); hangup(true); + + return; } } } From 331bf49f7392032759f989012206c2093f74ef9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Calvi=C3=B1o=20S=C3=A1nchez?= Date: Sun, 20 Nov 2022 01:51:29 +0100 Subject: [PATCH 3/3] Fix processing of participant list on reconnections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the HPB is used the signaling messages can be received even when the local participant is not currently in the call (for example, when starting the call timed out without other participant joining, or when reconnecting due to the publisher connection failing). Therefore if the local participant is not in the call it should not try to establish a connection with the other participants and disconnect them instead. Moreover, if the connection is tried to be established when not in the call the HPB will prevent that, and the PeerConnectionWrapper will stay in a limbo state waiting for an offer to be sent. If the local participant then joins the call the PeerConnectionWrapper will already exist for the other participants, so no new connections will be created, but those previous connections will never be finally established. Additionally, as the signaling messages can be received before the join call response the participant list could be received while the call state is "RECONNECTING" or "PUBLISHER_FAILED". In those cases, as long as the local participant is already in the call, the participant list should be processed as if the call state was already "JOINED" (otherwise the connections were not established either). For simplicity the participant list is now ignored only when the call state is "LEAVING"; this means that the participant list would be also processed in the "CONNECTION_TIMEOUT" state, but the signaling message should not be received anyway in that case. Signed-off-by: Daniel Calviño Sánchez --- .../nextcloud/talk/activities/CallActivity.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java index 90bd1179b..58cb13ea0 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java +++ b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java @@ -1853,6 +1853,8 @@ public class CallActivity extends CallBaseActivity { Log.d(TAG, " currentSessionId is " + currentSessionId); + boolean isSelfInCall = false; + for (HashMap participant : users) { long inCallFlag = (long) participant.get("inCall"); if (!participant.get("sessionId").equals(currentSessionId)) { @@ -1876,6 +1878,7 @@ public class CallActivity extends CallBaseActivity { userIdsBySessionId.put(participant.get("sessionId").toString(), userId); } else { Log.d(TAG, " inCallFlag of currentSessionId: " + inCallFlag); + isSelfInCall = inCallFlag != 0; if (inCallFlag == 0 && currentCallStatus != CallStatus.LEAVING && ApplicationWideCurrentRoomHolder.getInstance().isInCall()) { Log.d(TAG, "Most probably a moderator ended the call for all."); hangup(true); @@ -1891,6 +1894,17 @@ public class CallActivity extends CallBaseActivity { } } + if (!isSelfInCall) { + Log.d(TAG, "Self not in call, disconnecting from all other sessions"); + + for (String sessionId : oldSessions) { + Log.d(TAG, " oldSession that will be removed is: " + sessionId); + endPeerConnection(sessionId, false); + } + + return; + } + // Calculate sessions that left the call List disconnectedSessions = new ArrayList<>(oldSessions); disconnectedSessions.removeAll(newSessions); @@ -1898,7 +1912,7 @@ public class CallActivity extends CallBaseActivity { // Calculate sessions that join the call newSessions.removeAll(oldSessions); - if (!isConnectionEstablished() && currentCallStatus != CallStatus.CONNECTING) { + if (currentCallStatus == CallStatus.LEAVING) { return; }