Skip to content

Commit

Permalink
Add admin setting to specify a TURN server and a shared secret
Browse files Browse the repository at this point in the history
* then calculates the user credentials on the fly for 1 hour

Signed-off-by: Morris Jobke <hey@morrisjobke.de>
  • Loading branch information
MorrisJobke committed Nov 21, 2016
1 parent e7f2cb4 commit 7ffb59b
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 13 deletions.
8 changes: 8 additions & 0 deletions css/settings-admin.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#spreed_settings_form label {
min-width: 200px;
display: inline-block;
}

#spreed_settings_form input {
width: 300px;
}
2 changes: 2 additions & 0 deletions js/settings-admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ $(document).ready(function(){
var post = $( "#spreed_settings_form" ).serialize();
$.post(OC.generateUrl('/apps/spreed/settings/admin'), post, function(data){
OC.msg.finishedSaving('#spreed_settings_msg', data);
}).fail(function(){
OC.msg.finishedError('#spreed_settings_msg', t('spreed', 'Saving failed'));
});
});

Expand Down
34 changes: 32 additions & 2 deletions lib/Controller/AppSettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,10 @@ public function __construct($appName,
* in the form "stunserver:port", e.g. "stun.domain.invalid:1234".
*
* @param string $stun_server
* @param string $turn_server
* @param string $turn_server_secret
*/
public function setSpreedSettings($stun_server) {
public function setSpreedSettings($stun_server, $turn_server, $turn_server_secret, $turn_server_protocols) {
$stun_server = trim($stun_server);
if ($stun_server !== "") {
if (substr($stun_server, 0, 5) === "stun:") {
Expand Down Expand Up @@ -87,8 +89,36 @@ public function setSpreedSettings($stun_server) {
);
}
}
if ($turn_server_protocols !== '') {
if (!in_array($turn_server_protocols, array('udp,tcp', 'tcp', 'udp'))) {
return array('data' =>
array('message' =>
(string) $this->l10n->t('Invalid protocols specified.')
),
'status' => 'error'
);
}
}

$this->config->setAppValue('spreed', 'stun_server', $stun_server);
$currentStunServer = $this->config->getAppValue('spreed', 'stun_server', '');
if ( $currentStunServer !== $stun_server ) {
$this->config->setAppValue('spreed', 'stun_server', $stun_server);
}

$currentTurnServer = $this->config->getAppValue('spreed', 'turn_server', '');
if ( $currentTurnServer !== $turn_server ) {
$this->config->setAppValue('spreed', 'turn_server', $turn_server);
}

$currentTurnServerSecret = $this->config->getAppValue('spreed', 'turn_server_secret', '');
if ( $currentTurnServerSecret !== $turn_server_secret ) {
$this->config->setAppValue('spreed', 'turn_server_secret', $turn_server_secret);
}

$currentTurnServerProtocols = $this->config->getAppValue('spreed', 'turn_server_protocols', '');
if ( $currentTurnServerProtocols !== $turn_server_protocols ) {
$this->config->setAppValue('spreed', 'turn_server_protocols', $turn_server_protocols);
}

return array('data' =>
array('message' =>
Expand Down
17 changes: 16 additions & 1 deletion lib/Controller/SignallingController.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@

use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IRequest;

use OCA\Spreed\Util;
use OCP\ISession;

class SignallingController extends Controller {
/** @var IConfig */
Expand All @@ -38,6 +40,10 @@ class SignallingController extends Controller {
private $dbConnection;
/** @var string */
private $userId;
/** @var ISession */
private $session;
/** @var ITimeFactory */
private $timeFactory;


/**
Expand All @@ -46,16 +52,22 @@ class SignallingController extends Controller {
* @param IConfig $config
* @param IDBConnection $connection
* @param string $UserId
* @param ISession $session
* @param ITimeFactory $timeFactory
*/
public function __construct($appName,
IRequest $request,
IConfig $config,
IDBConnection $connection,
$UserId) {
$UserId,
ISession $session,
ITimeFactory $timeFactory) {
parent::__construct($appName, $request);
$this->config = $config;
$this->dbConnection = $connection;
$this->userId = $UserId;
$this->session = $session;
$this->timeFactory = $timeFactory;
}

/**
Expand Down Expand Up @@ -106,6 +118,9 @@ public function signalling($messages) {
case 'turnservers':
$response = [];
$turnSettings = Util::getTurnSettings($this->config, $this->userId);
if(empty($turnSettings)) {
$turnSettings = Util::generateTurnSettings($this->config, $this->session, $this->timeFactory);
}
if (!empty($turnSettings)) {
$protocols = explode(",", $turnSettings['protocols']);
foreach ($protocols as $proto) {
Expand Down
2 changes: 2 additions & 0 deletions lib/Settings/Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public function __construct(IConfig $config) {
public function getForm() {
$parameters = [
'stunServer' => Util::getStunServer($this->config),
'turnServer' => $this->config->getAppValue('spreed', 'turn_server', ''),
'turnServerSecret' => $this->config->getAppValue('spreed', 'turn_server_secret', ''),
];

return new TemplateResponse('spreed', 'settings-admin', $parameters, '');
Expand Down
43 changes: 39 additions & 4 deletions lib/Util.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@

namespace OCA\Spreed;

use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
use OCP\ISession;
use OCP\IUser;

class Util {
Expand Down Expand Up @@ -52,11 +54,44 @@ public static function deleteUser(IUser $user) {
}

public static function getTurnSettings(IConfig $config, $uid) {
$value = $config->getUserValue($uid, 'spreed', 'turn_settings');
if (empty($value)) {
return array();
$value = $config->getUserValue($uid, 'spreed', 'turn_settings');
if (empty($value)) {
return array();
}
return json_decode($value, true);
return json_decode($value, true);
}

/**
* Generates a username and password for the TURN server based on the
*
* @param IConfig $config
* @param ISession $session
* @param ITimeFactory $timeFactory
* @return array
*/
public static function generateTurnSettings(IConfig $config, ISession $session, ITimeFactory $timeFactory) {
// generate from shared secret
$turnServer = $config->getAppValue('spreed', 'turn_server', '');
$turnServerSecret = $config->getAppValue('spreed', 'turn_server_secret', '');
$turnServerProtocols = $config->getAppValue('spreed', 'turn_server_protocols', '');
$sessionId = $session->get('spreed-session');

if ($turnServer === '' || $turnServerSecret === '' || $turnServerProtocols === '' || empty($session)) {
return array();
}

$time = $timeFactory->getTime();

$string = sprintf('%d:%s', $time + 3600, $sessionId);
$hashedString = hash_hmac('sha1', $string, $turnServerSecret, true);
$password = base64_encode($hashedString);

return array(
'server' => $turnServer,
'username' => $sessionId,
'password' => $password,
'protocols' => $turnServerProtocols,
);
}

}
39 changes: 34 additions & 5 deletions templates/settings-admin.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php
script('spreed', ['settings-admin']);
style('spreed', ['settings-admin']);
?>

<div id="spreed" class="section">
Expand All @@ -8,13 +9,41 @@
<span id="spreed_settings_msg" class="msg"></span>
<p>
<label for="stun_server"><?php p($l->t('STUN server')) ?></label>
<!-- TODO(fancycode): Should use CSS style to make input wider. -->
<input type="text" style="width:300px" id="stun_server"
<input type="text" id="stun_server"
name="stun_server" placeholder="stunserver:port"
value="<?php p($_['stunServer']) ?>" />
<p>
<em><?php p($l->t('The STUN server is used to determine the public address of participants behind a router.')) ?></em>
</p>
</p>
<p>
<em><?php p($l->t('The STUN server is used to determine the public address of participants behind a router.')) ?></em>
</p>
<p>
<label for="turn_server"><?php p($l->t('TURN server')) ?></label>
<input type="text" id="turn_server"
name="turn_server" placeholder="https://turn.example.org"
value="<?php p($_['turnServer']) ?>" />
</p>
<p>
<label for="turn_server_secret"><?php p($l->t('TURN server shared secret')) ?></label>
<input type="text" id="turn_server_secret"
name="turn_server_secret" placeholder="shared secret"
value="<?php p($_['turnServerSecret']) ?>" />
</p>
<p>
<label for="turn_server_protocols"><?php p($l->t('TURN server protocols')) ?></label>
<select id="turn_server_protocols" name="turn_server_protocols">
<option value="udp,tcp"
<?php p($_['turnServerProtocols'] === 'udp,tcp' ? 'selected' : '') ?>>
udp and tcp</option>
<option value="udp"
<?php p($_['turnServerProtocols'] === 'udp' ? 'selected' : '') ?>>
udp only</option>
<option value="tcp"
<?php p($_['turnServerProtocols'] === 'tcp' ? 'selected' : '') ?>>
tcp only</option>
</select>
</p>
<p>
<em><?php p($l->t('The TURN server is used to proxy the traffic from participants behind a firewall.')) ?></em>
</p>
</form>
</div>
44 changes: 43 additions & 1 deletion tests/php/UtilTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
namespace OCA\Spreed\Tests\php;

use OCA\Spreed\Util;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
use OCP\ISession;
use Test\TestCase;

class UtilTest extends TestCase {
Expand All @@ -34,7 +36,7 @@ public function setUp() {
}

public function testGetStunServer() {
$config = $this->getMock(IConfig::class);
$config = $this->createMock(IConfig::class);
$config
->expects($this->once())
->method('getAppValue')
Expand All @@ -43,4 +45,44 @@ public function testGetStunServer() {

$this->assertSame('88.198.160.129', $this->util->getStunServer($config));
}

public function testGenerateTurnSettings() {
$session = $this->createMock(ISession::class);
$session
->expects($this->once())
->method('get')
->with('spreed-session')
->willReturn('thisisalongsessionid');
$config = $this->createMock(IConfig::class);
$config
->expects($this->at(0))
->method('getAppValue')
->with('spreed', 'turn_server', '')
->willReturn('turn.example.org');
$config
->expects($this->at(1))
->method('getAppValue')
->with('spreed', 'turn_server_secret', '')
->willReturn('thisisasupersecretsecret');
$config
->expects($this->at(2))
->method('getAppValue')
->with('spreed', 'turn_server_protocols', '')
->willReturn('udp,tcp');
$time = $this->createMock(ITimeFactory::class);
$time
->expects($this->once())
->method('getTime')
->willReturn(1479743025);

$this->assertSame(array(
'server' => 'turn.example.org',
'username' => 'thisisalongsessionid',
'password' => 'MTVT2kC2SL9I81lZrI6gJznKQKk=',
'protocols' => 'udp,tcp',
), $this->util->generateTurnSettings($config, $session, $time));

// command to calculate this by manually
// echo -n "$(($(date +"%s")+3600)):USERNAME" | openssl dgst -sha1 -hmac "SECRET" -binary | base64
}
}

0 comments on commit 7ffb59b

Please sign in to comment.