Bug 906986 - Convert NrIceCtxHandler to composition instead of inheriting from NrIceCtx draft
authorMichael Froman <mfroman@mozilla.com>
Tue, 22 Mar 2016 21:39:03 -0500
changeset 343675 52925fd21f38b677d4abfde5fdbcbcad28802d02
parent 342943 8aab9cf901b6811f590fbfbb624c1d8673265307
child 345696 745639935ba7f9da266fa93798c91653ae630a05
child 345976 5c4919e83307e739f1d76f8849cbf9435f94380f
push id13672
push usermfroman@nostrum.com
push dateWed, 23 Mar 2016 04:16:59 +0000
bugs906986
milestone47.0a1
Bug 906986 - Convert NrIceCtxHandler to composition instead of inheriting from NrIceCtx MozReview-Commit-ID: BfUzdcJDqk7
media/mtransport/nricectx.h
media/mtransport/nricectxhandler.cpp
media/mtransport/nricectxhandler.h
media/mtransport/test/ice_unittest.cpp
media/mtransport/test/multi_tcp_socket_unittest.cpp
media/mtransport/test/transport_unittests.cpp
media/webrtc/signaling/src/peerconnection/MediaPipelineFactory.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
--- a/media/mtransport/nricectx.h
+++ b/media/mtransport/nricectx.h
@@ -188,16 +188,17 @@ class NrIceProxyServer {
  private:
   std::string host_;
   uint16_t port_;
   std::string alpn_;
 };
 
 
 class NrIceCtx {
+ friend class NrIceCtxHandler;
  public:
   enum ConnectionState { ICE_CTX_INIT,
                          ICE_CTX_CHECKING,
                          ICE_CTX_OPEN,
                          ICE_CTX_FAILED
   };
 
   enum GatheringState { ICE_CTX_GATHER_INIT,
@@ -249,16 +250,17 @@ class NrIceCtx {
   // Some might be null
   size_t GetStreamCount() const
   {
     return streams_.size();
   }
 
   // The name of the ctx
   const std::string& name() const { return name_; }
+  bool offerer() const { return offerer_; }
 
   // Get ufrag and password.
   std::string ufrag() const;
   std::string pwd() const;
 
   // Current state
   ConnectionState connection_state() const {
     return connection_state_;
@@ -324,19 +326,17 @@ class NrIceCtx {
   sigslot::signal2<NrIceCtx*, NrIceCtx::ConnectionState>
     SignalConnectionStateChange;
 
   // The thread to direct method calls to
   nsCOMPtr<nsIEventTarget> thread() { return sts_target_; }
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrIceCtx)
 
- protected:
-  virtual ~NrIceCtx();
-
+private:
   NrIceCtx(const std::string& name,
            bool offerer,
            Policy policy)
   : connection_state_(ICE_CTX_INIT),
     gathering_state_(ICE_CTX_GATHER_INIT),
     name_(name),
     offerer_(offerer),
     streams_(),
@@ -345,17 +345,18 @@ class NrIceCtx {
     ice_handler_vtbl_(nullptr),
     ice_handler_(nullptr),
     trickle_(true),
     policy_(policy) {
     // XXX: offerer_ will be used eventually;  placate clang in the meantime.
     (void)offerer_;
   }
 
- private:
+  virtual ~NrIceCtx();
+
   DISALLOW_COPY_ASSIGN(NrIceCtx);
 
   // Callbacks for nICEr
   static void gather_cb(NR_SOCKET s, int h, void *arg);  // ICE gather complete
 
   // Handler implementation
   static int select_pair(void *obj,nr_ice_media_stream *stream,
                          int component_id, nr_ice_cand_pair **potentials,
@@ -374,17 +375,16 @@ class NrIceCtx {
   RefPtr<NrIceMediaStream> FindStream(nr_ice_media_stream *stream);
 
   // Set the state
   void SetConnectionState(ConnectionState state);
 
   // Set the state
   void SetGatheringState(GatheringState state);
 
-protected:
   ConnectionState connection_state_;
   GatheringState gathering_state_;
   const std::string name_;
   bool offerer_;
   std::vector<RefPtr<NrIceMediaStream> > streams_;
   nr_ice_ctx *ctx_;
   nr_ice_peer_ctx *peer_;
   nr_ice_handler_vtbl* ice_handler_vtbl_;  // Must be pointer
--- a/media/mtransport/nricectxhandler.cpp
+++ b/media/mtransport/nricectxhandler.cpp
@@ -7,125 +7,91 @@ extern "C" {
 }
 
 // Local includes
 #include "nricectxhandler.h"
 #include "nricemediastream.h"
 
 namespace mozilla {
 
-NrIceCtxHandler::~NrIceCtxHandler()
+NrIceCtxHandler::NrIceCtxHandler(const std::string& name,
+                  bool offerer,
+                  NrIceCtx::Policy policy)
+  : current_ctx(new NrIceCtx(name, offerer, policy)),
+    restart_ctx(nullptr),
+    restart_count(0)
 {
 }
 
-
 RefPtr<NrIceCtxHandler>
 NrIceCtxHandler::Create(const std::string& name,
                         bool offerer,
                         bool allow_loopback,
                         bool tcp_enabled,
                         bool allow_link_local,
                         bool hide_non_default,
-                        Policy policy)
+                        NrIceCtx::Policy policy)
 {
   // InitializeCryptoAndLogging only executes once
   NrIceCtx::InitializeCryptoAndLogging(allow_loopback,
                                        tcp_enabled,
                                        allow_link_local);
 
   RefPtr<NrIceCtxHandler> ctx = new NrIceCtxHandler(name, offerer, policy);
 
-  if (!NrIceCtx::Initialize(ctx,
+  if (!NrIceCtx::Initialize(ctx->current_ctx,
                             hide_non_default)) {
     return nullptr;
   }
 
   return ctx;
 }
 
 
 RefPtr<NrIceMediaStream>
 NrIceCtxHandler::CreateStream(const std::string& name, int components)
 {
   // To make tracking NrIceMediaStreams easier during ICE restart
   // prepend an int to the name that increments with each ICE restart
   std::ostringstream os;
   os << restart_count << "-" << name;
-  return NrIceMediaStream::Create(this, os.str(), components);
-}
-
-
-void
-NrIceCtxHandler::SwapContextData(NrIceCtxHandler& ctx1, NrIceCtxHandler& ctx2)
-{
-  ctx1.streams_.swap(ctx2.streams_);
-
-  ConnectionState tmp_connection_state      = ctx1.connection_state_;
-  GatheringState tmp_gathering_state        = ctx1.gathering_state_;
-  nr_ice_ctx *tmp_ctx                       = ctx1.ctx_;
-  nr_ice_peer_ctx *tmp_peer_ctx             = ctx1.peer_;
-  nr_ice_handler_vtbl *tmp_ice_handler_vtbl = ctx1.ice_handler_vtbl_;
-  nr_ice_handler *tmp_ice_handler           = ctx1.ice_handler_;
-  bool tmp_trickle                          = ctx1.trickle_;
-  nsCOMPtr<nsIEventTarget> tmp_sts_target   = ctx1.sts_target_;
-
-  ctx1.connection_state_ = ctx2.connection_state_;
-  ctx1.gathering_state_  = ctx2.gathering_state_;
-  ctx1.ctx_              = ctx2.ctx_;
-  ctx1.peer_             = ctx2.peer_;
-  ctx1.ice_handler_vtbl_ = ctx2.ice_handler_vtbl_;
-  ctx1.ice_handler_      = ctx2.ice_handler_;
-  if (ctx1.ice_handler_) {
-    ctx1.ice_handler_->obj = &ctx1;
-  }
-  ctx1.trickle_          = ctx2.trickle_;
-  ctx1.sts_target_       = ctx2.sts_target_;
-
-  ctx2.connection_state_ = tmp_connection_state;
-  ctx2.gathering_state_ = tmp_gathering_state;
-  ctx2.ctx_ = tmp_ctx;
-  ctx2.peer_ = tmp_peer_ctx;
-  ctx2.ice_handler_vtbl_ = tmp_ice_handler_vtbl;
-  ctx2.ice_handler_ = tmp_ice_handler;
-  if (ctx2.ice_handler_) {
-    ctx2.ice_handler_->obj = &ctx2;
-  }
-  ctx2.trickle_ = tmp_trickle;
-  ctx2.sts_target_ = tmp_sts_target;
+  return NrIceMediaStream::Create(this->current_ctx, os.str(), components);
 }
 
 
 void
 NrIceCtxHandler::BeginIceRestart()
 {
-  std::string ufrag = GetNewUfrag();
-  std::string pwd = GetNewPwd();
+  std::string ufrag = NrIceCtx::GetNewUfrag();
+  std::string pwd = NrIceCtx::GetNewPwd();
   BeginIceRestart(ufrag, pwd);
 }
 
+
 void
 NrIceCtxHandler::BeginIceRestart(const std::string& ufrag,
                                  const std::string& pwd)
 {
   MOZ_ASSERT(!restart_ctx, "existing ice restart in progress");
-  RefPtr<NrIceCtxHandler> new_ctx = new NrIceCtxHandler(name_, offerer_, policy_);
+  RefPtr<NrIceCtx> new_ctx = new NrIceCtx(this->current_ctx->name(),
+                                          this->current_ctx->offerer(),
+                                          this->current_ctx->policy());
 
   // reconstitute the hide_non_default bool based on the flags stored in the
   // original ctx flags
-  bool hide_non_default = ctx_->flags & NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS;
+  bool hide_non_default = current_ctx->ctx()->flags & NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS;
 
-  SwapContextData(*new_ctx, *this);
-
-  NrIceCtx::Initialize(this,
+  NrIceCtx::Initialize(new_ctx,
                        hide_non_default,
                        ufrag,
                        pwd);
 
   ++restart_count;
-  restart_ctx = new_ctx;
+  restart_ctx = current_ctx;
+  current_ctx = new_ctx;
 }
 
 
 void
 NrIceCtxHandler::FinalizeIceRestart()
 {
   // no harm calling this even if we're not in the middle of restarting
   restart_ctx = nullptr;
@@ -133,14 +99,14 @@ NrIceCtxHandler::FinalizeIceRestart()
 
 
 void
 NrIceCtxHandler::RollbackIceRestart()
 {
   if (restart_ctx == nullptr) {
     return;
   }
-  SwapContextData(*restart_ctx, *this);
+  current_ctx = restart_ctx;
   restart_ctx = nullptr;
 }
 
 
 } // close namespace
--- a/media/mtransport/nricectxhandler.h
+++ b/media/mtransport/nricectxhandler.h
@@ -1,49 +1,49 @@
 #ifndef nricectxhandler_h__
 #define nricectxhandler_h__
 
 #include "nricectx.h"
 
 namespace mozilla {
 
-class NrIceCtxHandler : public NrIceCtx {
+class NrIceCtxHandler {
 public:
   // TODO(ekr@rtfm.com): Too many bools here. Bug 1193437.
   static RefPtr<NrIceCtxHandler> Create(const std::string& name,
                                  bool offerer,
                                  bool allow_loopback = false,
                                  bool tcp_enabled = true,
                                  bool allow_link_local = false,
                                  bool hide_non_default = false,
-                                 Policy policy = ICE_POLICY_ALL);
+                                 NrIceCtx::Policy policy = NrIceCtx::ICE_POLICY_ALL);
 
-  // Create a media stream
   RefPtr<NrIceMediaStream> CreateStream(const std::string& name,
                                         int components);
 
+  RefPtr<NrIceCtx> ctx() { return current_ctx; }
+
   void BeginIceRestart(); // used in testing
   void BeginIceRestart(const std::string& ufrag,
                        const std::string& pwd);
   bool IsRestarting() { return (restart_ctx != nullptr); }
   void FinalizeIceRestart();
   void RollbackIceRestart();
 
-protected:
+
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrIceCtxHandler)
+
+private:
   NrIceCtxHandler(const std::string& name,
                   bool offerer,
-                  Policy policy)
-  : NrIceCtx(name, offerer, policy),
-    restart_ctx(nullptr), restart_count(0) {}
-
+                  NrIceCtx::Policy policy);
   NrIceCtxHandler(); // disable
-  virtual ~NrIceCtxHandler();
+  ~NrIceCtxHandler() {}
+  DISALLOW_COPY_ASSIGN(NrIceCtxHandler);
 
-  void SwapContextData(NrIceCtxHandler& ctx1, NrIceCtxHandler& ctx2);
-
-private:
-  RefPtr<NrIceCtxHandler> restart_ctx; // for while restart is in progress
+  RefPtr<NrIceCtx> current_ctx;
+  RefPtr<NrIceCtx> restart_ctx; // for while restart is in progress
   int restart_count; // used to differentiate streams between restarted ctx
 };
 
 } // close namespace
 
 #endif // nricectxhandler_h__
--- a/media/mtransport/test/ice_unittest.cpp
+++ b/media/mtransport/test/ice_unittest.cpp
@@ -303,66 +303,66 @@ class IceTestPeer : public sigslot::has_
       candidate_filter_(nullptr),
       expected_local_type_(NrIceCandidate::ICE_HOST),
       expected_local_transport_(kNrIceTransportUdp),
       expected_remote_type_(NrIceCandidate::ICE_HOST),
       trickle_mode_(TRICKLE_NONE),
       trickled_(0),
       simulate_ice_lite_(false),
       nat_(new TestNat) {
-    ice_ctx_->SignalGatheringStateChange.connect(
+    ice_ctx_->ctx()->SignalGatheringStateChange.connect(
         this,
         &IceTestPeer::GatheringStateChange);
-    ice_ctx_->SignalConnectionStateChange.connect(
+    ice_ctx_->ctx()->SignalConnectionStateChange.connect(
         this,
         &IceTestPeer::ConnectionStateChange);
 
     nr_socket_factory *fac;
     int r = nat_->create_socket_factory(&fac);
     MOZ_ASSERT(!r);
     if (!r) {
-      nr_ice_ctx_set_socket_factory(ice_ctx_->ctx(), fac);
+      nr_ice_ctx_set_socket_factory(ice_ctx_->ctx()->ctx(), fac);
     }
   }
 
   ~IceTestPeer() {
     test_utils->sts_target()->Dispatch(WrapRunnable(this,
                                                     &IceTestPeer::Shutdown),
         NS_DISPATCH_SYNC);
 
     // Give the ICE destruction callback time to fire before
     // we destroy the resolver.
     PR_Sleep(1000);
   }
 
   void AddStream_s(int components) {
     char name[100];
     snprintf(name, sizeof(name), "%s:stream%d", name_.c_str(),
-             (int)ice_ctx_->GetStreamCount());
+             (int)ice_ctx_->ctx()->GetStreamCount());
 
     RefPtr<NrIceMediaStream> stream =
         ice_ctx_->CreateStream(static_cast<char *>(name), components);
-    ice_ctx_->SetStream(ice_ctx_->GetStreamCount(), stream);
+    ice_ctx_->ctx()->SetStream(ice_ctx_->ctx()->GetStreamCount(), stream);
 
     ASSERT_TRUE(stream);
     stream->SignalCandidate.connect(this, &IceTestPeer::CandidateInitialized);
     stream->SignalReady.connect(this, &IceTestPeer::StreamReady);
     stream->SignalFailed.connect(this, &IceTestPeer::StreamFailed);
     stream->SignalPacketReceived.connect(this, &IceTestPeer::PacketReceived);
   }
 
   void AddStream(int components)
   {
     test_utils->sts_target()->Dispatch(
         WrapRunnable(this, &IceTestPeer::AddStream_s, components),
         NS_DISPATCH_SYNC);
   }
 
   void RemoveStream_s(size_t index) {
-    ice_ctx_->SetStream(index, nullptr);
+    ice_ctx_->ctx()->SetStream(index, nullptr);
   }
 
   void RemoveStream(size_t index) {
     test_utils->sts_target()->Dispatch(
         WrapRunnable(this, &IceTestPeer::RemoveStream_s, index),
         NS_DISPATCH_SYNC);
   }
 
@@ -376,17 +376,17 @@ class IceTestPeer : public sigslot::has_
     std::vector<NrIceStunServer> stun_servers;
     ScopedDeletePtr<NrIceStunServer> server(NrIceStunServer::Create(
         addr, port, transport));
     stun_servers.push_back(*server);
     SetStunServers(stun_servers);
   }
 
   void SetStunServers(const std::vector<NrIceStunServer> &servers) {
-    ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetStunServers(servers)));
+    ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->ctx()->SetStunServers(servers)));
   }
 
   void UseTestStunServer() {
     SetStunServer(TestStunServer::GetInstance(AF_INET)->addr(),
                   TestStunServer::GetInstance(AF_INET)->port());
   }
 
   void SetTurnServer(const std::string addr, uint16_t port,
@@ -401,48 +401,48 @@ class IceTestPeer : public sigslot::has_
   void SetTurnServer(const std::string addr, uint16_t port,
                      const std::string username,
                      const std::vector<unsigned char> password,
                      const char* transport) {
     std::vector<NrIceTurnServer> turn_servers;
     ScopedDeletePtr<NrIceTurnServer> server(NrIceTurnServer::Create(
         addr, port, username, password, transport));
     turn_servers.push_back(*server);
-    ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetTurnServers(turn_servers)));
+    ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->ctx()->SetTurnServers(turn_servers)));
   }
 
   void SetTurnServers(const std::vector<NrIceTurnServer> servers) {
-    ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetTurnServers(servers)));
+    ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->ctx()->SetTurnServers(servers)));
   }
 
   void SetFakeResolver(const std::string& ip = g_stun_server_address,
                        const std::string& fqdn = g_stun_server_hostname) {
     ASSERT_TRUE(NS_SUCCEEDED(dns_resolver_->Init()));
     if (!ip.empty() && !fqdn.empty()) {
       PRNetAddr addr;
       PRStatus status = PR_StringToNetAddr(ip.c_str(), &addr);
       addr.inet.port = kDefaultStunServerPort;
       ASSERT_EQ(PR_SUCCESS, status);
       fake_resolver_.SetAddr(fqdn, addr);
     }
-    ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetResolver(
+    ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->ctx()->SetResolver(
         fake_resolver_.AllocateResolver())));
   }
 
   void SetDNSResolver() {
     ASSERT_TRUE(NS_SUCCEEDED(dns_resolver_->Init()));
-    ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetResolver(
+    ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->ctx()->SetResolver(
         dns_resolver_->AllocateResolver())));
   }
 
   void Gather() {
     nsresult res;
 
     test_utils->sts_target()->Dispatch(
-        WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::StartGathering),
+        WrapRunnableRet(&res, ice_ctx_->ctx(), &NrIceCtx::StartGathering),
         NS_DISPATCH_SYNC);
 
     ASSERT_TRUE(NS_SUCCEEDED(res));
   }
 
   void UseNat() {
     nat_->enabled_ = true;
   }
@@ -459,17 +459,17 @@ class IceTestPeer : public sigslot::has_
 
   void SetBlockUdp(bool block) {
     MOZ_ASSERT(!nat_->has_port_mappings());
     nat_->block_udp_ = block;
   }
 
   // Get various pieces of state
   std::vector<std::string> GetGlobalAttributes() {
-    std::vector<std::string> attrs(ice_ctx_->GetGlobalAttributes());
+    std::vector<std::string> attrs(ice_ctx_->ctx()->GetGlobalAttributes());
     if (simulate_ice_lite_) {
       attrs.push_back("ice-lite");
     }
     return attrs;
   }
 
   std::vector<std::string> GetCandidates(size_t stream) {
     std::vector<std::string> v;
@@ -486,23 +486,24 @@ class IceTestPeer : public sigslot::has_
       return candidate_filter_(candidate);
     }
     return candidate;
   }
 
   std::vector<std::string> GetCandidates_s(size_t stream) {
     std::vector<std::string> candidates;
 
-    if (stream >= ice_ctx_->GetStreamCount() || !ice_ctx_->GetStream(stream)) {
+    if (stream >= ice_ctx_->ctx()->GetStreamCount() ||
+        !ice_ctx_->ctx()->GetStream(stream)) {
       EXPECT_TRUE(false) << "No such stream " << stream;
       return candidates;
     }
 
     std::vector<std::string> candidates_in =
-      ice_ctx_->GetStream(stream)->GetCandidates();
+      ice_ctx_->ctx()->GetStream(stream)->GetCandidates();
 
     for (size_t i=0; i < candidates_in.size(); i++) {
       std::string candidate(FilterCandidate(candidates_in[i]));
       if (!candidate.empty()) {
         std::cerr << name_ << " Returning candidate: " << candidate << std::endl;
         candidates.push_back(candidate);
       }
     }
@@ -546,21 +547,21 @@ class IceTestPeer : public sigslot::has_
       }
     }
     return host_net;
   }
 
   bool gathering_complete() { return gathering_complete_; }
   int ready_ct() { return ready_ct_; }
   bool is_ready_s(size_t stream) {
-    if (!ice_ctx_->GetStream(stream)) {
+    if (!ice_ctx_->ctx()->GetStream(stream)) {
       EXPECT_TRUE(false) << "No such stream " << stream;
       return false;
     }
-    return ice_ctx_->GetStream(stream)->state() == NrIceMediaStream::ICE_OPEN;
+    return ice_ctx_->ctx()->GetStream(stream)->state() == NrIceMediaStream::ICE_OPEN;
   }
   bool is_ready(size_t stream)
   {
     bool result;
     test_utils->sts_target()->Dispatch(
         WrapRunnableRet(&result, this, &IceTestPeer::is_ready_s, stream),
         NS_DISPATCH_SYNC);
     return result;
@@ -576,16 +577,25 @@ class IceTestPeer : public sigslot::has_
     test_utils->sts_target()->Dispatch(
         WrapRunnable(this, &IceTestPeer::RestartIce_s),
         NS_DISPATCH_SYNC);
   }
 
 
   void RestartIce_s() {
     ice_ctx_->BeginIceRestart();
+
+    // set signals for the newly restarted ctx
+    ice_ctx_->ctx()->SignalGatheringStateChange.connect(
+        this,
+        &IceTestPeer::GatheringStateChange);
+    ice_ctx_->ctx()->SignalConnectionStateChange.connect(
+        this,
+        &IceTestPeer::ConnectionStateChange);
+
     // take care of some local bookkeeping
     ready_ct_ = 0;
     gathering_complete_ = false;
     ice_complete_ = false;
     ice_reached_checking_ = false;
     remote_ = nullptr;
   }
 
@@ -619,52 +629,52 @@ class IceTestPeer : public sigslot::has_
                  bool start = true) {
     nsresult res;
 
     remote_ = remote;
 
     trickle_mode_ = trickle_mode;
     ice_complete_ = false;
     ice_reached_checking_ = false;
-    res = ice_ctx_->ParseGlobalAttributes(remote->GetGlobalAttributes());
+    res = ice_ctx_->ctx()->ParseGlobalAttributes(remote->GetGlobalAttributes());
     ASSERT_TRUE(NS_SUCCEEDED(res));
 
     if (trickle_mode == TRICKLE_NONE ||
         trickle_mode == TRICKLE_REAL) {
-      for (size_t i=0; i<ice_ctx_->GetStreamCount(); ++i) {
-        RefPtr<NrIceMediaStream> aStream = ice_ctx_->GetStream(i);
+      for (size_t i=0; i<ice_ctx_->ctx()->GetStreamCount(); ++i) {
+        RefPtr<NrIceMediaStream> aStream = ice_ctx_->ctx()->GetStream(i);
         if (!aStream || aStream->HasParsedAttributes()) {
           continue;
         }
         std::vector<std::string> candidates =
             remote->GetCandidates(i);
 
         for (size_t j=0; j<candidates.size(); ++j) {
           std::cerr << name_ << " Candidate: " + candidates[j] << std::endl;
         }
         res = aStream->ParseAttributes(candidates);
         ASSERT_TRUE(NS_SUCCEEDED(res));
       }
     } else {
       // Parse empty attributes and then trickle them out later
-      for (size_t i=0; i<ice_ctx_->GetStreamCount(); ++i) {
-        RefPtr<NrIceMediaStream> aStream = ice_ctx_->GetStream(i);
+      for (size_t i=0; i<ice_ctx_->ctx()->GetStreamCount(); ++i) {
+        RefPtr<NrIceMediaStream> aStream = ice_ctx_->ctx()->GetStream(i);
         if (!aStream || aStream->HasParsedAttributes()) {
           continue;
         }
         std::vector<std::string> empty_attrs;
         std::cout << "Calling ParseAttributes on stream " << i << std::endl;
         res = aStream->ParseAttributes(empty_attrs);
         ASSERT_TRUE(NS_SUCCEEDED(res));
       }
     }
 
     if (start) {
       // Now start checks
-      res = ice_ctx_->StartChecks();
+      res = ice_ctx_->ctx()->StartChecks();
       ASSERT_TRUE(NS_SUCCEEDED(res));
     }
   }
 
   void Connect(IceTestPeer *remote, TrickleMode trickle_mode,
                bool start = true) {
     test_utils->sts_target()->Dispatch(
         WrapRunnable(
@@ -674,18 +684,18 @@ class IceTestPeer : public sigslot::has_
 
   void SimulateTrickle(size_t stream) {
     std::cerr << name_ << " Doing trickle for stream " << stream << std::endl;
     // If we are in trickle deferred mode, now trickle in the candidates
     // for |stream|
 
     // The size of streams is not going to change out from under us, so should
     // be safe here.
-    ASSERT_GT(remote_->ice_ctx_->GetStreamCount(), stream);
-    ASSERT_TRUE(remote_->ice_ctx_->GetStream(stream).get());
+    ASSERT_GT(remote_->ice_ctx_->ctx()->GetStreamCount(), stream);
+    ASSERT_TRUE(remote_->ice_ctx_->ctx()->GetStream(stream).get());
 
     std::vector<SchedulableTrickleCandidate*>& candidates =
       ControlTrickle(stream);
 
     for (auto i = candidates.begin(); i != candidates.end(); ++i) {
       (*i)->Schedule(0);
     }
   }
@@ -703,21 +713,21 @@ class IceTestPeer : public sigslot::has_
       controlled_trickle_candidates_[stream].push_back(
           new SchedulableTrickleCandidate(this, stream, candidates[j]));
     }
 
     return controlled_trickle_candidates_[stream];
   }
 
   nsresult TrickleCandidate_s(const std::string &candidate, size_t stream) {
-    if (!ice_ctx_->GetStream(stream)) {
+    if (!ice_ctx_->ctx()->GetStream(stream)) {
       // stream might have gone away before the trickle timer popped
       return NS_OK;
     }
-    return ice_ctx_->GetStream(stream)->ParseTrickleCandidate(candidate);
+    return ice_ctx_->ctx()->GetStream(stream)->ParseTrickleCandidate(candidate);
   }
 
   void DumpCandidate(std::string which, const NrIceCandidate& cand) {
     std::string type;
     std::string tcp_type;
 
     std::string addr;
     int port;
@@ -779,28 +789,30 @@ class IceTestPeer : public sigslot::has_
               << tcp_type
               << " codeword="
               << cand.codeword
               << std::endl;
   }
 
   void DumpAndCheckActiveCandidates_s() {
     std::cerr << name_ << " Active candidates:" << std::endl;
-    for (size_t i=0; i < ice_ctx_->GetStreamCount(); ++i) {
-      if (!ice_ctx_->GetStream(i)) {
+    for (size_t i=0; i < ice_ctx_->ctx()->GetStreamCount(); ++i) {
+      if (!ice_ctx_->ctx()->GetStream(i)) {
         continue;
       }
 
-      for (size_t j=0; j < ice_ctx_->GetStream(i)->components(); ++j) {
+      for (size_t j=0; j < ice_ctx_->ctx()->GetStream(i)->components(); ++j) {
         std::cerr << name_ << " Stream " << i << " component " << j+1 << std::endl;
 
         NrIceCandidate *local;
         NrIceCandidate *remote;
 
-        nsresult res = ice_ctx_->GetStream(i)->GetActivePair(j+1, &local, &remote);
+        nsresult res = ice_ctx_->ctx()->GetStream(i)->GetActivePair(j+1,
+                                                                    &local,
+                                                                    &remote);
         if (res == NS_ERROR_NOT_AVAILABLE) {
           std::cerr << "Component unpaired or disabled." << std::endl;
         } else {
           ASSERT_TRUE(NS_SUCCEEDED(res));
           DumpCandidate("Local  ", *local);
           /* Depending on timing, and the whims of the network
            * stack/configuration we're running on top of, prflx is always a
            * possibility. */
@@ -834,17 +846,17 @@ class IceTestPeer : public sigslot::has_
   void DumpAndCheckActiveCandidates() {
     test_utils->sts_target()->Dispatch(
       WrapRunnable(this, &IceTestPeer::DumpAndCheckActiveCandidates_s),
       NS_DISPATCH_SYNC);
   }
 
   void Close() {
     test_utils->sts_target()->Dispatch(
-      WrapRunnable(ice_ctx_, &NrIceCtx::destroy_peer_ctx),
+      WrapRunnable(ice_ctx_->ctx(), &NrIceCtx::destroy_peer_ctx),
       NS_DISPATCH_SYNC);
   }
 
   void Shutdown() {
     std::cerr << name_ << " Shutdown" << std::endl;
     for (auto s = controlled_trickle_candidates_.begin();
          s != controlled_trickle_candidates_.end();
          ++s) {
@@ -866,43 +878,43 @@ class IceTestPeer : public sigslot::has_
     remote_ = nullptr;
   }
 
   void StartChecks() {
     nsresult res;
 
     // Now start checks
     test_utils->sts_target()->Dispatch(
-        WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::StartChecks),
+        WrapRunnableRet(&res, ice_ctx_->ctx(), &NrIceCtx::StartChecks),
         NS_DISPATCH_SYNC);
     ASSERT_TRUE(NS_SUCCEEDED(res));
   }
 
   // Handle events
   void GatheringStateChange(NrIceCtx* ctx,
                             NrIceCtx::GatheringState state) {
     (void)ctx;
     if (state != NrIceCtx::ICE_CTX_GATHER_COMPLETE) {
       return;
     }
 
     std::cerr << "Gathering complete for " <<  name_ << std::endl;
     gathering_complete_ = true;
 
     std::cerr << name_ << " CANDIDATES:" << std::endl;
-    for (size_t i=0; i<ice_ctx_->GetStreamCount(); ++i) {
+    for (size_t i=0; i<ice_ctx_->ctx()->GetStreamCount(); ++i) {
       std::cerr << "Stream " << name_ << std::endl;
 
-      if (!ice_ctx_->GetStream(i)) {
+      if (!ice_ctx_->ctx()->GetStream(i)) {
         std::cerr << "DISABLED" << std::endl;
         continue;
       }
 
       std::vector<std::string> candidates =
-          ice_ctx_->GetStream(i)->GetCandidates();
+          ice_ctx_->ctx()->GetStream(i)->GetCandidates();
 
       for(size_t j=0; j<candidates.size(); ++j) {
         std::cerr << candidates[j] << std::endl;
       }
     }
     std::cerr << std::endl;
 
   }
@@ -916,43 +928,45 @@ class IceTestPeer : public sigslot::has_
       << candidate << std::endl;
     candidates_[stream->name()].push_back(candidate);
 
     // If we are connected, then try to trickle to the other side.
     if (remote_ && remote_->remote_ && (trickle_mode_ != TRICKLE_SIMULATE)) {
       // first, find the index of the stream we've been given so
       // we can get the corresponding stream on the remote side
       size_t index = -1;
-      for (size_t i=0; i<ice_ctx_->GetStreamCount(); ++i) {
-        if (ice_ctx_->GetStream(i) == stream) {
+      for (size_t i=0; i<ice_ctx_->ctx()->GetStreamCount(); ++i) {
+        if (ice_ctx_->ctx()->GetStream(i) == stream) {
           index = i;
           break;
         }
       }
-      ASSERT_NE(index, -1u);
-
-      ASSERT_GT(remote_->ice_ctx_->GetStreamCount(), index);
-      nsresult res = remote_->ice_ctx_->GetStream(index)->ParseTrickleCandidate(
+      ASSERT_NE(index, -1);
+
+      ASSERT_GT(remote_->ice_ctx_->ctx()->GetStreamCount(), index);
+      nsresult res = 
+        remote_->ice_ctx_->ctx()->GetStream(index)->ParseTrickleCandidate(
           candidate);
       ASSERT_TRUE(NS_SUCCEEDED(res));
       ++trickled_;
     }
   }
 
   nsresult GetCandidatePairs_s(size_t stream_index,
                                std::vector<NrIceCandidatePair>* pairs)
   {
     MOZ_ASSERT(pairs);
-    if (stream_index >= ice_ctx_->GetStreamCount() || !ice_ctx_->GetStream(stream_index)) {
+    if (stream_index >= ice_ctx_->ctx()->GetStreamCount() ||
+        !ice_ctx_->ctx()->GetStream(stream_index)) {
       // Is there a better error for "no such index"?
       ADD_FAILURE() << "No such media stream index: " << stream_index;
       return NS_ERROR_INVALID_ARG;
     }
 
-    return ice_ctx_->GetStream(stream_index)->GetCandidatePairs(pairs);
+    return ice_ctx_->ctx()->GetStream(stream_index)->GetCandidatePairs(pairs);
   }
 
   nsresult GetCandidatePairs(size_t stream_index,
                              std::vector<NrIceCandidatePair>* pairs) {
     nsresult v;
     test_utils->sts_target()->Dispatch(
         WrapRunnableRet(&v, this,
                         &IceTestPeer::GetCandidatePairs_s,
@@ -984,21 +998,21 @@ class IceTestPeer : public sigslot::has_
          p != pairs.end(); ++p) {
       DumpCandidatePair(*p);
     }
     std::cerr << "]" << std::endl;
   }
 
   void DumpCandidatePairs_s() {
     std::cerr << "Dumping candidate pairs for all streams [" << std::endl;
-    for (size_t s = 0; s < ice_ctx_->GetStreamCount(); ++s) {
-      if (!ice_ctx_->GetStream(s)) {
+    for (size_t s = 0; s < ice_ctx_->ctx()->GetStreamCount(); ++s) {
+      if (!ice_ctx_->ctx()->GetStream(s)) {
         continue;
       }
-      DumpCandidatePairs_s(ice_ctx_->GetStream(s).get());
+      DumpCandidatePairs_s(ice_ctx_->ctx()->GetStream(s).get());
     }
     std::cerr << "]" << std::endl;
   }
 
   bool CandidatePairsPriorityDescending(const std::vector<NrIceCandidatePair>&
                                         pairs) {
     // Verify that priority is descending
     uint64_t priority = std::numeric_limits<uint64_t>::max();
@@ -1107,54 +1121,55 @@ class IceTestPeer : public sigslot::has_
   void PacketReceived(NrIceMediaStream *stream, int component, const unsigned char *data,
                       int len) {
     std::cerr << name_ << ": received " << len << " bytes" << std::endl;
     ++received_;
   }
 
   void SendPacket(int stream, int component, const unsigned char *data,
                   int len) {
-    if (!ice_ctx_->GetStream(stream)) {
+    if (!ice_ctx_->ctx()->GetStream(stream)) {
       ADD_FAILURE() << "No such stream " << stream;
       return;
     }
 
-    ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->GetStream(stream)->SendPacket(component, data, len)));
+    ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->ctx()->GetStream(stream)->SendPacket(component, data, len)));
 
     ++sent_;
     std::cerr << name_ << ": sent " << len << " bytes" << std::endl;
   }
 
   void SetCandidateFilter(CandidateFilter filter) {
     candidate_filter_ = filter;
   }
 
   void ParseCandidate_s(size_t i, const std::string& candidate) {
-    ASSERT_TRUE(ice_ctx_->GetStream(i).get()) << "No such stream " << i;
+    ASSERT_TRUE(ice_ctx_->ctx()->GetStream(i).get()) << "No such stream " << i;
 
     std::vector<std::string> attributes;
 
     attributes.push_back(candidate);
-    ice_ctx_->GetStream(i)->ParseAttributes(attributes);
+    ice_ctx_->ctx()->GetStream(i)->ParseAttributes(attributes);
   }
 
   void ParseCandidate(size_t i, const std::string& candidate)
   {
     test_utils->sts_target()->Dispatch(
         WrapRunnable(this,
                         &IceTestPeer::ParseCandidate_s,
                         i,
                         candidate),
         NS_DISPATCH_SYNC);
   }
 
   void DisableComponent_s(size_t stream, int component_id) {
-    ASSERT_LT(stream, ice_ctx_->GetStreamCount());
-    ASSERT_TRUE(ice_ctx_->GetStream(stream).get()) << "No such stream " << stream;
-    nsresult res = ice_ctx_->GetStream(stream)->DisableComponent(component_id);
+    ASSERT_LT(stream, ice_ctx_->ctx()->GetStreamCount());
+    ASSERT_TRUE(ice_ctx_->ctx()->GetStream(stream).get()) << "No such stream " << stream;
+    nsresult res =
+      ice_ctx_->ctx()->GetStream(stream)->DisableComponent(component_id);
     ASSERT_TRUE(NS_SUCCEEDED(res));
   }
 
   void DisableComponent(size_t stream, int component_id)
   {
     test_utils->sts_target()->Dispatch(
         WrapRunnable(this,
                         &IceTestPeer::DisableComponent_s,
@@ -1163,33 +1178,33 @@ class IceTestPeer : public sigslot::has_
         NS_DISPATCH_SYNC);
   }
 
   int trickled() { return trickled_; }
 
   void SetControlling(NrIceCtx::Controlling controlling) {
     nsresult res;
     test_utils->sts_target()->Dispatch(
-        WrapRunnableRet(&res, ice_ctx_,
+        WrapRunnableRet(&res, ice_ctx_->ctx(),
                         &NrIceCtx::SetControlling,
                         controlling),
         NS_DISPATCH_SYNC);
     ASSERT_TRUE(NS_SUCCEEDED(res));
   }
 
   void SetTiebreaker(uint64_t tiebreaker) {
     test_utils->sts_target()->Dispatch(
         WrapRunnable(this,
                      &IceTestPeer::SetTiebreaker_s,
                      tiebreaker),
         NS_DISPATCH_SYNC);
   }
 
   void SetTiebreaker_s(uint64_t tiebreaker) {
-    ice_ctx_->peer()->tiebreaker = tiebreaker;
+    ice_ctx_->ctx()->peer()->tiebreaker = tiebreaker;
   }
 
   void SimulateIceLite() {
     simulate_ice_lite_ = true;
     SetControlling(NrIceCtx::ICE_CONTROLLED);
   }
 
   nsresult GetDefaultCandidate(unsigned int stream, NrIceCandidate* cand) {
@@ -1200,17 +1215,17 @@ class IceTestPeer : public sigslot::has_
                         &IceTestPeer::GetDefaultCandidate_s,
                         stream, cand),
         NS_DISPATCH_SYNC);
 
     return rv;
   }
 
   nsresult GetDefaultCandidate_s(unsigned int stream, NrIceCandidate* cand) {
-    return ice_ctx_->GetStream(stream)->GetDefaultCandidate(1, cand);
+    return ice_ctx_->ctx()->GetStream(stream)->GetDefaultCandidate(1, cand);
   }
 
  private:
   std::string name_;
   RefPtr<NrIceCtxHandler> ice_ctx_;
   std::map<std::string, std::vector<std::string> > candidates_;
   // Maps from stream id to list of remote trickle candidates
   std::map<size_t, std::vector<SchedulableTrickleCandidate*> >
--- a/media/mtransport/test/multi_tcp_socket_unittest.cpp
+++ b/media/mtransport/test/multi_tcp_socket_unittest.cpp
@@ -95,26 +95,26 @@ class MultiTcpSocketTest : public ::test
     int r;
 
     if (!stun_server_addr.empty()) {
       std::vector<NrIceStunServer> stun_servers;
       ScopedDeletePtr<NrIceStunServer> server(NrIceStunServer::Create(
           stun_server_addr, stun_server_port, kNrIceTransportTcp));
       stun_servers.push_back(*server);
 
-      ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetStunServers(stun_servers)));
+      ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->ctx()->SetStunServers(stun_servers)));
     }
 
     r = 1;
     for (int tries=10; tries && r; --tries) {
       r = nr_str_port_to_transport_addr(
         (char *)"127.0.0.1", EnsureEphemeral(port_s++), IPPROTO_TCP, &local);
       ASSERT_EQ(0, r);
 
-      r = nr_socket_multi_tcp_create(ice_ctx_->ctx(),
+      r = nr_socket_multi_tcp_create(ice_ctx_->ctx()->ctx(),
           &local, tcp_type, 1, 2048, sock);
     }
 
     ASSERT_EQ(0, r);
     printf("Creating socket on %s\n", local.as_string);
     r = nr_socket_multi_tcp_set_readable_cb(*sock,
         &MultiTcpSocketTest::SockReadable, this);
     ASSERT_EQ(0, r);
@@ -334,17 +334,17 @@ class MultiTcpSocketTest : public ::test
   bool IsReadable() const {
     return readable;
   }
   void SetReadable(bool r) {
     readable=r;
   }
   std::vector<nr_socket *> socks;
   Atomic<bool> readable;
-  RefPtr<NrIceCtx> ice_ctx_;
+  RefPtr<NrIceCtxHandler> ice_ctx_;
 };
 }
 
 TEST_F(MultiTcpSocketTest, TestListen) {
   socks[0] = Create(TCP_TYPE_PASSIVE);
   Listen(socks[0]);
 }
 
--- a/media/mtransport/test/transport_unittests.cpp
+++ b/media/mtransport/test/transport_unittests.cpp
@@ -455,17 +455,17 @@ class TransportTestPeer : public sigslot
         gathering_complete_(false),
         enabled_cipersuites_(),
         disabled_cipersuites_(),
         reuse_dhe_key_(false) {
     std::vector<NrIceStunServer> stun_servers;
     UniquePtr<NrIceStunServer> server(NrIceStunServer::Create(
         std::string((char *)"stun.services.mozilla.com"), 3478));
     stun_servers.push_back(*server);
-    EXPECT_TRUE(NS_SUCCEEDED(ice_ctx_->SetStunServers(stun_servers)));
+    EXPECT_TRUE(NS_SUCCEEDED(ice_ctx_->ctx()->SetStunServers(stun_servers)));
 
     dtls_->SetIdentity(identity_);
     dtls_->SetRole(name == "P2" ?
                    TransportLayerDtls::CLIENT :
                    TransportLayerDtls::SERVER);
 
     nsresult res = identity_->ComputeFingerprint("sha-1",
                                              fingerprint_,
@@ -598,38 +598,38 @@ class TransportTestPeer : public sigslot
                                peer),
                   NS_DISPATCH_SYNC);
   }
 
   void InitIce() {
     nsresult res;
 
     // Attach our slots
-    ice_ctx_->SignalGatheringStateChange.
+    ice_ctx_->ctx()->SignalGatheringStateChange.
         connect(this, &TransportTestPeer::GatheringStateChange);
 
     char name[100];
     snprintf(name, sizeof(name), "%s:stream%d", name_.c_str(),
              (int)streams_.size());
 
     // Create the media stream
     RefPtr<NrIceMediaStream> stream =
         ice_ctx_->CreateStream(static_cast<char *>(name), 1);
 
     ASSERT_TRUE(stream != nullptr);
-    ice_ctx_->SetStream(streams_.size(), stream);
+    ice_ctx_->ctx()->SetStream(streams_.size(), stream);
     streams_.push_back(stream);
 
     // Listen for candidates
     stream->SignalCandidate.
         connect(this, &TransportTestPeer::GotCandidate);
 
     // Create the transport layer
     ice_ = new TransportLayerIce(name);
-    ice_->SetParameters(ice_ctx_, stream, 1);
+    ice_->SetParameters(ice_ctx_->ctx(), stream, 1);
 
     // Assemble the stack
     nsAutoPtr<std::queue<mozilla::TransportLayer *> > layers(
       new std::queue<mozilla::TransportLayer *>);
     layers->push(ice_);
     layers->push(dtls_);
 
     test_utils->sts_target()->Dispatch(
@@ -639,17 +639,17 @@ class TransportTestPeer : public sigslot
     ASSERT_EQ((nsresult)NS_OK, res);
 
     // Listen for media events
     flow_->SignalPacketReceived.connect(this, &TransportTestPeer::PacketReceived);
     flow_->SignalStateChange.connect(this, &TransportTestPeer::StateChanged);
 
     // Start gathering
     test_utils->sts_target()->Dispatch(
-        WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::StartGathering),
+        WrapRunnableRet(&res, ice_ctx_->ctx(), &NrIceCtx::StartGathering),
         NS_DISPATCH_SYNC);
     ASSERT_TRUE(NS_SUCCEEDED(res));
   }
 
   void ConnectIce(TransportTestPeer *peer) {
     peer_ = peer;
 
     // If gathering is already complete, push the candidates over
@@ -679,33 +679,33 @@ class TransportTestPeer : public sigslot
     // Don't send to the other side
     if (!peer_) {
       gathering_complete_ = true;
       return;
     }
 
     // First send attributes
     test_utils->sts_target()->Dispatch(
-      WrapRunnableRet(&res, peer_->ice_ctx_,
+      WrapRunnableRet(&res, peer_->ice_ctx_->ctx(),
                       &NrIceCtx::ParseGlobalAttributes,
-                      ice_ctx_->GetGlobalAttributes()),
+                      ice_ctx_->ctx()->GetGlobalAttributes()),
       NS_DISPATCH_SYNC);
     ASSERT_TRUE(NS_SUCCEEDED(res));
 
     for (size_t i=0; i<streams_.size(); ++i) {
       test_utils->sts_target()->Dispatch(
         WrapRunnableRet(&res, peer_->streams_[i], &NrIceMediaStream::ParseAttributes,
                         candidates_[streams_[i]->name()]), NS_DISPATCH_SYNC);
 
       ASSERT_TRUE(NS_SUCCEEDED(res));
     }
 
     // Start checks on the other peer.
     test_utils->sts_target()->Dispatch(
-      WrapRunnableRet(&res, peer_->ice_ctx_, &NrIceCtx::StartChecks),
+      WrapRunnableRet(&res, peer_->ice_ctx_->ctx(), &NrIceCtx::StartChecks),
       NS_DISPATCH_SYNC);
     ASSERT_TRUE(NS_SUCCEEDED(res));
   }
 
   TransportResult SendPacket(const unsigned char* data, size_t len) {
     TransportResult ret;
     test_utils->sts_target()->Dispatch(
       WrapRunnableRet(&ret, flow_, &TransportFlow::SendPacket, data, len),
--- a/media/webrtc/signaling/src/peerconnection/MediaPipelineFactory.cpp
+++ b/media/webrtc/signaling/src/peerconnection/MediaPipelineFactory.cpp
@@ -182,18 +182,19 @@ NegotiatedDetailsToVideoCodecConfigs(con
 static void
 FinalizeTransportFlow_s(RefPtr<PeerConnectionMedia> aPCMedia,
                         RefPtr<TransportFlow> aFlow, size_t aLevel,
                         bool aIsRtcp,
                         nsAutoPtr<PtrVector<TransportLayer> > aLayerList)
 {
   TransportLayerIce* ice =
       static_cast<TransportLayerIce*>(aLayerList->values.front());
-  ice->SetParameters(
-      aPCMedia->ice_ctx(), aPCMedia->ice_media_stream(aLevel), aIsRtcp ? 2 : 1);
+  ice->SetParameters(aPCMedia->ice_ctx(),
+                     aPCMedia->ice_media_stream(aLevel),
+                     aIsRtcp ? 2 : 1);
   nsAutoPtr<std::queue<TransportLayer*> > layerQueue(
       new std::queue<TransportLayer*>);
   for (auto i = aLayerList->values.begin(); i != aLayerList->values.end();
        ++i) {
     layerQueue->push(*i);
   }
   aLayerList->values.clear();
   (void)aFlow->PushLayers(layerQueue); // TODO(bug 854518): Process errors.
@@ -219,17 +220,17 @@ MediaPipelineFactory::CreateOrGetTranspo
     const JsepTransport& aTransport,
     RefPtr<TransportFlow>* aFlowOutparam)
 {
   nsresult rv;
   RefPtr<TransportFlow> flow;
 
   flow = mPCMedia->GetTransportFlow(aLevel, aIsRtcp);
   if (flow) {
-    if (mPCMedia->ice_ctx()->IsRestarting()) {
+    if (mPCMedia->ice_ctx_hdlr()->IsRestarting()) {
       MOZ_MTLOG(ML_INFO, "Flow[" << flow->id() << "]: "
                                  << "detected ICE restart - level: "
                                  << aLevel << " rtcp: " << aIsRtcp);
 
       rv = mPCMedia->GetSTSThread()->Dispatch(
           WrapRunnableNM(AddNewIceStreamForRestart_s,
                          mPCMedia, flow, aLevel, aIsRtcp),
           NS_DISPATCH_NORMAL);
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -2775,17 +2775,17 @@ PeerConnectionImpl::SetSignalingState_m(
        !rollback)) {
     mMedia->EnsureTransports(*mJsepSession);
   }
 
   mSignalingState = aSignalingState;
 
   bool fireNegotiationNeeded = false;
   if (mSignalingState == PCImplSignalingState::SignalingStable) {
-    if (rollback && mMedia->ice_ctx()->IsRestarting()) {
+    if (rollback && mMedia->ice_ctx_hdlr()->IsRestarting()) {
       mMedia->RollbackIceRestart();
     }
 
     // Either negotiation is done, or we've rolled back. In either case, we
     // need to re-evaluate whether further negotiation is required.
     mNegotiationNeeded = false;
     // If we're rolling back a local offer, we might need to remove some
     // transports, but nothing further needs to be done.
@@ -3072,17 +3072,17 @@ void PeerConnectionImpl::IceConnectionSt
     }
   }
 #endif
 
   mIceConnectionState = domState;
 
   if (mIceConnectionState == PCImplIceConnectionState::Connected ||
       mIceConnectionState == PCImplIceConnectionState::Completed) {
-    if (mMedia->ice_ctx()->IsRestarting()) {
+    if (mMedia->ice_ctx_hdlr()->IsRestarting()) {
       mMedia->FinalizeIceRestart();
     }
   }
 
   // Would be nice if we had a means of converting one of these dom enums
   // to a string that wasn't almost as much text as this switch statement...
   switch (mIceConnectionState) {
     case PCImplIceConnectionState::New:
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
@@ -198,17 +198,17 @@ PeerConnectionMedia::ProtocolProxyQueryH
   }
 
   rv = proxyinfo.GetPort(&httpsProxyPort);
   if (NS_FAILED(rv)) {
     CSFLogError(logTag, "%s: Failed to get proxy server port", __FUNCTION__);
     return;
   }
 
-  if (pcm_->mIceCtx.get()) {
+  if (pcm_->mIceCtxHdlr.get()) {
     assert(httpsProxyPort >= 0 && httpsProxyPort < (1 << 16));
     // Note that this could check if PrivacyRequested() is set on the PC and
     // remove "webrtc" from the ALPN list.  But that would only work if the PC
     // was constructed with a peerIdentity constraint, not when isolated
     // streams are added.  If we ever need to signal to the proxy that the
     // media is isolated, then we would need to restructure this code.
     pcm_->mProxyServer.reset(
       new NrIceProxyServer(httpsProxyHost.get(),
@@ -222,17 +222,17 @@ PeerConnectionMedia::ProtocolProxyQueryH
 
 NS_IMPL_ISUPPORTS(PeerConnectionMedia::ProtocolProxyQueryHandler, nsIProtocolProxyCallback)
 #endif // !defined(MOZILLA_XPCOMRT_API)
 
 PeerConnectionMedia::PeerConnectionMedia(PeerConnectionImpl *parent)
     : mParent(parent),
       mParentHandle(parent->GetHandle()),
       mParentName(parent->GetName()),
-      mIceCtx(nullptr),
+      mIceCtxHdlr(nullptr),
       mDNSResolver(new NrIceResolver()),
       mUuidGen(MakeUnique<PCUuidGenerator>()),
       mMainThread(mParent->GetMainThread()),
       mSTSThread(mParent->GetSTSThread()),
       mProxyResolveCompleted(false) {
 }
 
 nsresult PeerConnectionMedia::Init(const std::vector<NrIceStunServer>& stun_servers,
@@ -319,58 +319,58 @@ nsresult PeerConnectionMedia::Init(const
 #else
   bool ice_tcp = false;
   bool default_address_only = false;
 #endif
 
 
   // TODO(ekr@rtfm.com): need some way to set not offerer later
   // Looks like a bug in the NrIceCtx API.
-  mIceCtx = NrIceCtxHandler::Create("PC:" + mParentName,
-                                    true, // Offerer
-                                    mParent->GetAllowIceLoopback(),
-                                    ice_tcp,
-                                    mParent->GetAllowIceLinkLocal(),
-                                    default_address_only,
-                                    policy);
-  if(!mIceCtx) {
+  mIceCtxHdlr = NrIceCtxHandler::Create("PC:" + mParentName,
+                                        true, // Offerer
+                                        mParent->GetAllowIceLoopback(),
+                                        ice_tcp,
+                                        mParent->GetAllowIceLinkLocal(),
+                                        default_address_only,
+                                        policy);
+  if(!mIceCtxHdlr) {
     CSFLogError(logTag, "%s: Failed to create Ice Context", __FUNCTION__);
     return NS_ERROR_FAILURE;
   }
 
-  if (NS_FAILED(rv = mIceCtx->SetStunServers(stun_servers))) {
+  if (NS_FAILED(rv = mIceCtxHdlr->ctx()->SetStunServers(stun_servers))) {
     CSFLogError(logTag, "%s: Failed to set stun servers", __FUNCTION__);
     return rv;
   }
   // Give us a way to globally turn off TURN support
 #if !defined(MOZILLA_EXTERNAL_LINKAGE)
   bool disabled = Preferences::GetBool("media.peerconnection.turn.disable", false);
 #else
   bool disabled = false;
 #endif
   if (!disabled) {
-    if (NS_FAILED(rv = mIceCtx->SetTurnServers(turn_servers))) {
+    if (NS_FAILED(rv = mIceCtxHdlr->ctx()->SetTurnServers(turn_servers))) {
       CSFLogError(logTag, "%s: Failed to set turn servers", __FUNCTION__);
       return rv;
     }
   } else if (turn_servers.size() != 0) {
     CSFLogError(logTag, "%s: Setting turn servers disabled", __FUNCTION__);
   }
   if (NS_FAILED(rv = mDNSResolver->Init())) {
     CSFLogError(logTag, "%s: Failed to initialize dns resolver", __FUNCTION__);
     return rv;
   }
-  if (NS_FAILED(rv = mIceCtx->SetResolver(mDNSResolver->AllocateResolver()))) {
+  if (NS_FAILED(rv = mIceCtxHdlr->ctx()->SetResolver(mDNSResolver->AllocateResolver()))) {
     CSFLogError(logTag, "%s: Failed to get dns resolver", __FUNCTION__);
     return rv;
   }
-  mIceCtx->SignalGatheringStateChange.connect(
+  mIceCtxHdlr->ctx()->SignalGatheringStateChange.connect(
       this,
       &PeerConnectionMedia::IceGatheringStateChange_s);
-  mIceCtx->SignalConnectionStateChange.connect(
+  mIceCtxHdlr->ctx()->SignalConnectionStateChange.connect(
       this,
       &PeerConnectionMedia::IceConnectionStateChange_s);
 
   return NS_OK;
 }
 
 void
 PeerConnectionMedia::EnsureTransports(const JsepSession& aSession)
@@ -388,38 +388,38 @@ PeerConnectionMedia::EnsureTransports(co
   }
 
   GatherIfReady();
 }
 
 void
 PeerConnectionMedia::EnsureTransport_s(size_t aLevel, size_t aComponentCount)
 {
-  RefPtr<NrIceMediaStream> stream(mIceCtx->GetStream(aLevel));
+  RefPtr<NrIceMediaStream> stream(mIceCtxHdlr->ctx()->GetStream(aLevel));
   if (!stream) {
     CSFLogDebug(logTag, "%s: Creating ICE media stream=%u components=%u",
                 mParentHandle.c_str(),
                 static_cast<unsigned>(aLevel),
                 static_cast<unsigned>(aComponentCount));
 
     std::ostringstream os;
     os << mParentName << " aLevel=" << aLevel;
-    RefPtr<NrIceMediaStream> stream = mIceCtx->CreateStream(os.str().c_str(),
+    RefPtr<NrIceMediaStream> stream = mIceCtxHdlr->CreateStream(os.str().c_str(),
                                                             aComponentCount);
 
     if (!stream) {
       CSFLogError(logTag, "Failed to create ICE stream.");
       return;
     }
 
     stream->SetLevel(aLevel);
     stream->SignalReady.connect(this, &PeerConnectionMedia::IceStreamReady_s);
     stream->SignalCandidate.connect(this,
                                     &PeerConnectionMedia::OnCandidateFound_s);
-    mIceCtx->SetStream(aLevel, stream);
+    mIceCtxHdlr->ctx()->SetStream(aLevel, stream);
   }
 }
 
 void
 PeerConnectionMedia::ActivateOrRemoveTransports(const JsepSession& aSession)
 {
   auto transports = aSession.GetTransports();
   for (size_t i = 0; i < transports.size(); ++i) {
@@ -470,21 +470,21 @@ PeerConnectionMedia::ActivateOrRemoveTra
     const std::string& aUfrag,
     const std::string& aPassword,
     const std::vector<std::string>& aCandidateList) {
 
   if (!aComponentCount) {
     CSFLogDebug(logTag, "%s: Removing ICE media stream=%u",
                 mParentHandle.c_str(),
                 static_cast<unsigned>(aMLine));
-    mIceCtx->SetStream(aMLine, nullptr);
+    mIceCtxHdlr->ctx()->SetStream(aMLine, nullptr);
     return;
   }
 
-  RefPtr<NrIceMediaStream> stream(mIceCtx->GetStream(aMLine));
+  RefPtr<NrIceMediaStream> stream(mIceCtxHdlr->ctx()->GetStream(aMLine));
   if (!stream) {
     MOZ_ASSERT(false);
     return;
   }
 
   if (!stream->HasParsedAttributes()) {
     CSFLogDebug(logTag, "%s: Activating ICE media stream=%u components=%u",
                 mParentHandle.c_str(),
@@ -509,18 +509,18 @@ PeerConnectionMedia::ActivateOrRemoveTra
       stream->DisableComponent(c + 1);
     }
   }
 }
 
 void
 PeerConnectionMedia::RemoveTransportsAtOrAfter_s(size_t aMLine)
 {
-  for (size_t i = aMLine; i < mIceCtx->GetStreamCount(); ++i) {
-    mIceCtx->SetStream(i, nullptr);
+  for (size_t i = aMLine; i < mIceCtxHdlr->ctx()->GetStreamCount(); ++i) {
+    mIceCtxHdlr->ctx()->SetStream(i, nullptr);
   }
 }
 
 nsresult PeerConnectionMedia::UpdateMediaPipelines(
     const JsepSession& session) {
   auto trackPairs = session.GetNegotiatedTrackPairs();
   MediaPipelineFactory factory(this);
   nsresult rv;
@@ -580,26 +580,26 @@ PeerConnectionMedia::StartIceChecks_s(
 
   if (!aIceOptionsList.empty()) {
     attributes.push_back("ice-options:");
     for (auto i = aIceOptionsList.begin(); i != aIceOptionsList.end(); ++i) {
       attributes.back() += *i + ' ';
     }
   }
 
-  nsresult rv = mIceCtx->ParseGlobalAttributes(attributes);
+  nsresult rv = mIceCtxHdlr->ctx()->ParseGlobalAttributes(attributes);
   if (NS_FAILED(rv)) {
     CSFLogError(logTag, "%s: couldn't parse global parameters", __FUNCTION__ );
   }
 
-  mIceCtx->SetControlling(aIsControlling ?
+  mIceCtxHdlr->ctx()->SetControlling(aIsControlling ?
                           NrIceCtx::ICE_CONTROLLING :
                           NrIceCtx::ICE_CONTROLLED);
 
-  mIceCtx->StartChecks();
+  mIceCtxHdlr->ctx()->StartChecks();
 }
 
 void
 PeerConnectionMedia::BeginIceRestart(const std::string& ufrag,
                                      const std::string& pwd)
 {
   ASSERT_ON_THREAD(mMainThread);
 
@@ -613,17 +613,25 @@ PeerConnectionMedia::BeginIceRestart(con
 }
 
 void
 PeerConnectionMedia::BeginIceRestart_s(const std::string& ufrag,
                                        const std::string& pwd)
 {
   ASSERT_ON_THREAD(mSTSThread);
 
-  ice_ctx()->BeginIceRestart(ufrag, pwd);
+  mIceCtxHdlr->BeginIceRestart(ufrag, pwd);
+  if (mIceCtxHdlr->IsRestarting()) {
+  mIceCtxHdlr->ctx()->SignalGatheringStateChange.connect(
+      this,
+      &PeerConnectionMedia::IceGatheringStateChange_s);
+  mIceCtxHdlr->ctx()->SignalConnectionStateChange.connect(
+      this,
+      &PeerConnectionMedia::IceConnectionStateChange_s);
+  }
 }
 
 void
 PeerConnectionMedia::FinalizeIceRestart()
 {
   ASSERT_ON_THREAD(mMainThread);
 
   RUN_ON_THREAD(GetSTSThread(),
@@ -633,17 +641,17 @@ PeerConnectionMedia::FinalizeIceRestart(
                 NS_DISPATCH_NORMAL);
 }
 
 void
 PeerConnectionMedia::FinalizeIceRestart_s()
 {
   ASSERT_ON_THREAD(mSTSThread);
 
-  ice_ctx()->FinalizeIceRestart();
+  mIceCtxHdlr->FinalizeIceRestart();
 }
 
 void
 PeerConnectionMedia::RollbackIceRestart()
 {
   ASSERT_ON_THREAD(mMainThread);
 
   RUN_ON_THREAD(GetSTSThread(),
@@ -653,17 +661,17 @@ PeerConnectionMedia::RollbackIceRestart(
                 NS_DISPATCH_NORMAL);
 }
 
 void
 PeerConnectionMedia::RollbackIceRestart_s()
 {
   ASSERT_ON_THREAD(mSTSThread);
 
-  ice_ctx()->RollbackIceRestart();
+  mIceCtxHdlr->RollbackIceRestart();
 }
 
 void
 PeerConnectionMedia::AddIceCandidate(const std::string& candidate,
                                      const std::string& mid,
                                      uint32_t aMLine) {
   RUN_ON_THREAD(GetSTSThread(),
                 WrapRunnable(
@@ -673,17 +681,17 @@ PeerConnectionMedia::AddIceCandidate(con
                     std::string(mid),
                     aMLine),
                 NS_DISPATCH_NORMAL);
 }
 void
 PeerConnectionMedia::AddIceCandidate_s(const std::string& aCandidate,
                                        const std::string& aMid,
                                        uint32_t aMLine) {
-  RefPtr<NrIceMediaStream> stream(mIceCtx->GetStream(aMLine));
+  RefPtr<NrIceMediaStream> stream(mIceCtxHdlr->ctx()->GetStream(aMLine));
   if (!stream) {
     CSFLogError(logTag, "No ICE stream for candidate at level %u: %s",
                         static_cast<unsigned>(aMLine), aCandidate.c_str());
     return;
   }
 
   nsresult rv = stream->ParseTrickleCandidate(aCandidate);
   if (NS_FAILED(rv)) {
@@ -729,31 +737,32 @@ PeerConnectionMedia::GatherIfReady() {
         &PeerConnectionMedia::EnsureIceGathering_s));
 
   PerformOrEnqueueIceCtxOperation(runnable);
 }
 
 void
 PeerConnectionMedia::EnsureIceGathering_s() {
   if (mProxyServer) {
-    mIceCtx->SetProxyServer(*mProxyServer);
+    mIceCtxHdlr->ctx()->SetProxyServer(*mProxyServer);
   }
 
   // Start gathering, but only if there are streams
-  for (size_t i = 0; i < mIceCtx->GetStreamCount(); ++i) {
-    if (mIceCtx->GetStream(i)) {
-      mIceCtx->StartGathering();
+  for (size_t i = 0; i < mIceCtxHdlr->ctx()->GetStreamCount(); ++i) {
+    if (mIceCtxHdlr->ctx()->GetStream(i)) {
+      mIceCtxHdlr->ctx()->StartGathering();
       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(mIceCtx.get(), NrIceCtx::ICE_CTX_GATHER_COMPLETE);
+  IceGatheringStateChange_s(mIceCtxHdlr->ctx().get(),
+                            NrIceCtx::ICE_CTX_GATHER_COMPLETE);
 }
 
 nsresult
 PeerConnectionMedia::AddTrack(DOMMediaStream* aMediaStream,
                               const std::string& streamId,
                               const std::string& trackId)
 {
   ASSERT_ON_THREAD(mMainThread);
@@ -897,17 +906,17 @@ PeerConnectionMedia::ShutdownMediaTransp
   }
 
   for (uint32_t i=0; i < mRemoteSourceStreams.Length(); ++i) {
     mRemoteSourceStreams[i]->DetachTransport_s();
   }
 
   disconnect_all();
   mTransportFlows.clear();
-  mIceCtx = nullptr;
+  mIceCtxHdlr = nullptr;
 
   mMainThread->Dispatch(WrapRunnable(this, &PeerConnectionMedia::SelfDestruct_m),
                         NS_DISPATCH_NORMAL);
 }
 
 LocalSourceStreamInfo*
 PeerConnectionMedia::GetLocalStreamByIndex(int aIndex)
 {
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
@@ -228,24 +228,25 @@ class PeerConnectionMedia : public sigsl
 
   PeerConnectionImpl* GetPC() { return mParent; }
   nsresult Init(const std::vector<NrIceStunServer>& stun_servers,
                 const std::vector<NrIceTurnServer>& turn_servers,
                 NrIceCtx::Policy policy);
   // WARNING: This destroys the object!
   void SelfDestruct();
 
-  RefPtr<NrIceCtxHandler> ice_ctx() const { return mIceCtx; }
+  RefPtr<NrIceCtxHandler> ice_ctx_hdlr() const { return mIceCtxHdlr; }
+  RefPtr<NrIceCtx> ice_ctx() const { return mIceCtxHdlr->ctx(); }
 
   RefPtr<NrIceMediaStream> ice_media_stream(size_t i) const {
-    return mIceCtx->GetStream(i);
+    return mIceCtxHdlr->ctx()->GetStream(i);
   }
 
   size_t num_ice_media_streams() const {
-    return mIceCtx->GetStreamCount();
+    return mIceCtxHdlr->ctx()->GetStreamCount();
   }
 
   // Ensure ICE transports exist that we might need when offer/answer concludes
   void EnsureTransports(const JsepSession& aSession);
 
   // Activate or remove ICE transports at the conclusion of offer/answer,
   // or when rollback occurs.
   void ActivateOrRemoveTransports(const JsepSession& aSession);
@@ -508,17 +509,17 @@ class PeerConnectionMedia : public sigsl
 
   // A list of streams provided by the other side
   // This is only accessed on the main thread (with one special exception)
   nsTArray<RefPtr<RemoteSourceStreamInfo> > mRemoteSourceStreams;
 
   std::map<size_t, std::pair<bool, RefPtr<MediaSessionConduit>>> mConduits;
 
   // ICE objects
-  RefPtr<NrIceCtxHandler> mIceCtx;
+  RefPtr<NrIceCtxHandler> mIceCtxHdlr;
 
   // DNS
   RefPtr<NrIceResolver> mDNSResolver;
 
   // Transport flows: even is RTP, odd is RTCP
   std::map<int, RefPtr<TransportFlow> > mTransportFlows;
 
   // UUID Generator