Bug 1126036: Queue runnables for starting gathering and checking in PCMedia until the proxy lookup is complete. r=mt
authorByron Campen [:bwc] <docfaraday@gmail.com>
Mon, 26 Jan 2015 15:24:37 -0800
changeset 226078 c82fb962499a9828804522b5c3fb7956c6769289
parent 226077 a8339212a52e69394ed3b0e48451756752a11d4d
child 226079 9028edd5e75235816af44b54673f31eab6120b79
push id28185
push userkwierso@gmail.com
push dateWed, 28 Jan 2015 00:05:15 +0000
treeherdermozilla-central@b2b10231606b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmt
bugs1126036
milestone38.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 1126036: Queue runnables for starting gathering and checking in PCMedia until the proxy lookup is complete. r=mt
media/mtransport/third_party/nICEr/src/stun/stun_server_ctx.c
media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
--- a/media/mtransport/third_party/nICEr/src/stun/stun_server_ctx.c
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_server_ctx.c
@@ -104,16 +104,17 @@ static int nr_stun_server_client_create(
       ABORT(R_NO_MEMORY);
 
     if(!(clnt->username=r_strdup(user)))
       ABORT(R_NO_MEMORY);
 
     if(r=r_data_copy(&clnt->password,pass))
       ABORT(r);
 
+    r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-SERVER(%s)/CLIENT(%s): Adding client for %s",ctx->label, client_label, user);
     clnt->stun_server_cb=cb;
     clnt->cb_arg=cb_arg;
 
     *clntp = clnt;
     _status=0;
  abort:
     if(_status){
       nr_stun_server_destroy_client(clnt);
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
@@ -208,16 +208,17 @@ PeerConnectionImpl* PeerConnectionImpl::
 NS_IMETHODIMP PeerConnectionMedia::ProtocolProxyQueryHandler::
 OnProxyAvailable(nsICancelable *request,
                  nsIChannel *aChannel,
                  nsIProxyInfo *proxyinfo,
                  nsresult result) {
   CSFLogInfo(logTag, "%s: Proxy Available: %d", __FUNCTION__, (int)result);
 
   if (NS_SUCCEEDED(result) && proxyinfo) {
+    CSFLogInfo(logTag, "%s: Had proxyinfo", __FUNCTION__);
     nsresult rv;
     nsCString httpsProxyHost;
     int32_t httpsProxyPort;
 
     rv = proxyinfo->GetHost(httpsProxyHost);
     if (NS_FAILED(rv)) {
       CSFLogError(logTag, "%s: Failed to get proxy server host", __FUNCTION__);
       return rv;
@@ -238,17 +239,17 @@ OnProxyAvailable(nsICancelable *request,
       CSFLogError(logTag, "%s: Failed to set proxy server (ICE ctx unavailable)",
           __FUNCTION__);
     }
   }
 
   if (result != NS_ERROR_ABORT) {
     // NS_ERROR_ABORT means that the PeerConnectionMedia is no longer waiting
     pcm_->mProxyResolveCompleted = true;
-    pcm_->GatherIfReady();
+    pcm_->FlushIceCtxOperationQueueIfReady();
   }
 
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS(PeerConnectionMedia::ProtocolProxyQueryHandler, nsIProtocolProxyCallback)
 
 PeerConnectionMedia::PeerConnectionMedia(PeerConnectionImpl *parent)
@@ -256,17 +257,16 @@ PeerConnectionMedia::PeerConnectionMedia
       mParentHandle(parent->GetHandle()),
       mParentName(parent->GetName()),
       mAllowIceLoopback(false),
       mIceCtx(nullptr),
       mDNSResolver(new mozilla::NrIceResolver()),
       mUuidGen(MakeUnique<PCUuidGenerator>()),
       mMainThread(mParent->GetMainThread()),
       mSTSThread(mParent->GetSTSThread()),
-      mTransportsUpdated(false),
       mProxyResolveCompleted(false) {
   nsresult rv;
 
   nsCOMPtr<nsIProtocolProxyService> pps =
     do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
   if (NS_FAILED(rv)) {
     CSFLogError(logTag, "%s: Failed to get proxy service: %d", __FUNCTION__, (int)rv);
     return;
@@ -395,17 +395,16 @@ PeerConnectionMedia::UpdateTransports(co
                                pwd,
                                candidates),
                   NS_DISPATCH_NORMAL);
   }
 
 
   // TODO(bug 1017888): Need to deal properly with renegotatiation.
   // For now just start gathering.
-  mTransportsUpdated = true;
   GatherIfReady();
 }
 
 nsresult PeerConnectionMedia::UpdateMediaPipelines(
     const mozilla::JsepSession& session) {
   size_t numPairs = session.GetNegotiatedTrackPairCount();
   mozilla::MediaPipelineFactory factory(this);
   const mozilla::JsepTrackPair* pair;
@@ -462,26 +461,27 @@ PeerConnectionMedia::StartIceChecks(cons
     } else {
       CSFLogDebug(logTag, "Transport %u has %u components",
                           static_cast<unsigned>(i),
                           static_cast<unsigned>(transport->mComponents));
       numComponentsByLevel.push_back(transport->mComponents);
     }
   }
 
-  RUN_ON_THREAD(GetSTSThread(),
-                WrapRunnable(
-                  RefPtr<PeerConnectionMedia>(this),
-                  &PeerConnectionMedia::StartIceChecks_s,
-                  session.IsIceControlling(),
-                  session.RemoteIsIceLite(),
-                  // Copy, just in case API changes to return a ref
-                  std::vector<std::string>(session.GetIceOptions()),
-                  numComponentsByLevel),
-                NS_DISPATCH_NORMAL);
+  nsRefPtr<nsIRunnable> runnable(
+      WrapRunnable(
+        RefPtr<PeerConnectionMedia>(this),
+        &PeerConnectionMedia::StartIceChecks_s,
+        session.IsIceControlling(),
+        session.RemoteIsIceLite(),
+        // Copy, just in case API changes to return a ref
+        std::vector<std::string>(session.GetIceOptions()),
+        numComponentsByLevel));
+
+  PerformOrEnqueueIceCtxOperation(runnable);
 }
 
 void
 PeerConnectionMedia::StartIceChecks_s(
     bool aIsControlling,
     bool aIsIceLite,
     const std::vector<std::string>& aIceOptionsList,
     const std::vector<size_t>& aComponentCountByLevel) {
@@ -552,26 +552,52 @@ PeerConnectionMedia::AddIceCandidate_s(c
   if (NS_FAILED(rv)) {
     CSFLogError(logTag, "Couldn't process ICE candidate at level %u",
                 aMLine);
     return;
   }
 }
 
 void
+PeerConnectionMedia::FlushIceCtxOperationQueueIfReady()
+{
+  ASSERT_ON_THREAD(mMainThread);
+
+  if (IsIceCtxReady()) {
+    for (auto i = mQueuedIceCtxOperations.begin();
+         i != mQueuedIceCtxOperations.end();
+         ++i) {
+      GetSTSThread()->Dispatch(*i, NS_DISPATCH_NORMAL);
+    }
+    mQueuedIceCtxOperations.clear();
+  }
+}
+
+void
+PeerConnectionMedia::PerformOrEnqueueIceCtxOperation(
+    const nsRefPtr<nsIRunnable>& runnable)
+{
+  ASSERT_ON_THREAD(mMainThread);
+
+  if (IsIceCtxReady()) {
+    GetSTSThread()->Dispatch(runnable, NS_DISPATCH_NORMAL);
+  } else {
+    mQueuedIceCtxOperations.push_back(runnable);
+  }
+}
+
+void
 PeerConnectionMedia::GatherIfReady() {
   ASSERT_ON_THREAD(mMainThread);
 
-  if (mTransportsUpdated && mProxyResolveCompleted) {
-    RUN_ON_THREAD(GetSTSThread(),
-        WrapRunnable(
-          RefPtr<PeerConnectionMedia>(this),
-          &PeerConnectionMedia::EnsureIceGathering_s),
-        NS_DISPATCH_NORMAL);
-  }
+  nsRefPtr<nsIRunnable> runnable(WrapRunnable(
+        RefPtr<PeerConnectionMedia>(this),
+        &PeerConnectionMedia::EnsureIceGathering_s));
+
+  PerformOrEnqueueIceCtxOperation(runnable);
 }
 
 void
 PeerConnectionMedia::EnsureIceGathering_s() {
   if (mIceCtx->gathering_state() == NrIceCtx::ICE_CTX_GATHER_INIT) {
     if (mProxyServer) {
       mIceCtx->SetProxyServer(*mProxyServer);
     }
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
@@ -461,16 +461,18 @@ class PeerConnectionMedia : public sigsl
 
   // Manage ICE transports.
   void UpdateIceMediaStream_s(size_t aMLine, size_t aComponentCount,
                               bool aHasAttrs,
                               const std::string& aUfrag,
                               const std::string& aPassword,
                               const std::vector<std::string>& aCandidateList);
   void GatherIfReady();
+  void FlushIceCtxOperationQueueIfReady();
+  void PerformOrEnqueueIceCtxOperation(const nsRefPtr<nsIRunnable>& runnable);
   void EnsureIceGathering_s();
   void StartIceChecks_s(bool aIsControlling,
                         bool aIsIceLite,
                         const std::vector<std::string>& aIceOptionsList,
                         const std::vector<size_t>& aComponentCountByLevel);
 
   // Process a trickle ICE candidate.
   void AddIceCandidate_s(const std::string& aCandidate, const std::string& aMid,
@@ -492,16 +494,19 @@ class PeerConnectionMedia : public sigsl
   void IceGatheringStateChange_m(mozilla::NrIceCtx* ctx,
                                  mozilla::NrIceCtx::GatheringState state);
   void IceConnectionStateChange_m(mozilla::NrIceCtx* ctx,
                                   mozilla::NrIceCtx::ConnectionState state);
   void OnCandidateFound_m(const std::string &candidate, uint16_t aMLine);
   void EndOfLocalCandidates_m(const std::string& aDefaultAddr,
                               uint16_t aDefaultPort,
                               uint16_t aMLine);
+  bool IsIceCtxReady() const {
+    return mProxyResolveCompleted;
+  }
 
 
   // The parent PC
   PeerConnectionImpl *mParent;
   // and a loose handle on it for event driven stuff
   std::string mParentHandle;
   std::string mParentName;
 
@@ -534,18 +539,21 @@ class PeerConnectionMedia : public sigsl
   mozilla::UniquePtr<PCUuidGenerator> mUuidGen;
 
   // The main thread.
   nsCOMPtr<nsIThread> mMainThread;
 
   // The STS thread.
   nsCOMPtr<nsIEventTarget> mSTSThread;
 
-  // Used to track when transports are updated and are ready to start gathering
-  bool mTransportsUpdated;
+  // Used whenever we need to dispatch a runnable to STS to tweak something
+  // on our ICE ctx, but are not ready to do so at the moment (eg; we are
+  // waiting to get a callback with our http proxy config before we start
+  // gathering or start checking)
+  std::vector<nsRefPtr<nsIRunnable>> mQueuedIceCtxOperations;
 
   // Used to cancel any ongoing proxy request.
   nsCOMPtr<nsICancelable> mProxyRequest;
 
   // Used to track the state of the request.
   bool mProxyResolveCompleted;
 
   // Used to store the result of the request.