Bug 928060: Parse ?transport=[udp|tcp] in TURN uri. r=ehsan
authorJan-Ivar Bruaroey <jib@mozilla.com>
Fri, 18 Oct 2013 18:14:21 -0400
changeset 151464 50ad84fae4019eeebc209ba6cd43cc3e6e01f034
parent 151463 0d316980f21f45f47daae605bf632348ad521136
child 151465 0ddbf9b3b20c8f4a799cf36a1778f55ee759b17b
push id35179
push userrjesup@wgate.com
push dateSun, 20 Oct 2013 09:14:42 +0000
treeherdermozilla-inbound@50ad84fae401 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs928060
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 928060: Parse ?transport=[udp|tcp] in TURN uri. r=ehsan
media/mtransport/nricectx.h
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
--- a/media/mtransport/nricectx.h
+++ b/media/mtransport/nricectx.h
@@ -76,16 +76,19 @@ typedef struct nr_ice_turn_server_ nr_ic
 typedef struct nr_resolver_ nr_resolver;
 
 typedef void* NR_SOCKET;
 
 namespace mozilla {
 
 class NrIceMediaStream;
 
+const std::string kNrIceTransportUdp("udp");
+const std::string kNrIceTransportTcp("tcp");
+
 class NrIceStunServer {
  public:
   NrIceStunServer(const PRNetAddr& addr) : has_addr_(true) {
     memcpy(&addr_, &addr, sizeof(addr));
   }
 
    // The main function to use. Will take either an address or a hostname.
   static NrIceStunServer* Create(const std::string& addr, uint16_t port) {
@@ -129,17 +132,19 @@ class NrIceStunServer {
   uint16_t port_;
   PRNetAddr addr_;
 };
 
 class NrIceTurnServer : public NrIceStunServer {
  public:
   static NrIceTurnServer *Create(const std::string& addr, uint16_t port,
                                  const std::string& username,
-                                 const std::vector<unsigned char>& password) {
+                                 const std::vector<unsigned char>& password,
+                                 const std::string& transport = kNrIceTransportUdp) {
+    // TODO: Bug 906968 - Support TCP
     ScopedDeletePtr<NrIceTurnServer> server(
         new NrIceTurnServer(username, password));
 
     nsresult rv = server->Init(addr, port);
     if (NS_FAILED(rv))
       return nullptr;
 
     return server.forget();
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -568,44 +568,62 @@ PeerConnectionImpl::ConvertRTCConfigurat
 {
 #ifdef MOZILLA_INTERNAL_API
   if (!aSrc.mIceServers.WasPassed()) {
     return NS_OK;
   }
   for (uint32_t i = 0; i < aSrc.mIceServers.Value().Length(); i++) {
     const RTCIceServer& server = aSrc.mIceServers.Value()[i];
     NS_ENSURE_TRUE(server.mUrl.WasPassed(), NS_ERROR_UNEXPECTED);
+
+    // Without STUN/TURN handlers, NS_NewURI returns nsSimpleURI rather than
+    // nsStandardURL. To parse STUN/TURN URI's to spec
+    // http://tools.ietf.org/html/draft-nandakumar-rtcweb-stun-uri-02#section-3
+    // http://tools.ietf.org/html/draft-petithuguenin-behave-turn-uri-03#section-3
+    // we parse out the query-string, and use ParseAuthority() on the rest
     nsRefPtr<nsIURI> url;
     nsresult rv = NS_NewURI(getter_AddRefs(url), server.mUrl.Value());
     NS_ENSURE_SUCCESS(rv, rv);
     bool isStun = false, isStuns = false, isTurn = false, isTurns = false;
     url->SchemeIs("stun", &isStun);
     url->SchemeIs("stuns", &isStuns);
     url->SchemeIs("turn", &isTurn);
     url->SchemeIs("turns", &isTurns);
     if (!(isStun || isStuns || isTurn || isTurns)) {
       return NS_ERROR_FAILURE;
     }
     nsAutoCString spec;
     rv = url->GetSpec(spec);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    // TODO(jib@mozilla.com): Revisit once nsURI has STUN host+port (Bug 833509)
+    // TODO(jib@mozilla.com): Revisit once nsURI supports STUN/TURN (Bug 833509)
     int32_t port;
     nsAutoCString host;
+    nsAutoCString transport;
     {
       uint32_t hostPos;
       int32_t hostLen;
       nsAutoCString path;
       rv = url->GetPath(path);
       NS_ENSURE_SUCCESS(rv, rv);
 
-      // Tolerate '?transport=udp' by stripping it.
+      // Tolerate query-string + parse 'transport=[udp|tcp]' by hand.
       int32_t questionmark = path.FindChar('?');
       if (questionmark >= 0) {
+        const nsCString match = NS_LITERAL_CSTRING("transport=");
+
+        for (int32_t i = questionmark, endPos; i >= 0; i = endPos) {
+          endPos = path.FindCharInSet("&", i + 1);
+          const nsDependentCSubstring fieldvaluepair = Substring(path, i + 1,
+                                                                 endPos);
+          if (StringBeginsWith(fieldvaluepair, match)) {
+            transport = Substring(fieldvaluepair, match.Length());
+            ToLowerCase(transport);
+          }
+        }
         path.SetLength(questionmark);
       }
 
       rv = net_GetAuthURLParser()->ParseAuthority(path.get(), path.Length(),
                                                   nullptr,  nullptr,
                                                   nullptr,  nullptr,
                                                   &hostPos,  &hostLen, &port);
       NS_ENSURE_SUCCESS(rv, rv);
@@ -620,17 +638,19 @@ PeerConnectionImpl::ConvertRTCConfigurat
       port = (isStuns || isTurns)? 5349 : 3478;
 
     if (isTurn || isTurns) {
       NS_ConvertUTF16toUTF8 credential(server.mCredential);
       NS_ConvertUTF16toUTF8 username(server.mUsername);
 
       if (!aDst->addTurnServer(host.get(), port,
                                username.get(),
-                               credential.get())) {
+                               credential.get(),
+                               (transport.IsEmpty() ?
+                                kNrIceTransportUdp : transport.get()))) {
         return NS_ERROR_FAILURE;
       }
     } else {
       if (!aDst->addStunServer(host.get(), port)) {
         return NS_ERROR_FAILURE;
       }
     }
   }
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
@@ -121,23 +121,25 @@ public:
     if (!server) {
       return false;
     }
     addStunServer(*server);
     return true;
   }
   bool addTurnServer(const std::string& addr, uint16_t port,
                      const std::string& username,
-                     const std::string& pwd)
+                     const std::string& pwd,
+                     const std::string& transport)
   {
     // TODO(ekr@rtfm.com): Need support for SASLprep for
     // username and password. Bug # ???
     std::vector<unsigned char> password(pwd.begin(), pwd.end());
 
-    NrIceTurnServer* server(NrIceTurnServer::Create(addr, port, username, password));
+    NrIceTurnServer* server(NrIceTurnServer::Create(addr, port, username, password,
+                                                    transport));
     if (!server) {
       return false;
     }
     addTurnServer(*server);
     return true;
   }
   void addStunServer(const NrIceStunServer& server) { mStunServers.push_back (server); }
   void addTurnServer(const NrIceTurnServer& server) { mTurnServers.push_back (server); }