Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
fix(calls): Make starting a call an explicit event
Signed-off-by: Joas Schilling <[email protected]>
  • Loading branch information
nickvergessen committed Jul 31, 2024
commit 1c673cd896d12587005245904fe4e4bb49e854fb
14 changes: 8 additions & 6 deletions docs/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ See the general [Nextcloud Developers - Events](https://docs.nextcloud.com/serve
* After event: `OCA\Talk\Events\LobbyModifiedEvent`
* Since: 18.0.0

### Call started

* Before event: `OCA\Talk\Events\BeforeCallStartedEvent`
* After event: `OCA\Talk\Events\CallStartedEvent`
The after event might be skipped if the request lost the race to update the database.
A parallel request will have triggered the before and after events in the meantime.
* Since: 20.0.0

### Call ended for everyone

* Before event: `OCA\Talk\Events\BeforeCallEndedForEveryoneEvent`
Expand All @@ -47,12 +55,6 @@ Allows to verify a password and set a redirect URL for the invalid case
* Event: `OCA\Talk\Events\RoomPasswordVerifyEvent`
* Since: 18.0.0

### Active since modified

* Before event: `OCA\Talk\Events\BeforeActiveSinceModifiedEvent`
* After event: `OCA\Talk\Events\ActiveSinceModifiedEvent`
* Since: 20.0.0

## Participant related events

### Attendees added
Expand Down
19 changes: 0 additions & 19 deletions lib/Activity/Listener.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,32 +61,13 @@ public function handle(Event $event): void {
};
}

protected function setActive(ParticipantModifiedEvent $event): void {
if ($event->getProperty() !== AParticipantModifiedEvent::PROPERTY_IN_CALL) {
return;
}

if ($event->getOldValue() !== Participant::FLAG_DISCONNECTED
|| $event->getNewValue() === Participant::FLAG_DISCONNECTED) {
return;
}

$participant = $event->getParticipant();
$this->roomService->setActiveSince(
$event->getRoom(),
$this->timeFactory->getDateTime(),
$participant->getSession() ? $participant->getSession()->getInCall() : Participant::FLAG_DISCONNECTED
);
}

protected function handleParticipantModified(ParticipantModifiedEvent $event): void {
if ($event->getProperty() !== AParticipantModifiedEvent::PROPERTY_IN_CALL) {
return;
}

if ($event->getOldValue() === Participant::FLAG_DISCONNECTED
|| $event->getNewValue() !== Participant::FLAG_DISCONNECTED) {
$this->setActive($event);
return;
}

Expand Down
9 changes: 5 additions & 4 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
use OCA\Talk\Config;
use OCA\Talk\Dashboard\TalkWidget;
use OCA\Talk\Deck\DeckPluginLoader;
use OCA\Talk\Events\ActiveSinceModifiedEvent;
use OCA\Talk\Events\BeforeCallStartedEvent;
use OCA\Talk\Events\CallStartedEvent;
use OCA\Talk\Events\AttendeeRemovedEvent;
use OCA\Talk\Events\AttendeesAddedEvent;
use OCA\Talk\Events\AttendeesRemovedEvent;
Expand Down Expand Up @@ -246,8 +247,8 @@ public function register(IRegistrationContext $context): void {

// Notification listeners
$context->registerEventListener(AttendeesAddedEvent::class, NotificationListener::class);
$context->registerEventListener(ActiveSinceModifiedEvent::class, NotificationListener::class);
$context->registerEventListener(BeforeParticipantModifiedEvent::class, NotificationListener::class);
$context->registerEventListener(BeforeCallStartedEvent::class, NotificationListener::class);
$context->registerEventListener(CallStartedEvent::class, NotificationListener::class);
$context->registerEventListener(CallNotificationSendEvent::class, NotificationListener::class);
$context->registerEventListener(ParticipantModifiedEvent::class, NotificationListener::class);
$context->registerEventListener(UserJoinedRoomEvent::class, NotificationListener::class);
Expand All @@ -265,7 +266,7 @@ public function register(IRegistrationContext $context): void {

// Federation listeners
$context->registerEventListener(BeforeRoomDeletedEvent::class, TalkV1BeforeRoomDeletedListener::class);
$context->registerEventListener(ActiveSinceModifiedEvent::class, TalkV1RoomModifiedListener::class);
$context->registerEventListener(CallStartedEvent::class, TalkV1RoomModifiedListener::class);
$context->registerEventListener(LobbyModifiedEvent::class, TalkV1RoomModifiedListener::class);
$context->registerEventListener(RoomModifiedEvent::class, TalkV1RoomModifiedListener::class);
$context->registerEventListener(ChatMessageSentEvent::class, TalkV1MessageSentListener::class);
Expand Down
15 changes: 9 additions & 6 deletions lib/Controller/CallController.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,11 @@ public function joinCall(?int $flags = null, ?int $forcePermissions = null, bool
$this->roomService->setPermissions($this->room, 'call', Attendee::PERMISSIONS_MODIFY_SET, $forcePermissions, true);
}

$joined = $this->participantService->changeInCall($this->room, $this->participant, $flags, false, $silent);

if (!$joined) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
try {
$this->participantService->changeInCall($this->room, $this->participant, $flags, silent: $silent);
$this->roomService->setActiveSince($this->room, $this->participant, $this->timeFactory->getDateTime(), $flags, silent: $silent);
} catch (\InvalidArgumentException $e) {
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
}
return new DataResponse();
}
Expand Down Expand Up @@ -226,8 +227,10 @@ public function joinFederatedCall(string $sessionId, ?int $flags = null, bool $s
return new DataResponse(['error' => 'consent'], Http::STATUS_BAD_REQUEST);
}

$joined = $this->participantService->changeInCall($this->room, $this->participant, $flags, false, $silent);
if (!$joined) {
try {
$this->participantService->changeInCall($this->room, $this->participant, $flags, false, $silent);
$this->roomService->setActiveSince($this->room, $this->participant, $this->timeFactory->getDateTime(), $flags, silent: $silent);
} catch (\InvalidArgumentException $e) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,37 @@

namespace OCA\Talk\Events;

use OCA\Talk\Participant;
use OCA\Talk\Room;

abstract class AActiveSinceModifiedEvent extends ARoomModifiedEvent {
abstract class ACallStartedEvent extends ARoomModifiedEvent {
/**
* @param array<AParticipantModifiedEvent::DETAIL_*, bool> $details
*/
public function __construct(
Room $room,
?\DateTime $newValue,
?\DateTime $oldValue,
protected int $callFlag,
protected int $oldCallFlag,
protected array $details,
?Participant $actor,
) {
parent::__construct(
$room,
self::PROPERTY_ACTIVE_SINCE,
$newValue,
$oldValue,
null,
$actor,
);
}

public function getCallFlag(): int {
return $this->callFlag;
}

public function getOldCallFlag(): int {
return $this->oldCallFlag;
/**
* @param AParticipantModifiedEvent::DETAIL_* $detail
*/
public function getDetail(string $detail): ?bool {
return $this->details[$detail] ?? null;
}
}
34 changes: 0 additions & 34 deletions lib/Events/ActiveSinceModifiedEvent.php

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@

namespace OCA\Talk\Events;

class BeforeActiveSinceModifiedEvent extends AActiveSinceModifiedEvent {
class BeforeCallStartedEvent extends ACallStartedEvent {
}
12 changes: 12 additions & 0 deletions lib/Events/CallStartedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Talk\Events;

class CallStartedEvent extends ACallStartedEvent {
}
21 changes: 9 additions & 12 deletions lib/Federation/BackendNotifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace OCA\Talk\Federation;

use OCA\FederatedFileSharing\AddressHandler;
use OCA\Talk\Events\ACallStartedEvent;
use OCA\Talk\Exceptions\RoomHasNoModeratorException;
use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\RetryNotification;
Expand Down Expand Up @@ -243,27 +244,22 @@ public function sendRoomModifiedUpdate(
/**
* Send information to remote participants that "active since" was updated
* Sent from Host server to Remote participant server
*
* @psalm-param array<AParticipantModifiedEvent::DETAIL_*, bool> $details
*/
public function sendRoomModifiedActiveSinceUpdate(
public function sendCallStarted(
string $remoteServer,
int $localAttendeeId,
#[SensitiveParameter]
string $accessToken,
string $localToken,
string $changedProperty,
?\DateTime $newValue,
?\DateTime $oldValue,
\DateTime $activeSince,
int $callFlag,
array $details,
): ?bool {
$remote = $this->prepareRemoteUrl($remoteServer);

if ($newValue instanceof \DateTime) {
$newValue = (string) $newValue->getTimestamp();
}
if ($oldValue instanceof \DateTime) {
$oldValue = (string) $oldValue->getTimestamp();
}

$notification = $this->cloudFederationFactory->getCloudFederationNotification();
$notification->setMessage(
FederationManager::NOTIFICATION_ROOM_MODIFIED,
Expand All @@ -274,9 +270,10 @@ public function sendRoomModifiedActiveSinceUpdate(
'sharedSecret' => $accessToken,
'remoteToken' => $localToken,
'changedProperty' => $changedProperty,
'newValue' => $newValue,
'oldValue' => $oldValue,
'newValue' => $activeSince->getTimestamp(),
'oldValue' => null,
'callFlag' => $callFlag,
'details' => $details,
],
);

Expand Down
9 changes: 5 additions & 4 deletions lib/Federation/CloudFederationProviderTalk.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use OCA\Talk\CachePrefix;
use OCA\Talk\Config;
use OCA\Talk\Events\AAttendeeRemovedEvent;
use OCA\Talk\Events\AParticipantModifiedEvent;
use OCA\Talk\Events\ARoomModifiedEvent;
use OCA\Talk\Events\AttendeesAddedEvent;
use OCA\Talk\Exceptions\CannotReachRemoteException;
Expand Down Expand Up @@ -288,7 +289,7 @@ private function shareUnshared(int $remoteAttendeeId, array $notification): arra

/**
* @param int $remoteAttendeeId
* @param array{remoteServerUrl: string, sharedSecret: string, remoteToken: string, changedProperty: string, newValue: string|int|bool|null, oldValue: string|int|bool|null, callFlag?: int, dateTime?: string, timerReached?: bool} $notification
* @param array{remoteServerUrl: string, sharedSecret: string, remoteToken: string, changedProperty: string, newValue: string|int|bool|null, oldValue: string|int|bool|null, callFlag?: int, dateTime?: string, timerReached?: bool, details?: array<AParticipantModifiedEvent::DETAIL_*, bool>} $notification
* @return array
* @throws ActionNotSupportedException
* @throws AuthenticationFailedException
Expand All @@ -311,15 +312,15 @@ private function roomModified(int $remoteAttendeeId, array $notification): array
if ($notification['newValue'] === null) {
$this->roomService->resetActiveSince($room);
} else {
$activeSince = \DateTime::createFromFormat('U', $notification['newValue']);
$this->roomService->setActiveSince($room, $activeSince, $notification['callFlag']);
$activeSince = $this->timeFactory->getDateTime('@' . $notification['newValue']);
$this->roomService->setActiveSince($room, null, $activeSince, $notification['callFlag'], !empty($notification['details'][AParticipantModifiedEvent::DETAIL_IN_CALL_SILENT]));
}
} elseif ($notification['changedProperty'] === ARoomModifiedEvent::PROPERTY_AVATAR) {
$this->roomService->setAvatar($room, $notification['newValue']);
} elseif ($notification['changedProperty'] === ARoomModifiedEvent::PROPERTY_DESCRIPTION) {
$this->roomService->setDescription($room, $notification['newValue']);
} elseif ($notification['changedProperty'] === ARoomModifiedEvent::PROPERTY_IN_CALL) {
$this->roomService->setActiveSince($room, $room->getActiveSince(), $notification['newValue']);
$this->roomService->setActiveSince($room, null, $room->getActiveSince(), $notification['newValue'], true);
} elseif ($notification['changedProperty'] === ARoomModifiedEvent::PROPERTY_LOBBY) {
$dateTime = !empty($notification['dateTime']) ? \DateTime::createFromFormat('U', $notification['dateTime']) : null;
$this->roomService->setLobby($room, $notification['newValue'], $dateTime, $notification['timerReached'] ?? false);
Expand Down
2 changes: 1 addition & 1 deletion lib/Federation/Proxy/TalkV1/Controller/CallController.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function __construct(
* @psalm-param int-mask-of<Participant::FLAG_*> $flags
* @param bool $silent Join the call silently
* @param bool $recordingConsent Agreement to be recorded
* @return DataResponse<Http::STATUS_OK|Http::STATUS_BAD_REQUEST|Http::STATUS_NOT_FOUND, array<empty>, array{}>
* @return DataResponse<Http::STATUS_OK|Http::STATUS_NOT_FOUND, array<empty>, array{}>|DataResponse<Http::STATUS_BAD_REQUEST, array{error?: string}, array{}>
* @throws CannotReachRemoteException
*
* 200: Federated user is now in the call
Expand Down
22 changes: 15 additions & 7 deletions lib/Federation/Proxy/TalkV1/Notifier/RoomModifiedListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@

use OCA\Talk\Events\AActiveSinceModifiedEvent;
use OCA\Talk\Events\AAttendeeRemovedEvent;
use OCA\Talk\Events\ActiveSinceModifiedEvent;
use OCA\Talk\Events\ALobbyModifiedEvent;
use OCA\Talk\Events\AParticipantModifiedEvent;
use OCA\Talk\Events\ARoomModifiedEvent;
use OCA\Talk\Events\CallEndedEvent;
use OCA\Talk\Events\CallEndedForEveryoneEvent;
use OCA\Talk\Events\CallStartedEvent;
use OCA\Talk\Events\LobbyModifiedEvent;
use OCA\Talk\Events\RoomModifiedEvent;
use OCA\Talk\Federation\BackendNotifier;
Expand All @@ -36,7 +39,7 @@ public function __construct(
}

public function handle(Event $event): void {
if (!$event instanceof ActiveSinceModifiedEvent
if (!$event instanceof CallStartedEvent
&& !$event instanceof LobbyModifiedEvent
&& !$event instanceof RoomModifiedEvent) {
return;
Expand All @@ -60,8 +63,8 @@ public function handle(Event $event): void {
foreach ($participants as $participant) {
$cloudId = $this->cloudIdManager->resolveCloudId($participant->getAttendee()->getActorId());

if ($event instanceof AActiveSinceModifiedEvent) {
$success = $this->notifyActiveSinceModified($cloudId, $participant, $event);
if ($event instanceof CallStartedEvent) {
$success = $this->notifyCallStarted($cloudId, $participant, $event);
} elseif ($event instanceof ALobbyModifiedEvent) {
$success = $this->notifyLobbyModified($cloudId, $participant, $event);
} else {
Expand All @@ -74,16 +77,21 @@ public function handle(Event $event): void {
}
}

private function notifyActiveSinceModified(ICloudId $cloudId, Participant $participant, AActiveSinceModifiedEvent $event) {
return $this->backendNotifier->sendRoomModifiedActiveSinceUpdate(
private function notifyCallStarted(ICloudId $cloudId, Participant $participant, CallStartedEvent $event) {
$details = [];
if ($event->getDetail(AParticipantModifiedEvent::DETAIL_IN_CALL_SILENT)) {
$details = [AParticipantModifiedEvent::DETAIL_IN_CALL_SILENT => true];
}

return $this->backendNotifier->sendCallStarted(
$cloudId->getRemote(),
$participant->getAttendee()->getId(),
$participant->getAttendee()->getAccessToken(),
$event->getRoom()->getToken(),
$event->getProperty(),
$event->getNewValue(),
$event->getOldValue(),
$event->getCallFlag(),
$details,
);
}

Expand Down
Loading