diff options
author | Joas Schilling <213943+nickvergessen@users.noreply.github.com> | 2022-08-26 22:37:53 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-26 22:37:53 +0300 |
commit | 4b27d7fd3a32de74e827b29fb089a91e9525a435 (patch) | |
tree | 5f358ae717644ee41cb27d9fef9a9705b37db1c8 | |
parent | 510575da45d37a48054b3c01a22bccf893ac1cbe (diff) | |
parent | 48443886b30f55a598eca1980ccbdb0da088a1d7 (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.php | 2 | ||||
-rw-r--r-- | lib/Events/DuplicatedParticipantEvent.php | 34 | ||||
-rw-r--r-- | lib/Service/ParticipantService.php | 20 | ||||
-rw-r--r-- | lib/Signaling/Listener.php | 9 | ||||
-rw-r--r-- | tests/php/Signaling/BackendNotifierTest.php | 79 |
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(); |