diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Controller/SignalingController.php | 61 | ||||
-rw-r--r-- | lib/Signaling/Manager.php | 88 |
2 files changed, 104 insertions, 45 deletions
diff --git a/lib/Controller/SignalingController.php b/lib/Controller/SignalingController.php index 7f0b4f72d..0ac38ea35 100644 --- a/lib/Controller/SignalingController.php +++ b/lib/Controller/SignalingController.php @@ -58,8 +58,8 @@ class SignalingController extends OCSController { private $talkConfig; /** @var IConfig */ private $serverConfig; - /** @var ICache */ - private $cache; + /** @var \OCA\Talk\Signaling\Manager */ + private $signalingManager; /** @var TalkSession */ private $session; /** @var Manager */ @@ -83,7 +83,7 @@ class SignalingController extends OCSController { IRequest $request, Config $talkConfig, IConfig $serverConfig, - ICacheFactory $cacheFactory, + \OCA\Talk\Signaling\Manager $signalingManager, TalkSession $session, Manager $manager, IDBConnection $connection, @@ -96,7 +96,7 @@ class SignalingController extends OCSController { parent::__construct($appName, $request); $this->talkConfig = $talkConfig; $this->serverConfig = $serverConfig; - $this->cache = $cacheFactory->createDistributed('hpb_servers'); + $this->signalingManager = $signalingManager; $this->session = $session; $this->dbConnection = $connection; $this->manager = $manager; @@ -115,6 +115,17 @@ class SignalingController extends OCSController { * @return DataResponse */ public function getSettings(string $token = ''): DataResponse { + try { + if ($token !== '') { + $room = $this->manager->getRoomForParticipantByToken($token, $this->userId); + } else { + // FIXME Soft-fail for legacy support in mobile apps + $room = null; + } + } catch (RoomNotFoundException $e) { + return new DataResponse([], Http::STATUS_NOT_FOUND); + } + $stun = []; $stunServer = $this->talkConfig->getStunServer(); if ($stunServer) { @@ -137,24 +148,8 @@ class SignalingController extends OCSController { } } - $signaling = ''; $signalingMode = $this->talkConfig->getSignalingMode(); - if ($signalingMode !== Config::SIGNALING_INTERNAL) { - $servers = $this->talkConfig->getSignalingServers(); - try { - $serverId = random_int(0, count($servers) - 1); - } catch (\Exception $e) { - $serverId = 0; - } - if ($signalingMode === Config::SIGNALING_CLUSTER_CONVERSATION) { - try { - $serverId = $this->getSignalingServerForConversation($this->userId, $serverId, $token); - } catch (RoomNotFoundException $e) { - return new DataResponse([], Http::STATUS_NOT_FOUND); - } - } - $signaling = $servers[$serverId]['server']; - } + $signaling = $this->signalingManager->getSignalingServerForConversation($room); return new DataResponse([ 'signalingMode' => $signalingMode, @@ -168,30 +163,6 @@ class SignalingController extends OCSController { } /** - * @param string|null $userId - * @param int $randomServerId - * @param string $token - * @throws RoomNotFoundException - * @return int - */ - protected function getSignalingServerForConversation(?string $userId, int $randomServerId, string $token): int { - $room = $this->manager->getRoomForParticipantByToken($token, $userId); - $serverId = $room->getAssignedSignalingServer(); - - if ($serverId === null) { - // Avoid concurrency issues - $serverId = $this->cache->get($token); - if ($serverId === null) { - $this->cache->set($token, $randomServerId); - $serverId = $randomServerId; - $room->setAssignedSignalingServer($randomServerId); - } - } - - return $serverId; - } - - /** * Only available for logged in users because guests can not use the apps * right now. * diff --git a/lib/Signaling/Manager.php b/lib/Signaling/Manager.php new file mode 100644 index 000000000..23580cb68 --- /dev/null +++ b/lib/Signaling/Manager.php @@ -0,0 +1,88 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2020 Joas Schilling <coding@schilljs.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\Signaling; + + +use OCA\Talk\Config; +use OCA\Talk\Room; +use OCP\ICache; +use OCP\ICacheFactory; + +class Manager { + + /** @var Config */ + protected $talkConfig; + /** @var ICache */ + private $cache; + + public function __construct(Config $talkConfig, + ICacheFactory $cacheFactory) { + $this->talkConfig = $talkConfig; + $this->cache = $cacheFactory->createDistributed('hpb_servers'); + } + + public function getSignalingServerForConversation(?Room $room): string { + switch ($this->talkConfig->getSignalingMode()) { + case Config::SIGNALING_INTERNAL: + return ''; + case Config::SIGNALING_EXTERNAL: + return $this->getSignalingServerRandomly(); + case Config::SIGNALING_CLUSTER_CONVERSATION: + if (!$room instanceof Room) { + throw new \RuntimeException('Can not get conversation cluster HPB without conversation'); + } + return $this->getSignalingServerConversationCluster($room); + default: + throw new \RuntimeException('Unknown signaling mode'); + } + } + + public function getSignalingServerRandomly(): string { + $servers = $this->talkConfig->getSignalingServers(); + try { + $serverId = random_int(0, count($servers) - 1); + return $servers[$serverId]['server']; + } catch (\Exception $e) { + return $servers[0]['server']; + } + } + + public function getSignalingServerConversationCluster(Room $room): string { + $serverId = $room->getAssignedSignalingServer(); + $servers = $this->talkConfig->getSignalingServers(); + + if ($serverId !== null && isset($servers[$serverId])) { + return $servers[$serverId]['server']; + } + + $randomServerId = random_int(0, count($servers) - 1); + $serverId = $this->cache->get($room->getToken()); + if ($serverId === null) { + $this->cache->set($room->getToken(), $randomServerId); + $serverId = $randomServerId; + $room->setAssignedSignalingServer($serverId); + } + + return $servers[$serverId]['server']; + } +} |