From 7679ee7321ff588a84edab31507185d2cee80fc7 Mon Sep 17 00:00:00 2001
From: David Baker <dbkr@matrix.org>
Date: Wed, 24 Sep 2014 16:07:33 +0100
Subject: Hopefully implement turn in the web client (probably wrong for
 Firefox because Firefox is a special snowflake)

---
 webclient/components/matrix/matrix-call.js    | 33 ++++++++++++++++++++++++---
 webclient/components/matrix/matrix-service.js |  4 ++++
 2 files changed, 34 insertions(+), 3 deletions(-)

(limited to 'webclient/components')

diff --git a/webclient/components/matrix/matrix-call.js b/webclient/components/matrix/matrix-call.js
index 7b5d9cffef..888f853472 100644
--- a/webclient/components/matrix/matrix-call.js
+++ b/webclient/components/matrix/matrix-call.js
@@ -49,6 +49,15 @@ angular.module('MatrixCall', [])
 .factory('MatrixCall', ['matrixService', 'matrixPhoneService', '$rootScope', '$timeout', function MatrixCallFactory(matrixService, matrixPhoneService, $rootScope, $timeout) {
     $rootScope.isWebRTCSupported = isWebRTCSupported();
 
+    // FIXME: we should prevent any class from being placed or accepted before this has finished
+    matrixService.getTurnServer().then(function(response) {
+        console.log("Got TURN URIs: "+response.data.uris);
+        MatrixCall.turnServer = response.data;
+    }, function(error) {
+        console.log("Failed to get TURN URIs");
+        MatrixCall.turnServer = {};
+    });
+
     var MatrixCall = function(room_id) {
         this.room_id = room_id;
         this.call_id = "c" + new Date().getTime();
@@ -69,12 +78,30 @@ angular.module('MatrixCall', [])
     MatrixCall.CALL_TIMEOUT = 60000;
 
     MatrixCall.prototype.createPeerConnection = function() {
-        var stunServer = 'stun:stun.l.google.com:19302';
         var pc;
         if (window.mozRTCPeerConnection) {
-            pc = new window.mozRTCPeerConnection({'url': stunServer});
+            var iceServers = [];
+            if (MatrixCall.turnServer) {
+                iceServers.push({
+                    'urls': MatrixCall.turnServer.uris,
+                    'username': MatrixCall.turnServer.username,
+                    'credential': MatrixCall.turnServer.password,
+                });
+            }
+          
+            pc = new window.mozRTCPeerConnection({"iceServers":iceServers});
+            //pc = new window.mozRTCPeerConnection({'url': stunServer});
         } else {
-            pc = new window.RTCPeerConnection({"iceServers":[{"urls":"stun:stun.l.google.com:19302"}]});
+            var iceServers = [];
+            if (MatrixCall.turnServer) {
+                iceServers.push({
+                    'urls': MatrixCall.turnServer.uris,
+                    'username': MatrixCall.turnServer.username,
+                    'credential': MatrixCall.turnServer.password,
+                });
+            }
+          
+            pc = new window.RTCPeerConnection({"iceServers":iceServers});
         }
         var self = this;
         pc.oniceconnectionstatechange = function() { self.onIceConnectionStateChanged(); };
diff --git a/webclient/components/matrix/matrix-service.js b/webclient/components/matrix/matrix-service.js
index 069e02e939..69e6caccd3 100644
--- a/webclient/components/matrix/matrix-service.js
+++ b/webclient/components/matrix/matrix-service.js
@@ -762,6 +762,10 @@ angular.module('matrixService', [])
             var deferred = $q.defer();
             deferred.reject({data:{error: "Invalid room: " + room_id}});
             return deferred.promise;
+        },
+
+        getTurnServer: function() {
+            return doRequest("GET", "/voip/turnServers");
         }
 
     };
-- 
cgit 1.5.1


From 7dc7c53029fccbccf291ca4c299fccfdeb8e19fb Mon Sep 17 00:00:00 2001
From: David Baker <dbkr@matrix.org>
Date: Wed, 24 Sep 2014 17:28:47 +0200
Subject: The REST API spec only alows for returning a single server so name
 the endpoint appropriately.

---
 synapse/rest/voip.py                          | 2 +-
 webclient/components/matrix/matrix-service.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

(limited to 'webclient/components')

diff --git a/synapse/rest/voip.py b/synapse/rest/voip.py
index a3a8842cb6..7260ff0e8e 100644
--- a/synapse/rest/voip.py
+++ b/synapse/rest/voip.py
@@ -24,7 +24,7 @@ import base64
 
 
 class VoipRestServlet(RestServlet):
-    PATTERN = client_path_pattern("/voip/turnServers$")
+    PATTERN = client_path_pattern("/voip/turnServer$")
 
     @defer.inlineCallbacks
     def on_GET(self, request):
diff --git a/webclient/components/matrix/matrix-service.js b/webclient/components/matrix/matrix-service.js
index 69e6caccd3..cb827a0b4d 100644
--- a/webclient/components/matrix/matrix-service.js
+++ b/webclient/components/matrix/matrix-service.js
@@ -765,7 +765,7 @@ angular.module('matrixService', [])
         },
 
         getTurnServer: function() {
-            return doRequest("GET", "/voip/turnServers");
+            return doRequest("GET", "/voip/turnServer");
         }
 
     };
-- 
cgit 1.5.1


From 6806caffc7d10ed643a6bc80d53a0fe76becd6f5 Mon Sep 17 00:00:00 2001
From: David Baker <dbkr@matrix.org>
Date: Wed, 24 Sep 2014 17:57:34 +0100
Subject: Refresh turn server before the ttl runs out. Support firefox.

---
 webclient/components/matrix/matrix-call.js | 37 +++++++++++++++++++-----------
 1 file changed, 23 insertions(+), 14 deletions(-)

(limited to 'webclient/components')

diff --git a/webclient/components/matrix/matrix-call.js b/webclient/components/matrix/matrix-call.js
index 888f853472..5c7902f874 100644
--- a/webclient/components/matrix/matrix-call.js
+++ b/webclient/components/matrix/matrix-call.js
@@ -49,15 +49,6 @@ angular.module('MatrixCall', [])
 .factory('MatrixCall', ['matrixService', 'matrixPhoneService', '$rootScope', '$timeout', function MatrixCallFactory(matrixService, matrixPhoneService, $rootScope, $timeout) {
     $rootScope.isWebRTCSupported = isWebRTCSupported();
 
-    // FIXME: we should prevent any class from being placed or accepted before this has finished
-    matrixService.getTurnServer().then(function(response) {
-        console.log("Got TURN URIs: "+response.data.uris);
-        MatrixCall.turnServer = response.data;
-    }, function(error) {
-        console.log("Failed to get TURN URIs");
-        MatrixCall.turnServer = {};
-    });
-
     var MatrixCall = function(room_id) {
         this.room_id = room_id;
         this.call_id = "c" + new Date().getTime();
@@ -75,6 +66,22 @@ angular.module('MatrixCall', [])
 
     }
 
+    MatrixCall.getTurnServer = function() {
+        matrixService.getTurnServer().then(function(response) {
+            console.log("Got TURN URIs: "+response.data.uris);
+            MatrixCall.turnServer = response.data;
+            // re-fetch when we're about to reach the TTL
+            $timeout(MatrixCall.getTurnServer, MatrixCall.turnServer.ttl * 1000 * 0.9);
+        }, function(error) {
+            console.log("Failed to get TURN URIs");
+            MatrixCall.turnServer = {};
+            $timeout(MatrixCall.getTurnServer, 60000);
+        });
+    }
+
+    // FIXME: we should prevent any class from being placed or accepted before this has finished
+    MatrixCall.getTurnServer();
+
     MatrixCall.CALL_TIMEOUT = 60000;
 
     MatrixCall.prototype.createPeerConnection = function() {
@@ -82,11 +89,13 @@ angular.module('MatrixCall', [])
         if (window.mozRTCPeerConnection) {
             var iceServers = [];
             if (MatrixCall.turnServer) {
-                iceServers.push({
-                    'urls': MatrixCall.turnServer.uris,
-                    'username': MatrixCall.turnServer.username,
-                    'credential': MatrixCall.turnServer.password,
-                });
+                for (var i = 0; i < MatrixCall.turnServer.uris.length; i++) {
+                    iceServers.push({
+                        'url': MatrixCall.turnServer.uris[i],
+                        'username': MatrixCall.turnServer.username,
+                        'credential': MatrixCall.turnServer.password,
+                    });
+               }
             }
           
             pc = new window.mozRTCPeerConnection({"iceServers":iceServers});
-- 
cgit 1.5.1


From c0936b103c215aef12d64fbb490d8daef07903c4 Mon Sep 17 00:00:00 2001
From: David Baker <dbkr@matrix.org>
Date: Thu, 25 Sep 2014 11:13:32 +0100
Subject: Add stun server fallback and I-told-you-so message if we get no TURN
 server and the connection fails.

---
 webclient/components/matrix/matrix-call.js | 50 ++++++++++++++++++++----------
 webclient/index.html                       |  2 +-
 2 files changed, 34 insertions(+), 18 deletions(-)

(limited to 'webclient/components')

diff --git a/webclient/components/matrix/matrix-call.js b/webclient/components/matrix/matrix-call.js
index 5c7902f874..3e8811e5fc 100644
--- a/webclient/components/matrix/matrix-call.js
+++ b/webclient/components/matrix/matrix-call.js
@@ -68,10 +68,16 @@ angular.module('MatrixCall', [])
 
     MatrixCall.getTurnServer = function() {
         matrixService.getTurnServer().then(function(response) {
-            console.log("Got TURN URIs: "+response.data.uris);
-            MatrixCall.turnServer = response.data;
-            // re-fetch when we're about to reach the TTL
-            $timeout(MatrixCall.getTurnServer, MatrixCall.turnServer.ttl * 1000 * 0.9);
+            if (response.data.uris) {
+                console.log("Got TURN URIs: "+response.data.uris);
+                MatrixCall.turnServer = response.data;
+                $rootScope.haveTurn = true;
+                // re-fetch when we're about to reach the TTL
+                $timeout(MatrixCall.getTurnServer, MatrixCall.turnServer.ttl * 1000 * 0.9);
+            } else {
+                console.log("Got no TURN URIs from HS");
+                $rootScope.haveTurn = false;
+            }
         }, function(error) {
             console.log("Failed to get TURN URIs");
             MatrixCall.turnServer = {};
@@ -83,31 +89,41 @@ angular.module('MatrixCall', [])
     MatrixCall.getTurnServer();
 
     MatrixCall.CALL_TIMEOUT = 60000;
+    MatrixCall.FALLBACK_STUN_SERVER = 'stun:stun.l.google.com:19302';
 
     MatrixCall.prototype.createPeerConnection = function() {
         var pc;
         if (window.mozRTCPeerConnection) {
             var iceServers = [];
             if (MatrixCall.turnServer) {
-                for (var i = 0; i < MatrixCall.turnServer.uris.length; i++) {
-                    iceServers.push({
-                        'url': MatrixCall.turnServer.uris[i],
-                        'username': MatrixCall.turnServer.username,
-                        'credential': MatrixCall.turnServer.password,
-                    });
-               }
+                if (MatrixCall.turnServer.uris) {
+                    for (var i = 0; i < MatrixCall.turnServer.uris.length; i++) {
+                        iceServers.push({
+                            'url': MatrixCall.turnServer.uris[i],
+                            'username': MatrixCall.turnServer.username,
+                            'credential': MatrixCall.turnServer.password,
+                        });
+                    }
+                } else {
+                    console.log("No TURN server: using fallback STUN server");
+                    iceServers.push({ 'url' : MatrixCall.FALLBACK_STUN_SERVER });
+                }
             }
           
             pc = new window.mozRTCPeerConnection({"iceServers":iceServers});
-            //pc = new window.mozRTCPeerConnection({'url': stunServer});
         } else {
             var iceServers = [];
             if (MatrixCall.turnServer) {
-                iceServers.push({
-                    'urls': MatrixCall.turnServer.uris,
-                    'username': MatrixCall.turnServer.username,
-                    'credential': MatrixCall.turnServer.password,
-                });
+                if (MatrixCall.turnServer.uris) {
+                    iceServers.push({
+                        'urls': MatrixCall.turnServer.uris,
+                        'username': MatrixCall.turnServer.username,
+                        'credential': MatrixCall.turnServer.password,
+                    });
+                } else {
+                    console.log("No TURN server: using fallback STUN server");
+                    iceServers.push({ 'urls' : MatrixCall.FALLBACK_STUN_SERVER });
+                }
             }
           
             pc = new window.RTCPeerConnection({"iceServers":iceServers});
diff --git a/webclient/index.html b/webclient/index.html
index 411c2762d3..f233919e3d 100644
--- a/webclient/index.html
+++ b/webclient/index.html
@@ -69,7 +69,7 @@
                         <span ng-show="currentCall.state == 'ringing' && currentCall && currentCall.type == 'voice'">Incoming Voice Call</span>
                         <span ng-show="currentCall.state == 'connecting'">Call Connecting...</span>
                         <span ng-show="currentCall.state == 'connected'">Call Connected</span>
-                        <span ng-show="currentCall.state == 'ended' && currentCall.hangupReason == 'ice_failed'">Media Connection Failed</span>
+                        <span ng-show="currentCall.state == 'ended' && currentCall.hangupReason == 'ice_failed'">Media Connection Failed{{ haveTurn ? "" : " (VoIP relaying unsupported by Home Server)" }}</span>
                         <span ng-show="currentCall.state == 'ended' && !currentCall.hangupReason && !currentCall.didConnect && currentCall.direction == 'outbound' && currentCall.hangupParty == 'remote'">Call Rejected</span>
                         <span ng-show="currentCall.state == 'ended' && !currentCall.hangupReason && !currentCall.didConnect && currentCall.direction == 'outbound' && currentCall.hangupParty == 'local'">Call Canceled</span>
                         <span ng-show="currentCall.state == 'ended' && currentCall.hangupReason == 'invite_timeout' && !currentCall.didConnect && currentCall.direction == 'outbound' && currentCall.hangupParty == 'local'">User Not Responding</span>
-- 
cgit 1.5.1