diff --git a/server.conf.in b/server.conf.in index bbab48d2..3b9f0425 100644 --- a/server.conf.in +++ b/server.conf.in @@ -57,6 +57,8 @@ listen = 127.0.0.1:8080 ; See http://tools.ietf.org/html/draft-uberti-behave-turn-rest-00 for details. ; A supported TURN server is https://code.google.com/p/rfc5766-turn-server/. ;turnSecret = the-default-turn-shared-secret-do-not-keep +; Enable adding TURN servers inside of the client side webui under settings +;clientSideTurn = false ; Enable renegotiation support. Set to true to tell clients that they can ; renegotiate peer connections when required. Firefox support is not complete, ; so do not enable if you want compatibility with Firefox clients. diff --git a/src/app/spreed-webrtc-server/config.go b/src/app/spreed-webrtc-server/config.go index 89a14c54..08f2c9dc 100644 --- a/src/app/spreed-webrtc-server/config.go +++ b/src/app/spreed-webrtc-server/config.go @@ -39,6 +39,7 @@ type Config struct { Renegotiation bool // Renegotiation flag StunURIs []string // STUN server URIs TurnURIs []string // TURN server URIs + ClientSideTurn bool // Enable TURN server customization under settings in web ui Tokens bool // True when we got a tokens file Version string // Server version number UsersEnabled bool // Flag if users are enabled @@ -116,6 +117,7 @@ func NewConfig(container phoenix.Container, tokens bool) *Config { Renegotiation: container.GetBoolDefault("app", "renegotiation", false), StunURIs: stunURIs, TurnURIs: turnURIs, + ClientSideTurn: container.GetBoolDefault("app", "clientSideTurn", false), Tokens: tokens, Version: version, UsersEnabled: container.GetBoolDefault("users", "enabled", false), diff --git a/static/js/controllers/appcontroller.js b/static/js/controllers/appcontroller.js index 65e10948..27f980a8 100644 --- a/static/js/controllers/appcontroller.js +++ b/static/js/controllers/appcontroller.js @@ -57,6 +57,13 @@ define(["jquery", "angular", "underscore"], function($, angular, _) { videoNoiseReduction: false, preferVideoSendCodecVP9: false }, + turn: { + clientSideTurn: { + urls: [], + username: '', + password: '' + } + }, sound: { incomingMessages: true, incomingCall: true, diff --git a/static/js/directives/settings.js b/static/js/directives/settings.js index 43c9f9a2..324c90fd 100644 --- a/static/js/directives/settings.js +++ b/static/js/directives/settings.js @@ -55,7 +55,7 @@ define(['jquery', 'underscore', 'text!partials/settings.html'], function($, _, t return ["$compile", "mediaStream", function($compile, mediaStream) { - var controller = ['$scope', 'desktopNotify', 'mediaSources', 'safeApply', 'availableLanguages', 'translation', 'localStorage', 'userSettingsData', 'constraints', 'appData', '$timeout', function($scope, desktopNotify, mediaSources, safeApply, availableLanguages, translation, localStorage, userSettingsData, constraints, appData, $timeout) { + var controller = ['$scope', 'desktopNotify', 'mediaSources', 'safeApply', 'availableLanguages', 'translation', 'localStorage', 'userSettingsData', 'constraints', 'appData', '$timeout', 'turnSettings', function($scope, desktopNotify, mediaSources, safeApply, availableLanguages, translation, localStorage, userSettingsData, constraints, appData, $timeout, turnSettings) { $scope.layout.settings = false; $scope.showAdvancedSettings = true; @@ -70,6 +70,7 @@ define(['jquery', 'underscore', 'text!partials/settings.html'], function($, _, t $scope.withUsers = mediaStream.config.UsersEnabled; $scope.withUsersRegistration = mediaStream.config.UsersAllowRegistration; $scope.withUsersMode = mediaStream.config.UsersMode; + $scope.clientSideTurn = turnSettings.clientSideTurn(); _.each(availableLanguages, function(name, code) { $scope.availableLanguages.push({ @@ -90,6 +91,7 @@ define(['jquery', 'underscore', 'text!partials/settings.html'], function($, _, t if (form.$valid && form.$dirty) { var user = $scope.user; $scope.update(user); + turnSettings.update($scope.user.settings.turn.clientSideTurn); if ($scope.rememberSettings) { userSettingsData.save(user); localStorage.setItem("mediastream-language", user.settings.language || ""); diff --git a/static/js/services/services.js b/static/js/services/services.js index 4fa9919a..35a1abe3 100644 --- a/static/js/services/services.js +++ b/static/js/services/services.js @@ -70,7 +70,8 @@ define([ 'services/mediadevices', 'services/sandbox', 'services/dummystream', - 'services/usermedia'], function(_, + 'services/usermedia', + 'services/turnsettings'], function(_, desktopNotify, playSound, safeApply, @@ -118,7 +119,8 @@ modules, mediaDevices, sandbox, dummyStream, -userMedia) { +userMedia, +turnSettings) { var services = { desktopNotify: desktopNotify, @@ -168,7 +170,8 @@ userMedia) { mediaDevices: mediaDevices, sandbox: sandbox, dummyStream: dummyStream, - userMedia: userMedia + userMedia: userMedia, + turnSettings: turnSettings }; var initialize = function(angModule) { diff --git a/static/js/services/turnsettings.js b/static/js/services/turnsettings.js new file mode 100644 index 00000000..4ba32c89 --- /dev/null +++ b/static/js/services/turnsettings.js @@ -0,0 +1,72 @@ +/* + * Spreed WebRTC. + * Copyright (C) 2013-2015 struktur AG + * + * This file is part of Spreed WebRTC. + * + * 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 . + * + */ + +"use strict"; +define([], function() { + + // turnSettings + // Service to correctly sync client and server side TURN settings to contraints.js + // See contraints.js for actual TURN configuration in use for a connection + return ['mediaStream', 'appData', 'constraints', function(mediaStream, appData, constraints) { + + var clientSideTurn = mediaStream.config.ClientSideTurn; + var turnConfigServer = null; + + // @param Object config Turn configuration object + // @param Array config.urls + // @param String config.username + // @param String config.password + var updateTurnSettings = function(config) { + if (!clientSideTurn) { + return; + } + if (config.urls.length) { + constraints.turn(config); + // Apply original server side TURN settings when user removes client side TURN settings + } else if (turnConfigServer && turnConfigServer.urls.length) { + constraints.turn(turnConfigServer); + } + }; + + if (clientSideTurn) { + // Overwrite server Turn settings with user settings when loading app + appData.e.one("userSettingsLoaded", function(event, loadedUser, user) { + if (user) { + updateTurnSettings(user.settings.turn.clientSideTurn); + } + }); + // Get server site TURN settings + mediaStream.api.e.on("received.self", function(event, data) { + if (data.Turn.urls && data.Turn.urls.length) { + turnConfigServer = data.Turn; + } + }); + } + + return { + clientSideTurn: function() { + return clientSideTurn; + }, + update: updateTurnSettings + }; + + }]; +}); diff --git a/static/partials/settings.html b/static/partials/settings.html index e2588b98..94319d77 100644 --- a/static/partials/settings.html +++ b/static/partials/settings.html @@ -294,6 +294,32 @@ +
+ {{_('Turn')}} +
+

{{_('Normally a TURN server is not required. Only use in cases when peer to peer connections are blocked by a firewall.')}}

+
+ +
+ + {{_('Comma separated list of urls')}} +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ @@ -325,4 +351,4 @@ - \ No newline at end of file +