Provide multiple TURN servers to webrtc client

- Provides all in the backend specified turnservers to webrtc clients

Signed-off-by: Sebastian L <sl@momou.ch>
This commit is contained in:
Sebastian L 2021-05-04 23:41:54 +02:00
Родитель f549e525bc
Коммит 74baa14c5c
3 изменённых файлов: 77 добавлений и 50 удалений

Просмотреть файл

@ -251,7 +251,7 @@ class Config {
}
/**
* Generates a username and password for the TURN server
* Prepares a list of TURN servers with username and password
*
* @return array
*/
@ -259,20 +259,7 @@ class Config {
$servers = $this->getTurnServers();
if (empty($servers)) {
return [
'schemes' => '',
'server' => '',
'username' => '',
'password' => '',
'protocols' => '',
];
}
// For now we use a random server from the list
try {
$server = $servers[random_int(0, count($servers) - 1)];
} catch (\Exception $e) {
$server = $servers[0];
return [];
}
// Credentials are valid for 24h
@ -280,15 +267,20 @@ class Config {
$timestamp = $this->timeFactory->getTime() + 86400;
$rnd = $this->secureRandom->generate(16);
$username = $timestamp . ':' . $rnd;
$password = base64_encode(hash_hmac('sha1', $username, $server['secret'], true));
return [
'schemes' => $server['schemes'],
'server' => $server['server'],
'username' => $username,
'password' => $password,
'protocols' => $server['protocols'],
];
foreach ($servers as $server) {
$password = base64_encode(hash_hmac('sha1', $username, $server['secret'], true));
$turnSettings[] = [
'schemes' => $server['schemes'],
'server' => $server['server'],
'username' => $username,
'password' => $password,
'protocols' => $server['protocols'],
];
}
return $turnSettings;
}
public function getSignalingMode(bool $cleanExternalSignaling = true): string {

Просмотреть файл

@ -146,16 +146,16 @@ class SignalingController extends OCSController {
$turn = [];
$turnSettings = $this->talkConfig->getTurnSettings();
if (!empty($turnSettings['server'])) {
$schemes = explode(',', $turnSettings['schemes']);
$protocols = explode(',', $turnSettings['protocols']);
foreach ($turnSettings as $turnServer) {
$schemes = explode(',', $turnServer['schemes']);
$protocols = explode(',', $turnServer['protocols']);
foreach ($schemes as $scheme) {
foreach ($protocols as $proto) {
$turn[] = [
'url' => [$scheme . ':' . $turnSettings['server'] . '?transport=' . $proto],
'urls' => [$scheme . ':' . $turnSettings['server'] . '?transport=' . $proto],
'username' => $turnSettings['username'],
'credential' => $turnSettings['password'],
'url' => [$scheme . ':' . $turnServer['server'] . '?transport=' . $proto],
'urls' => [$scheme . ':' . $turnServer['server'] . '?transport=' . $proto],
'username' => $turnServer['username'],
'credential' => $turnServer['password'],
];
}
}

Просмотреть файл

@ -117,13 +117,19 @@ class ConfigTest extends TestCase {
->willReturn(json_encode([
[
// No scheme explicitly given
'server' => 'turn.example.org',
'server' => 'turn.example.org:3478',
'secret' => 'thisisasupersecretsecret',
'protocols' => 'udp,tcp',
],
[
'schemes' => 'turn,turns',
'server' => 'turn2.example.com',
'server' => 'turn2.example.com:5349',
'secret' => 'ThisIsAlsoSuperSecret',
'protocols' => 'udp',
],
[
'schemes' => 'turns',
'server' => 'turn-tls.example.com:443',
'secret' => 'ThisIsAlsoSuperSecret',
'protocols' => 'tcp',
],
@ -149,24 +155,53 @@ class ConfigTest extends TestCase {
$helper = new Config($config, $secureRandom, $groupManager, $timeFactory);
//
$server = $helper->getTurnSettings();
if ($server['server'] === 'turn.example.org') {
$this->assertSame([
'schemes' => 'turn',
'server' => 'turn.example.org',
'username' => '1479829425:abcdefghijklmnop',
'password' => '4VJLVbihLzuxgMfDrm5C3zy8kLQ=',
'protocols' => 'udp,tcp',
], $server);
} else {
$this->assertSame([
'schemes' => 'turn,turns',
'server' => 'turn2.example.com',
'username' => '1479829425:abcdefghijklmnop',
'password' => 'Ol9DEqnvyN4g+IAM+vFnqhfWUTE=',
'protocols' => 'tcp',
], $server);
}
$settings = $helper->getTurnSettings();
$this->assertEquals(3, count($settings));
$this->assertSame([
'schemes' => 'turn',
'server' => 'turn.example.org:3478',
'username' => '1479829425:abcdefghijklmnop',
'password' => '4VJLVbihLzuxgMfDrm5C3zy8kLQ=',
'protocols' => 'udp,tcp',
], $settings[0]);
$this->assertSame([
'schemes' => 'turn,turns',
'server' => 'turn2.example.com:5349',
'username' => '1479829425:abcdefghijklmnop',
'password' => 'Ol9DEqnvyN4g+IAM+vFnqhfWUTE=',
'protocols' => 'udp',
], $settings[1]);
$this->assertSame([
'schemes' => 'turns',
'server' => 'turn-tls.example.com:443',
'username' => '1479829425:abcdefghijklmnop',
'password' => 'Ol9DEqnvyN4g+IAM+vFnqhfWUTE=',
'protocols' => 'tcp',
], $settings[2]);
}
public function testGenerateTurnSettingsEmpty() {
/** @var MockObject|IConfig $config */
$config = $this->createMock(IConfig::class);
$config
->expects($this->once())
->method('getAppValue')
->with('spreed', 'turn_servers', '')
->willReturn(json_encode([]));
/** @var MockObject|ITimeFactory $timeFactory */
$timeFactory = $this->createMock(ITimeFactory::class);
/** @var MockObject|IGroupManager $secureRandom */
$groupManager = $this->createMock(IGroupManager::class);
/** @var MockObject|ISecureRandom $secureRandom */
$secureRandom = $this->createMock(ISecureRandom::class);
$helper = new Config($config, $secureRandom, $groupManager, $timeFactory);
$settings = $helper->getTurnSettings();
$this->assertEquals(0, count($settings));
}
public function dataGetWebSocketDomainForSignalingServer() {