Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/spreed.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoas Schilling <213943+nickvergessen@users.noreply.github.com>2022-08-26 22:37:53 +0300
committerGitHub <noreply@github.com>2022-08-26 22:37:53 +0300
commit4b27d7fd3a32de74e827b29fb089a91e9525a435 (patch)
tree5f358ae717644ee41cb27d9fef9a9705b37db1c8
parent510575da45d37a48054b3c01a22bccf893ac1cbe (diff)
parent48443886b30f55a598eca1980ccbdb0da088a1d7 (diff)
Merge pull request #7806 from nextcloud/backport/7801/stable24
[stable24] Fix leaving room in one session causing call to be partially left in another session
-rw-r--r--lib/Controller/RoomController.php2
-rw-r--r--lib/Events/DuplicatedParticipantEvent.php34
-rw-r--r--lib/Service/ParticipantService.php20
-rw-r--r--lib/Signaling/Listener.php9
-rw-r--r--tests/php/Signaling/BackendNotifierTest.php79
5 files changed, 131 insertions, 13 deletions
diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php
index 5a67f9904..ecaa7aeb0 100644
--- a/lib/Controller/RoomController.php
+++ b/lib/Controller/RoomController.php
@@ -1379,7 +1379,7 @@ class RoomController extends AEnvironmentAwareController {
$this->participantService->changeInCall($room, $previousParticipant, Participant::FLAG_DISCONNECTED);
}
- $this->participantService->leaveRoomAsSession($room, $previousParticipant);
+ $this->participantService->leaveRoomAsSession($room, $previousParticipant, true);
}
$user = $this->userManager->get($this->userId);
diff --git a/lib/Events/DuplicatedParticipantEvent.php b/lib/Events/DuplicatedParticipantEvent.php
new file mode 100644
index 000000000..8b7f754b4
--- /dev/null
+++ b/lib/Events/DuplicatedParticipantEvent.php
@@ -0,0 +1,34 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2022 Daniel Calviño Sánchez <danxuliu@gmail.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Talk\Events;
+
+use OCA\Talk\Participant;
+use OCA\Talk\Room;
+
+class DuplicatedParticipantEvent extends ParticipantEvent {
+ public function __construct(Room $room,
+ Participant $participant) {
+ parent::__construct($room, $participant);
+ }
+}
diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php
index 7d7582315..cbd692e35 100644
--- a/lib/Service/ParticipantService.php
+++ b/lib/Service/ParticipantService.php
@@ -33,6 +33,7 @@ use OCA\Talk\Events\AddParticipantsEvent;
use OCA\Talk\Events\AttendeesAddedEvent;
use OCA\Talk\Events\AttendeesRemovedEvent;
use OCA\Talk\Events\ChatEvent;
+use OCA\Talk\Events\DuplicatedParticipantEvent;
use OCA\Talk\Events\EndCallForEveryoneEvent;
use OCA\Talk\Events\JoinRoomGuestEvent;
use OCA\Talk\Events\JoinRoomUserEvent;
@@ -687,23 +688,22 @@ class ParticipantService {
}
}
- public function leaveRoomAsSession(Room $room, Participant $participant): void {
- $event = new ParticipantEvent($room, $participant);
+ public function leaveRoomAsSession(Room $room, Participant $participant, bool $duplicatedParticipant = false): void {
+ if ($duplicatedParticipant) {
+ $event = new DuplicatedParticipantEvent($room, $participant);
+ } else {
+ $event = new ParticipantEvent($room, $participant);
+ }
$this->dispatcher->dispatch(Room::EVENT_BEFORE_ROOM_DISCONNECT, $event);
$session = $participant->getSession();
if ($session instanceof Session) {
- $dispatchLeaveCallEvents = $session->getInCall() !== Participant::FLAG_DISCONNECTED;
- if ($dispatchLeaveCallEvents) {
- $event = new ModifyParticipantEvent($room, $participant, 'inCall', Participant::FLAG_DISCONNECTED, $session->getInCall());
- $this->dispatcher->dispatch(Room::EVENT_BEFORE_SESSION_LEAVE_CALL, $event);
+ $isInCall = $session->getInCall() !== Participant::FLAG_DISCONNECTED;
+ if ($isInCall) {
+ $this->changeInCall($room, $participant, Participant::FLAG_DISCONNECTED);
}
$this->sessionMapper->delete($session);
-
- if ($dispatchLeaveCallEvents) {
- $this->dispatcher->dispatch(Room::EVENT_AFTER_SESSION_LEAVE_CALL, $event);
- }
} else {
$this->sessionMapper->deleteByAttendeeId($participant->getAttendee()->getId());
}
diff --git a/lib/Signaling/Listener.php b/lib/Signaling/Listener.php
index 338eb48c0..6155f5fdc 100644
--- a/lib/Signaling/Listener.php
+++ b/lib/Signaling/Listener.php
@@ -27,6 +27,7 @@ use OCA\Talk\Chat\ChatManager;
use OCA\Talk\Config;
use OCA\Talk\Events\AddParticipantsEvent;
use OCA\Talk\Events\ChatEvent;
+use OCA\Talk\Events\DuplicatedParticipantEvent;
use OCA\Talk\Events\EndCallForEveryoneEvent;
use OCA\Talk\Events\ModifyEveryoneEvent;
use OCA\Talk\Events\ModifyParticipantEvent;
@@ -252,9 +253,13 @@ class Listener {
$sessionIds = [];
if ($event->getParticipant()->getSession()) {
- // Only for guests and self-joined users disconnecting is "leaving" and therefor should trigger a disinvite
+ // If a previous duplicated session is being removed it must be
+ // notified to the external signaling server. Otherwise only for
+ // guests and self-joined users disconnecting is "leaving" and
+ // therefor should trigger a disinvite.
$attendeeParticipantType = $event->getParticipant()->getAttendee()->getParticipantType();
- if ($attendeeParticipantType === Participant::GUEST
+ if ($event instanceof DuplicatedParticipantEvent
+ || $attendeeParticipantType === Participant::GUEST
|| $attendeeParticipantType === Participant::GUEST_MODERATOR) {
$sessionIds[] = $event->getParticipant()->getSession()->getSessionId();
$notifier->roomSessionsRemoved($event->getRoom(), $sessionIds);
diff --git a/tests/php/Signaling/BackendNotifierTest.php b/tests/php/Signaling/BackendNotifierTest.php
index 3bb2fc386..fd2be706b 100644
--- a/tests/php/Signaling/BackendNotifierTest.php
+++ b/tests/php/Signaling/BackendNotifierTest.php
@@ -324,6 +324,46 @@ class BackendNotifierTest extends TestCase {
$this->assertNoMessageOfTypeWasSent($room, 'disinvite');
}
+ public function testRoomDisinviteOnLeaveOfNormalUserWithDuplicatedSession() {
+ /** @var IUser|MockObject $testUser */
+ $testUser = $this->createMock(IUser::class);
+ $testUser->expects($this->any())
+ ->method('getUID')
+ ->willReturn($this->userId);
+
+ $room = $this->manager->createRoom(Room::TYPE_PUBLIC);
+ $this->participantService->addUsers($room, [[
+ 'actorType' => 'users',
+ 'actorId' => $this->userId,
+ ]]);
+ $participant = $this->participantService->joinRoom($room, $testUser, '');
+ $this->controller->clearRequests();
+ $this->participantService->leaveRoomAsSession($room, $participant, true);
+
+ $this->assertMessageWasSent($room, [
+ 'type' => 'disinvite',
+ 'disinvite' => [
+ 'sessionids' => [
+ $participant->getSession()->getSessionId(),
+ ],
+ 'alluserids' => [
+ $this->userId,
+ ],
+ 'properties' => [
+ 'name' => $room->getDisplayName(''),
+ 'type' => $room->getType(),
+ 'lobby-state' => Webinary::LOBBY_NONE,
+ 'lobby-timer' => null,
+ 'read-only' => Room::READ_WRITE,
+ 'listable' => Room::LISTABLE_NONE,
+ 'active-since' => null,
+ 'sip-enabled' => 0,
+ 'participant-list' => 'refresh',
+ ],
+ ],
+ ]);
+ }
+
public function testRoomDisinviteOnLeaveOfSelfJoinedUser() {
/** @var IUser|MockObject $testUser */
$testUser = $this->createMock(IUser::class);
@@ -697,6 +737,45 @@ class BackendNotifierTest extends TestCase {
]);
}
+ public function testRoomInCallChangedWhenLeavingConversationWhileInCall() {
+ /** @var IUser|MockObject $testUser */
+ $testUser = $this->createMock(IUser::class);
+ $testUser->expects($this->any())
+ ->method('getUID')
+ ->willReturn($this->userId);
+
+ $room = $this->manager->createRoom(Room::TYPE_PUBLIC);
+ $this->participantService->addUsers($room, [[
+ 'actorType' => 'users',
+ 'actorId' => $this->userId,
+ ]]);
+ $participant = $this->participantService->joinRoom($room, $testUser, '');
+ $userSession = $participant->getSession()->getSessionId();
+ $this->participantService->changeInCall($room, $participant, Participant::FLAG_IN_CALL | Participant::FLAG_WITH_AUDIO | Participant::FLAG_WITH_VIDEO);
+ $this->controller->clearRequests();
+ $this->participantService->leaveRoomAsSession($room, $participant);
+
+ $this->assertMessageWasSent($room, [
+ 'type' => 'incall',
+ 'incall' => [
+ 'incall' => 0,
+ 'changed' => [
+ [
+ 'inCall' => 0,
+ 'lastPing' => 0,
+ 'sessionId' => $userSession,
+ 'nextcloudSessionId' => $userSession,
+ 'participantType' => Participant::USER,
+ 'participantPermissions' => (Attendee::PERMISSIONS_MAX_DEFAULT ^ Attendee::PERMISSIONS_LOBBY_IGNORE),
+ 'userId' => $this->userId,
+ ],
+ ],
+ 'users' => [
+ ],
+ ],
+ ]);
+ }
+
public function testRoomPropertiesEvent(): void {
$listener = static function (SignalingRoomPropertiesEvent $event) {
$room = $event->getRoom();