Bug 1297416 - Part 3: Add proxy-only mode and pref. draft
authorByron Campen [:bwc] <docfaraday@gmail.com>
Tue, 23 Aug 2016 15:15:33 -0500
changeset 411740 99be39e9a4880cd5aaa44243c5f76c1986d8d72b
parent 411739 f7c723ac0fa54144631b3eca974daf9cbe561e12
child 411741 8da26984d350447b33c68bce97dc5c0f83844398
push id28972
push userbcampen@mozilla.com
push dateThu, 08 Sep 2016 16:00:01 +0000
bugs1297416
milestone51.0a1
Bug 1297416 - Part 3: Add proxy-only mode and pref. MozReview-Commit-ID: D1e9f3OkVsU
media/mtransport/nricectx.cpp
media/mtransport/nricectx.h
media/mtransport/test/ice_unittest.cpp
media/mtransport/test/transport_unittests.cpp
media/mtransport/third_party/nICEr/src/ice/ice_component.c
media/mtransport/third_party/nICEr/src/ice/ice_ctx.h
media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
modules/libpref/init/all.js
--- a/media/mtransport/nricectx.cpp
+++ b/media/mtransport/nricectx.cpp
@@ -830,29 +830,35 @@ abort:
   nr_proxy_tunnel_config_destroy(&config);
   if (_status) {
     nr_socket_wrapper_factory_destroy(&wrapper);
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
 
-nsresult NrIceCtx::StartGathering(bool default_route_only) {
+nsresult NrIceCtx::StartGathering(bool default_route_only, bool proxy_only) {
   ASSERT_ON_THREAD(sts_target_);
   if (policy_ == ICE_POLICY_NONE) {
     return NS_OK;
   }
   SetGatheringState(ICE_CTX_GATHER_STARTED);
 
   if (default_route_only) {
     nr_ice_ctx_add_flags(ctx_, NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS);
   } else {
     nr_ice_ctx_remove_flags(ctx_, NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS);
   }
 
+  if (proxy_only) {
+    nr_ice_ctx_add_flags(ctx_, NR_ICE_CTX_FLAGS_ONLY_PROXY);
+  } else {
+    nr_ice_ctx_remove_flags(ctx_, NR_ICE_CTX_FLAGS_ONLY_PROXY);
+  }
+
   // This might start gathering for the first time, or again after
   // renegotiation, or might do nothing at all if gathering has already
   // finished.
   int r = nr_ice_gather(ctx_, &NrIceCtx::gather_cb, this);
 
   if (!r) {
     SetGatheringState(ICE_CTX_GATHER_COMPLETE);
   } else if (r != R_WOULDBLOCK) {
--- a/media/mtransport/nricectx.h
+++ b/media/mtransport/nricectx.h
@@ -302,17 +302,17 @@ class NrIceCtx {
   // StartGathering.
   nsresult SetResolver(nr_resolver *resolver);
 
   // Provide the proxy address. Must be called before
   // StartGathering.
   nsresult SetProxyServer(const NrIceProxyServer& proxy_server);
 
   // Start ICE gathering
-  nsresult StartGathering(bool default_route_only);
+  nsresult StartGathering(bool default_route_only, bool proxy_only);
 
   // Start checking
   nsresult StartChecks();
 
   // Finalize the ICE negotiation. I.e., there will be no
   // more forking.
   nsresult Finalize();
 
--- a/media/mtransport/test/ice_unittest.cpp
+++ b/media/mtransport/test/ice_unittest.cpp
@@ -535,17 +535,18 @@ class IceTestPeer : public sigslot::has_
 
   void Gather(bool default_route_only = false) {
     nsresult res;
 
     test_utils_->sts_target()->Dispatch(
         WrapRunnableRet(&res,
                         ice_ctx_->ctx(),
                         &NrIceCtx::StartGathering,
-                        default_route_only),
+                        default_route_only,
+                        false),
         NS_DISPATCH_SYNC);
 
     ASSERT_TRUE(NS_SUCCEEDED(res));
   }
 
   void UseNat() {
     nat_->enabled_ = true;
   }
--- a/media/mtransport/test/transport_unittests.cpp
+++ b/media/mtransport/test/transport_unittests.cpp
@@ -638,16 +638,17 @@ class TransportTestPeer : public sigslot
     flow_->SignalPacketReceived.connect(this, &TransportTestPeer::PacketReceived);
     flow_->SignalStateChange.connect(this, &TransportTestPeer::StateChanged);
 
     // Start gathering
     test_utils_->sts_target()->Dispatch(
         WrapRunnableRet(&res,
                         ice_ctx_->ctx(),
                         &NrIceCtx::StartGathering,
+                        false,
                         false),
         NS_DISPATCH_SYNC);
     ASSERT_TRUE(NS_SUCCEEDED(res));
   }
 
   void ConnectIce(TransportTestPeer *peer) {
     peer_ = peer;
 
--- a/media/mtransport/third_party/nICEr/src/ice/ice_component.c
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_component.c
@@ -202,16 +202,21 @@ static int nr_ice_component_initialize_u
   {
     nr_socket *sock;
     nr_ice_socket *isock=0;
     nr_ice_candidate *cand=0;
     int i;
     int j;
     int r,_status;
 
+    if(ctx->flags & NR_ICE_CTX_FLAGS_ONLY_PROXY) {
+      /* No UDP support if we must use a proxy */
+      return 0;
+    }
+
     /* Now one ice_socket for each address */
     for(i=0;i<addr_ct;i++){
       char suppress;
 
       if(r=NR_reg_get2_char(NR_ICE_REG_SUPPRESS_INTERFACE_PRFX,addrs[i].addr.ifname,&suppress)){
         if(r!=R_NOT_FOUND)
           ABORT(r);
       }
@@ -424,18 +429,19 @@ static int nr_ice_component_initialize_t
       if(r!=R_NOT_FOUND)
         ABORT(r);
     }
 
     if ((r=NR_reg_get_char(NR_ICE_REG_ICE_TCP_DISABLE, &ice_tcp_disabled))) {
       if (r != R_NOT_FOUND)
         ABORT(r);
     }
-    if (ctx->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY) {
-      r_log(LOG_ICE,LOG_WARNING,"ICE(%s): relay only option results in ICE TCP being disabled",ctx->label);
+    if ((ctx->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY) ||
+        (ctx->flags & NR_ICE_CTX_FLAGS_ONLY_PROXY)) {
+      r_log(LOG_ICE,LOG_WARNING,"ICE(%s): relay/proxy only option results in ICE TCP being disabled",ctx->label);
       ice_tcp_disabled = 1;
     }
 
     for(i=0;i<addr_ct;i++){
       char suppress;
       nr_ice_socket *isock_psv=0;
       nr_ice_socket *isock_so=0;
 
@@ -1084,16 +1090,22 @@ int nr_ice_component_pair_candidates(nr_
     nr_ice_candidate *lcand, *pcand;
     nr_ice_socket *isock;
     int r,_status;
 
     r_log(LOG_ICE,LOG_DEBUG,"Pairing candidates======");
 
     /* Create the candidate pairs */
     lcand=TAILQ_FIRST(&lcomp->candidates);
+
+    if (!lcand) {
+      /* No local candidates, initialized or not! */
+      ABORT(R_FAILED);
+    }
+
     while(lcand){
       if (lcand->state == NR_ICE_CAND_STATE_INITIALIZED) {
         if ((r = nr_ice_component_pair_candidate(pctx, pcomp, lcand, 0)))
           ABORT(r);
       }
 
       lcand=TAILQ_NEXT(lcand,entry_comp);
     }
--- a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h
@@ -160,16 +160,17 @@ int nr_ice_ctx_create(char *label, UINT4
 int nr_ice_ctx_create_with_credentials(char *label, UINT4 flags, char* ufrag, char* pwd, 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)
 #define NR_ICE_CTX_FLAGS_HIDE_HOST_CANDIDATES              (1<<5)
 #define NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS                (1<<6)
+#define NR_ICE_CTX_FLAGS_ONLY_PROXY                        (1<<7)
 
 void nr_ice_ctx_add_flags(nr_ice_ctx *ctx, UINT4 flags);
 void nr_ice_ctx_remove_flags(nr_ice_ctx *ctx, UINT4 flags);
 int nr_ice_ctx_destroy(nr_ice_ctx **ctxp);
 int nr_ice_gather(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg);
 int nr_ice_add_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand);
 void nr_ice_gather_finished_cb(NR_SOCKET s, int h, void *cb_arg);
 int nr_ice_add_media_stream(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp);
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
@@ -785,16 +785,28 @@ PeerConnectionMedia::GetPrefDefaultAddre
   default_address_only |=
     !MediaManager::Get()->IsActivelyCapturingOrHasAPermission(winId);
 #else
   bool default_address_only = true;
 #endif
   return default_address_only;
 }
 
+bool
+PeerConnectionMedia::GetPrefProxyOnly() const
+{
+  ASSERT_ON_THREAD(mMainThread); // will crash on STS thread
+
+#if !defined(MOZILLA_EXTERNAL_LINKAGE)
+  return Preferences::GetBool("media.peerconnection.ice.proxy_only", false);
+#else
+  return false;
+#endif
+}
+
 void
 PeerConnectionMedia::ConnectSignals(NrIceCtx *aCtx, NrIceCtx *aOldCtx)
 {
   aCtx->SignalGatheringStateChange.connect(
       this,
       &PeerConnectionMedia::IceGatheringStateChange_s);
   aCtx->SignalConnectionStateChange.connect(
       this,
@@ -882,31 +894,37 @@ PeerConnectionMedia::PerformOrEnqueueIce
 
 void
 PeerConnectionMedia::GatherIfReady() {
   ASSERT_ON_THREAD(mMainThread);
 
   nsCOMPtr<nsIRunnable> runnable(WrapRunnable(
         RefPtr<PeerConnectionMedia>(this),
         &PeerConnectionMedia::EnsureIceGathering_s,
-        GetPrefDefaultAddressOnly()));
+        GetPrefDefaultAddressOnly(),
+        GetPrefProxyOnly()));
 
   PerformOrEnqueueIceCtxOperation(runnable);
 }
 
 void
-PeerConnectionMedia::EnsureIceGathering_s(bool aDefaultRouteOnly) {
+PeerConnectionMedia::EnsureIceGathering_s(bool aDefaultRouteOnly,
+                                          bool aProxyOnly) {
   if (mProxyServer) {
     mIceCtxHdlr->ctx()->SetProxyServer(*mProxyServer);
+  } else if (aProxyOnly) {
+    IceGatheringStateChange_s(mIceCtxHdlr->ctx().get(),
+                              NrIceCtx::ICE_CTX_GATHER_COMPLETE);
+    return;
   }
 
   // Start gathering, but only if there are streams
   for (size_t i = 0; i < mIceCtxHdlr->ctx()->GetStreamCount(); ++i) {
     if (mIceCtxHdlr->ctx()->GetStream(i)) {
-      mIceCtxHdlr->ctx()->StartGathering(aDefaultRouteOnly);
+      mIceCtxHdlr->ctx()->StartGathering(aDefaultRouteOnly, aProxyOnly);
       return;
     }
   }
 
   // If there are no streams, we're probably in a situation where we've rolled
   // back while still waiting for our proxy configuration to come back. Make
   // sure content knows that the rollback has stuck wrt gathering.
   IceGatheringStateChange_s(mIceCtxHdlr->ctx().get(),
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
@@ -469,25 +469,26 @@ class PeerConnectionMedia : public sigsl
       const std::string& aUfrag,
       const std::string& aPassword,
       const std::vector<std::string>& aCandidateList);
   void RemoveTransportsAtOrAfter_s(size_t aMLine);
 
   void GatherIfReady();
   void FlushIceCtxOperationQueueIfReady();
   void PerformOrEnqueueIceCtxOperation(nsIRunnable* runnable);
-  void EnsureIceGathering_s(bool aDefaultRouteOnly);
+  void EnsureIceGathering_s(bool aDefaultRouteOnly, bool aProxyOnly);
   void StartIceChecks_s(bool aIsControlling,
                         bool aIsIceLite,
                         const std::vector<std::string>& aIceOptionsList);
 
   void BeginIceRestart_s(RefPtr<NrIceCtx> new_ctx);
   void FinalizeIceRestart_s();
   void RollbackIceRestart_s();
   bool GetPrefDefaultAddressOnly() const;
+  bool GetPrefProxyOnly() const;
 
   void ConnectSignals(NrIceCtx *aCtx, NrIceCtx *aOldCtx=nullptr);
 
   // Process a trickle ICE candidate.
   void AddIceCandidate_s(const std::string& aCandidate, const std::string& aMid,
                          uint32_t aMLine);
 
 
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -468,16 +468,17 @@ pref("media.peerconnection.ice.force_int
 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);
 pref("media.peerconnection.ice.no_host", false);
 pref("media.peerconnection.ice.default_address_only", false);
+pref("media.peerconnection.ice.proxy_only", false);
 
 // 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
 // setting (for Xxx = Ec, Agc, or Ns).  Defaults are all set to kXxxDefault here.
 pref("media.peerconnection.turn.disable", false);
 #if defined(MOZ_WEBRTC_HARDWARE_AEC_NS)
 pref("media.getusermedia.aec_enabled", false);
 pref("media.getusermedia.noise_enabled", false);