Bug 1189040: add a whitelist for network interfaces to use with ICE/webrtc r=ekr a=ritu
authorRandell Jesup <rjesup@jesup.org>
Wed, 12 Aug 2015 19:45:36 -0400
changeset 288813 8618de5f122fea2c3b6ee68c275fd9d422417d64
parent 288812 2bac25974183b0b48faf5513d4de2ef124dfefec
child 288814 5ca63e954c03f5fd007a6dc8be5d3d5291e0a31b
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersekr, ritu
bugs1189040
milestone42.0a2
Bug 1189040: add a whitelist for network interfaces to use with ICE/webrtc r=ekr a=ritu
media/mtransport/nricectx.cpp
media/mtransport/third_party/nICEr/src/ice/ice_ctx.c
media/mtransport/third_party/nICEr/src/ice/ice_ctx.h
media/mtransport/third_party/nICEr/src/ice/ice_reg.h
modules/libpref/init/all.js
--- a/media/mtransport/nricectx.cpp
+++ b/media/mtransport/nricectx.cpp
@@ -430,16 +430,17 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const 
       NR_reg_set_uchar((char *)"ice.pref.interface.virbr0", 233);
       NR_reg_set_uchar((char *)"ice.pref.interface.wlan0", 232);
     }
 
     int32_t stun_client_maximum_transmits = 7;
     int32_t ice_trickle_grace_period = 5000;
     int32_t ice_tcp_so_sock_count = 3;
     int32_t ice_tcp_listen_backlog = 10;
+    nsAutoCString force_net_interface;
 #ifndef MOZILLA_XPCOMRT_API
     nsresult res;
     nsCOMPtr<nsIPrefService> prefs =
       do_GetService("@mozilla.org/preferences-service;1", &res);
 
     if (NS_SUCCEEDED(res)) {
       nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
       if (branch) {
@@ -450,16 +451,19 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const 
             "media.peerconnection.ice.trickle_grace_period",
             &ice_trickle_grace_period);
         branch->GetIntPref(
             "media.peerconnection.ice.tcp_so_sock_count",
             &ice_tcp_so_sock_count);
         branch->GetIntPref(
             "media.peerconnection.ice.tcp_listen_backlog",
             &ice_tcp_listen_backlog);
+        branch->GetCharPref(
+            "media.peerconnection.ice.force_interface",
+            getter_Copies(force_net_interface));
       }
     }
 #endif
     NR_reg_set_uint4((char *)"stun.client.maximum_transmits",
                      stun_client_maximum_transmits);
     NR_reg_set_uint4((char *)NR_ICE_REG_TRICKLE_GRACE_PERIOD,
                      ice_trickle_grace_period);
     NR_reg_set_int4((char *)NR_ICE_REG_ICE_TCP_SO_SOCK_COUNT,
@@ -473,16 +477,21 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const 
 
     if (allow_loopback) {
       NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LOOPBACK_ADDRS, 1);
     }
 
     if (allow_link_local) {
       NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LINK_LOCAL_ADDRS, 1);
     }
+    if (force_net_interface.Length() > 0) {
+      // Stupid cast.... but needed
+      const nsCString& flat = PromiseFlatCString(static_cast<nsACString&>(force_net_interface));
+      NR_reg_set_string((char *)NR_ICE_REG_PREF_FORCE_INTERFACE_NAME, const_cast<char*>(flat.get()));
+    }
   }
 
   // Create the ICE context
   int r;
 
   UINT4 flags = offerer ? NR_ICE_CTX_FLAGS_OFFERER:
       NR_ICE_CTX_FLAGS_ANSWERER;
   flags |= NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION;
--- a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c
@@ -310,17 +310,17 @@ int nr_ice_fetch_turn_servers(int ct, nr
   abort:
     RFREE(data.data);
     RFREE(addr);
     if (_status) RFREE(servers);
     return(_status);
   }
 #endif /* USE_TURN */
 
-#define MAXADDRS 100 // Ridiculously high
+#define MAXADDRS 100 /* Ridiculously high */
 int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp)
   {
     nr_ice_ctx *ctx=0;
     int r,_status;
     char buf[100];
 
     if(r=r_log_register("ice", &LOG_ICE))
       ABORT(r);
@@ -394,16 +394,24 @@ int nr_ice_ctx_create(char *label, UINT4
 #endif /* USE_TURN */
 
 
     ctx->Ta = 20;
 
     if (r=nr_socket_factory_create_int(NULL, &default_socket_factory_vtbl, &ctx->socket_factory))
       ABORT(r);
 
+    if ((r=NR_reg_get_string((char *)NR_ICE_REG_PREF_FORCE_INTERFACE_NAME, ctx->force_net_interface, sizeof(ctx->force_net_interface)))) {
+      if (r == R_NOT_FOUND) {
+        ctx->force_net_interface[0] = 0;
+      } else {
+        ABORT(r);
+      }
+    }
+
     STAILQ_INIT(&ctx->streams);
     STAILQ_INIT(&ctx->sockets);
     STAILQ_INIT(&ctx->foundations);
     STAILQ_INIT(&ctx->peers);
     STAILQ_INIT(&ctx->ids);
 
     *ctxp=ctx;
 
@@ -486,17 +494,17 @@ void nr_ice_gather_finished_cb(NR_SOCKET
 
     assert(cb_arg);
     if (!cb_arg)
       return;
     ctx = cand->ctx;
 
     ctx->uninitialized_candidates--;
 
-    // Avoid the need for yet another initialization function
+    /* Avoid the need for yet another initialization function */
     if (cand->state == NR_ICE_CAND_STATE_INITIALIZING && cand->type == HOST)
       cand->state = NR_ICE_CAND_STATE_INITIALIZED;
 
     if (cand->state == NR_ICE_CAND_STATE_INITIALIZED) {
       int was_pruned = 0;
 
       if (r=nr_ice_component_maybe_prune_candidate(ctx, cand->component,
                                                    cand, &was_pruned)) {
@@ -560,16 +568,50 @@ int nr_ice_gather(nr_ice_ctx *ctx, NR_as
 
     if (!ctx->local_addrs) {
       /* First, gather all the local addresses we have */
       if(r=nr_stun_find_local_addresses(addrs,MAXADDRS,&addr_ct)) {
         r_log(LOG_ICE,LOG_ERR,"ICE(%s): unable to find local addresses",ctx->label);
         ABORT(r);
       }
 
+      if (ctx->force_net_interface[0]) {
+        /* Limit us to only addresses on a single interface */
+        int force_addr_ct = 0;
+        for(i=0;i<addr_ct;i++){
+          if (!strcmp(local_addrs[i].addr.ifname, ctx->force_net_interface)) {
+            // copy it down in the array, if needed
+            if (i != force_addr_ct) {
+              if (r=nr_local_addr_copy(&local_addrs[force_addr_ct], &local_addrs[i])) {
+                ABORT(r);
+              }
+            }
+            force_addr_ct++;
+          }
+        }
+        addr_ct = force_addr_ct;
+      }
+
+      if (ctx->flags & NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS) {
+        /* Get just the default IPv4 and IPv6 addrs */
+        if(!nr_ice_get_default_local_address(ctx, NR_IPV4, local_addrs, addr_ct,
+                                             &default_addrs[default_addr_ct])) {
+          ++default_addr_ct;
+        }
+        if(!nr_ice_get_default_local_address(ctx, NR_IPV6, local_addrs, addr_ct,
+                                             &default_addrs[default_addr_ct])) {
+          ++default_addr_ct;
+        }
+        addrs = default_addrs;
+        addr_ct = default_addr_ct;
+      }
+      else {
+        addrs = local_addrs;
+      }
+
       /* Sort interfaces by preference */
       if(ctx->interface_prioritizer) {
         for(i=0;i<addr_ct;i++){
           if(r=nr_interface_prioritizer_add_interface(ctx->interface_prioritizer,addrs+i)) {
             r_log(LOG_ICE,LOG_ERR,"ICE(%s): unable to add interface ",ctx->label);
             ABORT(r);
           }
         }
@@ -691,18 +733,16 @@ static int nr_ice_random_string(char *st
     int needed;
     int r,_status;
 
     if(len%2) ABORT(R_BAD_ARGS);
     needed=len/2;
 
     if(needed>sizeof(bytes)) ABORT(R_BAD_ARGS);
 
-    //memset(bytes,0,needed);
-
     if(r=nr_crypto_random_bytes(bytes,needed))
       ABORT(r);
 
     if(r=nr_bin2hex(bytes,needed,(unsigned char *)str))
       ABORT(r);
 
     _status=0;
   abort:
@@ -806,8 +846,23 @@ int nr_ice_ctx_finalize(nr_ice_ctx *ctx,
 
 int nr_ice_ctx_set_trickle_cb(nr_ice_ctx *ctx, nr_ice_trickle_candidate_cb cb, void *cb_arg)
 {
   ctx->trickle_cb = cb;
   ctx->trickle_cb_arg = cb_arg;
 
   return 0;
 }
+
+int nr_ice_ctx_hide_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand)
+  {
+    if (cand->state != NR_ICE_CAND_STATE_INITIALIZED) {
+      return 1;
+    }
+
+    if (ctx->flags & NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS) {
+      if (cand->type == HOST)
+        return 1;
+    }
+
+    return 0;
+  }
+
--- a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h
@@ -145,16 +145,18 @@ struct nr_ice_ctx_ {
   nr_ice_peer_ctx_head peers;
   nr_ice_stun_id_head ids;
 
   NR_async_cb done_cb;
   void *cb_arg;
 
   nr_ice_trickle_candidate_cb trickle_cb;
   void *trickle_cb_arg;
+
+  char force_net_interface[MAXIFNAME];
 };
 
 int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp);
 #define NR_ICE_CTX_FLAGS_OFFERER                           1
 #define NR_ICE_CTX_FLAGS_ANSWERER                          (1<<1)
 #define NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION             (1<<2)
 #define NR_ICE_CTX_FLAGS_LITE                              (1<<3)
 #define NR_ICE_CTX_FLAGS_RELAY_ONLY                        (1<<4)
--- a/media/mtransport/third_party/nICEr/src/ice/ice_reg.h
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_reg.h
@@ -65,13 +65,15 @@ extern "C" {
 
 #define NR_ICE_REG_ICE_TCP_DISABLE          "ice.tcp.disable"
 #define NR_ICE_REG_ICE_TCP_SO_SOCK_COUNT    "ice.tcp.so_sock_count"
 #define NR_ICE_REG_ICE_TCP_LISTEN_BACKLOG   "ice.tcp.listen_backlog"
 
 #define NR_ICE_REG_KEEPALIVE_TIMER          "ice.keepalive_timer"
 
 #define NR_ICE_REG_TRICKLE_GRACE_PERIOD     "ice.trickle_grace_period"
+#define NR_ICE_REG_PREF_FORCE_INTERFACE_NAME "ice.forced_interface_name"
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
 #endif
 
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -393,16 +393,17 @@ pref("media.peerconnection.video.min_bit
 pref("media.peerconnection.video.start_bitrate", 300);
 pref("media.peerconnection.video.max_bitrate", 2000);
 #endif
 pref("media.navigator.permission.disabled", false);
 pref("media.peerconnection.default_iceservers", "[]");
 pref("media.peerconnection.ice.loopback", false); // Set only for testing in offline environments.
 pref("media.peerconnection.ice.tcp", false);
 pref("media.peerconnection.ice.link_local", false); // Set only for testing IPV6 in networks that don't assign IPV6 addresses
+pref("media.peerconnection.ice.force_interface", ""); // Limit to only a single interface
 pref("media.peerconnection.ice.relay_only", false); // Limit candidates to TURN
 pref("media.peerconnection.use_document_iceservers", true);
 pref("media.peerconnection.identity.enabled", true);
 pref("media.peerconnection.identity.timeout", 10000);
 pref("media.peerconnection.ice.stun_client_maximum_transmits", 7);
 pref("media.peerconnection.ice.trickle_grace_period", 5000);
 // These values (aec, agc, and noice) are from media/webrtc/trunk/webrtc/common_types.h
 // kXxxUnchanged = 0, kXxxDefault = 1, and higher values are specific to each