diff --git a/synapse/config/homeserver.py b/synapse/config/homeserver.py
index 4b810a2302..5a11fd6c76 100644
--- a/synapse/config/homeserver.py
+++ b/synapse/config/homeserver.py
@@ -21,11 +21,12 @@ from .ratelimiting import RatelimitConfig
from .repository import ContentRepositoryConfig
from .captcha import CaptchaConfig
from .email import EmailConfig
+from .voip import VoipConfig
class HomeServerConfig(TlsConfig, ServerConfig, DatabaseConfig, LoggingConfig,
RatelimitConfig, ContentRepositoryConfig, CaptchaConfig,
- EmailConfig):
+ EmailConfig, VoipConfig):
pass
diff --git a/synapse/config/voip.py b/synapse/config/voip.py
new file mode 100644
index 0000000000..c5131d9bcd
--- /dev/null
+++ b/synapse/config/voip.py
@@ -0,0 +1,41 @@
+# Copyright 2014 OpenMarket Ltd
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ._base import Config
+
+
+class VoipConfig(Config):
+
+ def __init__(self, args):
+ super(VoipConfig, self).__init__(args)
+ self.turn_uris = args.turn_uris.split(",") if args.turn_uris else None
+ self.turn_shared_secret = args.turn_shared_secret
+ self.turn_user_lifetime = args.turn_user_lifetime
+
+ @classmethod
+ def add_arguments(cls, parser):
+ super(VoipConfig, cls).add_arguments(parser)
+ group = parser.add_argument_group("voip")
+ group.add_argument(
+ "--turn-uris", type=str, default=None,
+ help="The public URIs of the TURN server to give to clients"
+ )
+ group.add_argument(
+ "--turn-shared-secret", type=str, default=None,
+ help="The shared secret used to compute passwords for the TURN server"
+ )
+ group.add_argument(
+ "--turn-user-lifetime", type=int, default=(1000 * 60 * 60),
+ help="How long generated TURN credentials last, in ms"
+ )
diff --git a/synapse/rest/__init__.py b/synapse/rest/__init__.py
index ed785cfbd5..3b9aa59733 100644
--- a/synapse/rest/__init__.py
+++ b/synapse/rest/__init__.py
@@ -15,7 +15,7 @@
from . import (
- room, events, register, login, profile, presence, initial_sync, directory
+ room, events, register, login, profile, presence, initial_sync, directory, voip
)
@@ -42,3 +42,4 @@ class RestServletFactory(object):
presence.register_servlets(hs, client_resource)
initial_sync.register_servlets(hs, client_resource)
directory.register_servlets(hs, client_resource)
+ voip.register_servlets(hs, client_resource)
diff --git a/synapse/rest/voip.py b/synapse/rest/voip.py
new file mode 100644
index 0000000000..2e4627606f
--- /dev/null
+++ b/synapse/rest/voip.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+# Copyright 2014 OpenMarket Ltd
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from twisted.internet import defer
+
+from base import RestServlet, client_path_pattern
+
+
+import hmac
+import hashlib
+import base64
+
+
+class VoipRestServlet(RestServlet):
+ PATTERN = client_path_pattern("/voip/turnServer$")
+
+ @defer.inlineCallbacks
+ def on_GET(self, request):
+ auth_user = yield self.auth.get_user_by_req(request)
+
+ turnUris = self.hs.config.turn_uris
+ turnSecret = self.hs.config.turn_shared_secret
+ userLifetime = self.hs.config.turn_user_lifetime
+ if not turnUris or not turnSecret or not userLifetime:
+ defer.returnValue( (200, {}) )
+
+ expiry = self.hs.get_clock().time_msec() + userLifetime
+ username = "%d:%s" % (expiry, auth_user.to_string())
+
+ mac = hmac.new(turnSecret, msg=username, digestmod=hashlib.sha1)
+ # We need to use standard base64 encoding here, *not* syutil's encode_base64
+ # because we need to add the standard padding to get the same result as the
+ # TURN server.
+ password = base64.b64encode(mac.digest())
+
+ defer.returnValue( (200, {
+ 'username': username,
+ 'password': password,
+ 'ttl': userLifetime / 1000,
+ 'uris': turnUris,
+ }) )
+
+ def on_OPTIONS(self, request):
+ return (200, {})
+
+
+def register_servlets(hs, http_server):
+ VoipRestServlet(hs).register(http_server)
|