Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 2 additions & 0 deletions lib/ConfigLexicon.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace OCA\Talk;

use OCA\Talk\Settings\UserPreference;
use OCA\Talk\Signaling\Manager as SignalingManager;
use OCP\Config\Lexicon\Entry;
use OCP\Config\Lexicon\ILexicon;
use OCP\Config\Lexicon\Strictness;
Expand All @@ -26,6 +27,7 @@ public function getAppConfigs(): array {
return [
new Entry(UserPreference::CONVERSATIONS_LIST_STYLE, ValueType::STRING, UserPreference::CONVERSATION_LIST_STYLE_TWO_LINES),
new Entry(UserPreference::CHAT_STYLE, ValueType::STRING, UserPreference::CHAT_STYLE_SPLIT),
new Entry(SignalingManager::HAS_FEATURE_CHANGED_USERS, ValueType::BOOL, false),
];
}

Expand Down
159 changes: 116 additions & 43 deletions lib/Signaling/BackendNotifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use OCA\Talk\Participant;
use OCA\Talk\Room;
use OCA\Talk\Service\ParticipantService;
use OCP\AppFramework\Services\IAppConfig;
use OCP\Http\Client\IClientService;
use OCP\Http\Client\IResponse;
use OCP\IURLGenerator;
Expand All @@ -27,6 +28,7 @@ class BackendNotifier {

public function __construct(
private readonly Config $config,
private readonly IAppConfig $appConfig,
private readonly LoggerInterface $logger,
private readonly IClientService $clientService,
private readonly ISecureRandom $secureRandom,
Expand Down Expand Up @@ -61,6 +63,12 @@ protected function doRequest(string $url, array $params, int $retries = 3): ?IRe
throw new \RuntimeException('Signaling server needs to be updated to be compatible with this version of Talk');
}

if (!$this->appConfig->getAppValueBool(Manager::HAS_FEATURE_CHANGED_USERS)) {
if ($this->signalingManager->hasFeature($response, 'changed-users')) {
$this->appConfig->setAppValueBool(Manager::HAS_FEATURE_CHANGED_USERS, true);
}
}
Comment on lines +66 to +70

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any specific reason to use a "ratchet" (so it never goes back once enabled) instead of setting the value based on the actual header? Although a signaling server downgrade or having more than one would be unlikely it is nevertheless possible.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any specific reason to use a "ratchet" (so it never goes back once enabled) instead of setting the value based on the actual header?

So we can drop the config completely once we require the feature (most likely in an upcoming version)

Although a signaling server downgrade or having more than one would be unlikely it is nevertheless possible.

Having multiple yields a setupcheck error by now, so this is fine.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any specific reason to use a "ratchet" (so it never goes back once enabled) instead of setting the value based on the actual header?

So we can drop the config completely once we require the feature (most likely in an upcoming version)

But the configuration can still be dropped once the feature is required even if it keeps track of the actual changed-users header with something like the following, no? 🤔 :

if ($this->appConfig->getAppValueBool(Manager::HAS_FEATURE_CHANGED_USERS) !== $this->signalingManager->hasFeature($response, 'changed-users')) {
	$this->appConfig->setAppValueBool(Manager::HAS_FEATURE_CHANGED_USERS, $this->signalingManager->hasFeature($response, 'changed-users'));
}

Although a signaling server downgrade or having more than one would be unlikely it is nevertheless possible.

Having multiple yields a setupcheck error by now, so this is fine.

I did not mean multiple configured, but multiple signaling servers that could be switched between them. Like the one in s10 and the one in talk.meeting.


return $response;
} catch (ConnectException $e) {
if ($retries > 1) {
Expand Down Expand Up @@ -150,23 +158,36 @@ private function backendRequest(Room $room, array $data): ?IResponse {
* @throws \Exception
*/
public function roomInvited(Room $room, array $attendees): void {
// TODO Remove once a new HPB is required
$supportsChangedUsers = $this->appConfig->getAppValueBool(Manager::HAS_FEATURE_CHANGED_USERS);

$userIds = [];
foreach ($attendees as $attendee) {
if ($attendee->getActorType() === Attendee::ACTOR_USERS) {
$userIds[] = $attendee->getActorId();
}
}
$start = microtime(true);
$this->backendRequest($room, [

if ($supportsChangedUsers && empty($userIds)) {
return;
}

$data = [
'type' => 'invite',
'invite' => [
'userids' => $userIds,
// TODO(fancycode): We should try to get rid of 'alluserids' and
// find a better way to notify existing users to update the room.
'alluserids' => $this->participantService->getParticipantUserIdsAndFederatedUserCloudIds($room),
'properties' => $this->roomPropertiesHelper->getPropertiesForSignaling($room, '', false),
],
]);
];

if (!$supportsChangedUsers) {
$allUserIds = $this->participantService->getParticipantUserIdsAndFederatedUserCloudIds($room);
sort($allUserIds);
$data['invite']['alluserids'] = $allUserIds;
}

$start = microtime(true);
$this->backendRequest($room, $data);
$duration = microtime(true) - $start;
$this->logger->debug('Now invited to {token}: {users} ({duration})', [
'token' => $room->getToken(),
Expand All @@ -184,25 +205,36 @@ public function roomInvited(Room $room, array $attendees): void {
* @throws \Exception
*/
public function roomsDisinvited(Room $room, array $attendees): void {
$allUserIds = $this->participantService->getParticipantUserIdsAndFederatedUserCloudIds($room);
sort($allUserIds);
// TODO Remove once a new HPB is required
$supportsChangedUsers = $this->appConfig->getAppValueBool(Manager::HAS_FEATURE_CHANGED_USERS);

$userIds = [];
foreach ($attendees as $attendee) {
if ($attendee->getActorType() === Attendee::ACTOR_USERS) {
$userIds[] = $attendee->getActorId();
}
}
$start = microtime(true);
$this->backendRequest($room, [

if ($supportsChangedUsers && empty($userIds)) {
return;
}

$data = [
'type' => 'disinvite',
'disinvite' => [
'userids' => $userIds,
// TODO(fancycode): We should try to get rid of 'alluserids' and
// find a better way to notify existing users to update the room.
'alluserids' => $allUserIds,
'properties' => $this->roomPropertiesHelper->getPropertiesForSignaling($room, '', false),
],
]);
];

if (!$supportsChangedUsers) {
$allUserIds = $this->participantService->getParticipantUserIdsAndFederatedUserCloudIds($room);
sort($allUserIds);
$data['disinvite']['alluserids'] = $allUserIds;
}

$start = microtime(true);
$this->backendRequest($room, $data);
$duration = microtime(true) - $start;
$this->logger->debug('No longer invited to {token}: {users} ({duration})', [
'token' => $room->getToken(),
Expand All @@ -220,19 +252,25 @@ public function roomsDisinvited(Room $room, array $attendees): void {
* @throws \Exception
*/
public function roomSessionsRemoved(Room $room, array $sessionIds): void {
$allUserIds = $this->participantService->getParticipantUserIdsAndFederatedUserCloudIds($room);
sort($allUserIds);
$start = microtime(true);
$this->backendRequest($room, [
// TODO Remove once a new HPB is required
$supportsChangedUsers = $this->appConfig->getAppValueBool(Manager::HAS_FEATURE_CHANGED_USERS);

$data = [
'type' => 'disinvite',
'disinvite' => [
'sessionids' => $sessionIds,
// TODO(fancycode): We should try to get rid of 'alluserids' and
// find a better way to notify existing users to update the room.
'alluserids' => $allUserIds,
'properties' => $this->roomPropertiesHelper->getPropertiesForSignaling($room, '', false),
],
]);
];

if (!$supportsChangedUsers) {
$allUserIds = $this->participantService->getParticipantUserIdsAndFederatedUserCloudIds($room);
sort($allUserIds);
$data['disinvite']['alluserids'] = $allUserIds;
}

$start = microtime(true);
$this->backendRequest($room, $data);
$duration = microtime(true) - $start;
$this->logger->debug('Removed from {token}: {users} ({duration})', [
'token' => $room->getToken(),
Expand All @@ -249,17 +287,22 @@ public function roomSessionsRemoved(Room $room, array $sessionIds): void {
* @throws \Exception
*/
public function roomModified(Room $room): void {
$start = microtime(true);
$this->backendRequest($room, [
// TODO Remove once a new HPB is required
$supportsChangedUsers = $this->appConfig->getAppValueBool(Manager::HAS_FEATURE_CHANGED_USERS);

$data = [
'type' => 'update',
'update' => [
// Message not sent for federated users, as they will receive
// the message from their federated Nextcloud server once the
// property change is propagated.
'userids' => $this->participantService->getParticipantUserIds($room),
'properties' => $this->roomPropertiesHelper->getPropertiesForSignaling($room, ''),
],
]);
];

if (!$supportsChangedUsers) {
$data['update']['userids'] = $this->participantService->getParticipantUserIds($room);
}

$start = microtime(true);
$this->backendRequest($room, $data);
$duration = microtime(true) - $start;
$this->logger->debug('Room modified: {token} ({duration})', [
'token' => $room->getToken(),
Expand All @@ -272,17 +315,25 @@ public function roomModified(Room $room): void {
* The given room has been deleted.
*
* @param Room $room
* @param string[] $userIds
* @throws \Exception
*/
public function roomDeleted(Room $room, array $userIds): void {
$start = microtime(true);
$this->backendRequest($room, [
public function roomDeleted(Room $room): void {
// TODO Remove once a new HPB is required
$supportsChangedUsers = $this->appConfig->getAppValueBool(Manager::HAS_FEATURE_CHANGED_USERS);

$data = [
'type' => 'delete',
'delete' => [
'userids' => $userIds,
],
]);
'delete' => new \stdClass(),
];

if (!$supportsChangedUsers) {
$data['delete'] = [
'userids' => $this->participantService->getParticipantUserIds($room),
];
}

$start = microtime(true);
$this->backendRequest($room, $data);
$duration = microtime(true) - $start;
$this->logger->debug('Room deleted: {token} ({duration})', [
'token' => $room->getToken(),
Expand Down Expand Up @@ -326,6 +377,9 @@ public function switchToRoom(Room $room, string $switchToRoomToken, array $sessi
* @throws \Exception
*/
public function participantsModified(Room $room, array $sessionIds): void {
// TODO Remove once a new HPB is required
$supportsChangedUsers = $this->appConfig->getAppValueBool(Manager::HAS_FEATURE_CHANGED_USERS);

$changed = [];
$users = [];
$participants = $this->participantService->getSessionsAndParticipantsForRoom($room);
Expand Down Expand Up @@ -381,14 +435,23 @@ public function participantsModified(Room $room, array $sessionIds): void {
}
}

$start = microtime(true);
$this->backendRequest($room, [
if ($supportsChangedUsers && empty($changed)) {
return;
}

$data = [
'type' => 'participants',
'participants' => [
'changed' => $changed,
'users' => $users
],
]);
];

if (!$supportsChangedUsers) {
$data['participants']['users'] = $users;
}

$start = microtime(true);
$this->backendRequest($room, $data);
$duration = microtime(true) - $start;
$this->logger->debug('Room participants modified: {token} {users} ({duration})', [
'token' => $room->getToken(),
Expand All @@ -408,6 +471,9 @@ public function participantsModified(Room $room, array $sessionIds): void {
* @throws \Exception
*/
public function roomInCallChanged(Room $room, int $flags, array $sessionIds, bool $changeAll = false): void {
// TODO Remove once a new HPB is required
$supportsChangedUsers = $this->appConfig->getAppValueBool(Manager::HAS_FEATURE_CHANGED_USERS);

if ($changeAll) {
$data = [
'incall' => $flags,
Expand Down Expand Up @@ -446,7 +512,7 @@ public function roomInCallChanged(Room $room, int $flags, array $sessionIds, boo
$data['userId'] = $attendee->getActorId();
}

if ($session->getInCall() !== Participant::FLAG_DISCONNECTED) {
if (!$supportsChangedUsers && $session->getInCall() !== Participant::FLAG_DISCONNECTED) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

supportsChangedUsers should be unneeded here, or it should be also added when assigning users in participantsModified for consistency.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added it, so it's easier to spot that once the feature is required we can drop the code block

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then it should be added in

$users[] = $data;
and
$users[] = $data;
too

$users[] = $data;
}

Expand All @@ -455,11 +521,18 @@ public function roomInCallChanged(Room $room, int $flags, array $sessionIds, boo
}
}

if ($supportsChangedUsers && empty($changed)) {
return;
}

$data = [
'incall' => $flags,
'changed' => $changed,
'users' => $users,
];

if (!$supportsChangedUsers) {
$data['users'] = $users;
}
}

$start = microtime(true);
Expand Down
5 changes: 1 addition & 4 deletions lib/Signaling/Listener.php
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ protected function notifyCallEndedForEveryone(CallEndedForEveryoneEvent $event):

protected function notifyBeforeRoomDeleted(BeforeRoomDeletedEvent $event): void {
$room = $event->getRoom();
$this->externalSignaling->roomDeleted($room, $this->participantService->getParticipantUserIds($room));
$this->externalSignaling->roomDeleted($room);
}

protected function notifyGuestsCleanedUp(GuestsCleanedUpEvent $event): void {
Expand Down Expand Up @@ -311,9 +311,6 @@ protected function notifyParticipantNameModified(AParticipantModifiedEvent $even
protected function notifyParticipantTypeOrPermissionsModified(AParticipantModifiedEvent $event): void {
$sessionIds = [];

// If the participant is not active in the room the "participants"
// request will be sent anyway, although with an empty "changed"
// property.
$sessions = $this->sessionService->getAllSessionsForAttendee($event->getParticipant()->getAttendee());
foreach ($sessions as $session) {
$sessionIds[] = $session->getSessionId();
Expand Down
Loading
Loading