LCOV - code coverage report
Current view: top level - media/webrtc/signaling/src/peerconnection - PeerConnectionMedia.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 831 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 97 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Public
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       3             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : #include <ostream>
       6             : #include <string>
       7             : #include <vector>
       8             : 
       9             : #include "CSFLog.h"
      10             : 
      11             : #include "nspr.h"
      12             : 
      13             : #include "nricectx.h"
      14             : #include "nricemediastream.h"
      15             : #include "MediaPipelineFactory.h"
      16             : #include "PeerConnectionImpl.h"
      17             : #include "PeerConnectionMedia.h"
      18             : #include "AudioConduit.h"
      19             : #include "VideoConduit.h"
      20             : #include "runnable_utils.h"
      21             : #include "transportlayerice.h"
      22             : #include "transportlayerdtls.h"
      23             : #include "signaling/src/jsep/JsepSession.h"
      24             : #include "signaling/src/jsep/JsepTransport.h"
      25             : 
      26             : #include "MediaSegment.h"
      27             : #include "MediaStreamGraph.h"
      28             : 
      29             : #include "MediaStreamGraphImpl.h"
      30             : 
      31             : #include "nsNetCID.h"
      32             : #include "nsNetUtil.h"
      33             : #include "nsIURI.h"
      34             : #include "nsIScriptSecurityManager.h"
      35             : #include "nsICancelable.h"
      36             : #include "nsILoadInfo.h"
      37             : #include "nsIContentPolicy.h"
      38             : #include "nsIProxyInfo.h"
      39             : #include "nsIProtocolProxyService.h"
      40             : 
      41             : #include "nsProxyRelease.h"
      42             : 
      43             : #include "MediaStreamList.h"
      44             : #include "nsIScriptGlobalObject.h"
      45             : #include "mozilla/Preferences.h"
      46             : #include "mozilla/Telemetry.h"
      47             : #include "mozilla/dom/RTCStatsReportBinding.h"
      48             : #include "MediaStreamTrack.h"
      49             : #include "VideoStreamTrack.h"
      50             : #include "MediaStreamError.h"
      51             : #include "MediaManager.h"
      52             : 
      53             : 
      54             : 
      55             : namespace mozilla {
      56             : using namespace dom;
      57             : 
      58             : static const char* logTag = "PeerConnectionMedia";
      59             : 
      60             : //XXX(pkerr) What about bitrate settings? Going with the defaults for now.
      61             : RefPtr<WebRtcCallWrapper>
      62           0 : CreateCall()
      63             : {
      64           0 :   return WebRtcCallWrapper::Create();
      65             : }
      66             : 
      67             : nsresult
      68           0 : PeerConnectionMedia::ReplaceTrack(const std::string& aOldStreamId,
      69             :                                   const std::string& aOldTrackId,
      70             :                                   MediaStreamTrack& aNewTrack,
      71             :                                   const std::string& aNewStreamId,
      72             :                                   const std::string& aNewTrackId)
      73             : {
      74           0 :   RefPtr<LocalSourceStreamInfo> oldInfo(GetLocalStreamById(aOldStreamId));
      75             : 
      76           0 :   if (!oldInfo) {
      77           0 :     CSFLogError(logTag, "Failed to find stream id %s", aOldStreamId.c_str());
      78           0 :     return NS_ERROR_NOT_AVAILABLE;
      79             :   }
      80             : 
      81           0 :   nsresult rv = AddTrack(*aNewTrack.mOwningStream, aNewStreamId,
      82           0 :                          aNewTrack, aNewTrackId);
      83           0 :   NS_ENSURE_SUCCESS(rv, rv);
      84             : 
      85           0 :   RefPtr<LocalSourceStreamInfo> newInfo(GetLocalStreamById(aNewStreamId));
      86             : 
      87           0 :   if (!newInfo) {
      88           0 :     CSFLogError(logTag, "Failed to add track id %s", aNewTrackId.c_str());
      89           0 :     MOZ_ASSERT(false);
      90             :     return NS_ERROR_FAILURE;
      91             :   }
      92             : 
      93           0 :   rv = newInfo->TakePipelineFrom(oldInfo, aOldTrackId, aNewTrack, aNewTrackId);
      94           0 :   NS_ENSURE_SUCCESS(rv, rv);
      95             : 
      96           0 :   return RemoveLocalTrack(aOldStreamId, aOldTrackId);
      97             : }
      98             : 
      99             : static void
     100           0 : PipelineReleaseRef_m(RefPtr<MediaPipeline> pipeline)
     101           0 : {}
     102             : 
     103             : static void
     104           0 : PipelineDetachTransport_s(RefPtr<MediaPipeline> pipeline,
     105             :                           nsCOMPtr<nsIThread> mainThread)
     106             : {
     107           0 :   pipeline->DetachTransport_s();
     108           0 :   mainThread->Dispatch(
     109             :       // Make sure we let go of our reference before dispatching
     110             :       // If the dispatch fails, well, we're hosed anyway.
     111           0 :       WrapRunnableNM(PipelineReleaseRef_m, pipeline.forget()),
     112           0 :       NS_DISPATCH_NORMAL);
     113           0 : }
     114             : 
     115             : void
     116           0 : SourceStreamInfo::EndTrack(MediaStream* stream, dom::MediaStreamTrack* track)
     117             : {
     118           0 :   if (!stream || !stream->AsSourceStream()) {
     119           0 :     return;
     120             :   }
     121             : 
     122           0 :   class Message : public ControlMessage {
     123             :    public:
     124           0 :     Message(MediaStream* stream, TrackID track)
     125           0 :       : ControlMessage(stream),
     126           0 :         track_id_(track) {}
     127             : 
     128           0 :     virtual void Run() override {
     129           0 :       mStream->AsSourceStream()->EndTrack(track_id_);
     130           0 :     }
     131             :    private:
     132             :     TrackID track_id_;
     133             :   };
     134             : 
     135           0 :   stream->GraphImpl()->AppendMessage(
     136           0 :       MakeUnique<Message>(stream, track->mTrackID));
     137             : }
     138             : 
     139             : void
     140           0 : SourceStreamInfo::RemoveTrack(const std::string& trackId)
     141             : {
     142           0 :   mTracks.erase(trackId);
     143             : 
     144           0 :   RefPtr<MediaPipeline> pipeline = GetPipelineByTrackId_m(trackId);
     145           0 :   if (pipeline) {
     146           0 :     mPipelines.erase(trackId);
     147           0 :     pipeline->ShutdownMedia_m();
     148           0 :     mParent->GetSTSThread()->Dispatch(
     149           0 :         WrapRunnableNM(PipelineDetachTransport_s,
     150           0 :                        pipeline.forget(),
     151           0 :                        mParent->GetMainThread()),
     152           0 :         NS_DISPATCH_NORMAL);
     153             :   }
     154           0 : }
     155             : 
     156           0 : void SourceStreamInfo::DetachTransport_s()
     157             : {
     158           0 :   ASSERT_ON_THREAD(mParent->GetSTSThread());
     159             :   // walk through all the MediaPipelines and call the shutdown
     160             :   // transport functions. Must be on the STS thread.
     161           0 :   for (auto& pipeline : mPipelines) {
     162           0 :     pipeline.second->DetachTransport_s();
     163             :   }
     164           0 : }
     165             : 
     166           0 : void SourceStreamInfo::DetachMedia_m()
     167             : {
     168           0 :   ASSERT_ON_THREAD(mParent->GetMainThread());
     169             : 
     170             :   // walk through all the MediaPipelines and call the shutdown
     171             :   // media functions. Must be on the main thread.
     172           0 :   for (auto& pipeline : mPipelines) {
     173           0 :     pipeline.second->ShutdownMedia_m();
     174             :   }
     175           0 :   mMediaStream = nullptr;
     176           0 : }
     177             : 
     178             : already_AddRefed<PeerConnectionImpl>
     179           0 : PeerConnectionImpl::Constructor(const dom::GlobalObject& aGlobal, ErrorResult& rv)
     180             : {
     181           0 :   RefPtr<PeerConnectionImpl> pc = new PeerConnectionImpl(&aGlobal);
     182             : 
     183           0 :   CSFLogDebug(logTag, "Created PeerConnection: %p", pc.get());
     184             : 
     185           0 :   return pc.forget();
     186             : }
     187             : 
     188           0 : PeerConnectionImpl* PeerConnectionImpl::CreatePeerConnection()
     189             : {
     190           0 :   PeerConnectionImpl *pc = new PeerConnectionImpl();
     191             : 
     192           0 :   CSFLogDebug(logTag, "Created PeerConnection: %p", pc);
     193             : 
     194           0 :   return pc;
     195             : }
     196             : 
     197           0 : NS_IMETHODIMP PeerConnectionMedia::ProtocolProxyQueryHandler::
     198             : OnProxyAvailable(nsICancelable *request,
     199             :                  nsIChannel *aChannel,
     200             :                  nsIProxyInfo *proxyinfo,
     201             :                  nsresult result) {
     202             : 
     203           0 :   if (!pcm_->mProxyRequest) {
     204             :     // PeerConnectionMedia is no longer waiting
     205           0 :     return NS_OK;
     206             :   }
     207             : 
     208           0 :   CSFLogInfo(logTag, "%s: Proxy Available: %d", __FUNCTION__, (int)result);
     209             : 
     210           0 :   if (NS_SUCCEEDED(result) && proxyinfo) {
     211           0 :     SetProxyOnPcm(*proxyinfo);
     212             :   }
     213             : 
     214           0 :   pcm_->mProxyResolveCompleted = true;
     215           0 :   pcm_->mProxyRequest = nullptr;
     216           0 :   pcm_->FlushIceCtxOperationQueueIfReady();
     217             : 
     218           0 :   return NS_OK;
     219             : }
     220             : 
     221             : void
     222           0 : PeerConnectionMedia::ProtocolProxyQueryHandler::SetProxyOnPcm(
     223             :     nsIProxyInfo& proxyinfo)
     224             : {
     225           0 :   CSFLogInfo(logTag, "%s: Had proxyinfo", __FUNCTION__);
     226             :   nsresult rv;
     227           0 :   nsCString httpsProxyHost;
     228             :   int32_t httpsProxyPort;
     229             : 
     230           0 :   rv = proxyinfo.GetHost(httpsProxyHost);
     231           0 :   if (NS_FAILED(rv)) {
     232           0 :     CSFLogError(logTag, "%s: Failed to get proxy server host", __FUNCTION__);
     233           0 :     return;
     234             :   }
     235             : 
     236           0 :   rv = proxyinfo.GetPort(&httpsProxyPort);
     237           0 :   if (NS_FAILED(rv)) {
     238           0 :     CSFLogError(logTag, "%s: Failed to get proxy server port", __FUNCTION__);
     239           0 :     return;
     240             :   }
     241             : 
     242           0 :   if (pcm_->mIceCtxHdlr.get()) {
     243           0 :     assert(httpsProxyPort >= 0 && httpsProxyPort < (1 << 16));
     244             :     // Note that this could check if PrivacyRequested() is set on the PC and
     245             :     // remove "webrtc" from the ALPN list.  But that would only work if the PC
     246             :     // was constructed with a peerIdentity constraint, not when isolated
     247             :     // streams are added.  If we ever need to signal to the proxy that the
     248             :     // media is isolated, then we would need to restructure this code.
     249           0 :     pcm_->mProxyServer.reset(
     250             :       new NrIceProxyServer(httpsProxyHost.get(),
     251             :                            static_cast<uint16_t>(httpsProxyPort),
     252           0 :                            "webrtc,c-webrtc"));
     253             :   } else {
     254             :     CSFLogError(logTag, "%s: Failed to set proxy server (ICE ctx unavailable)",
     255           0 :         __FUNCTION__);
     256             :   }
     257             : }
     258             : 
     259           0 : NS_IMPL_ISUPPORTS(PeerConnectionMedia::ProtocolProxyQueryHandler, nsIProtocolProxyCallback)
     260             : 
     261             : void
     262           0 : PeerConnectionMedia::StunAddrsHandler::OnStunAddrsAvailable(
     263             :     const mozilla::net::NrIceStunAddrArray& addrs)
     264             : {
     265           0 :   CSFLogInfo(logTag, "%s: receiving (%d) stun addrs", __FUNCTION__,
     266           0 :                                                       (int)addrs.Length());
     267           0 :   if (pcm_) {
     268           0 :     pcm_->mStunAddrs = addrs;
     269           0 :     pcm_->mLocalAddrsCompleted = true;
     270           0 :     pcm_->mStunAddrsRequest = nullptr;
     271           0 :     pcm_->FlushIceCtxOperationQueueIfReady();
     272           0 :     pcm_ = nullptr;
     273             :   }
     274           0 : }
     275             : 
     276           0 : PeerConnectionMedia::PeerConnectionMedia(PeerConnectionImpl *parent)
     277             :     : mParent(parent),
     278           0 :       mParentHandle(parent->GetHandle()),
     279           0 :       mParentName(parent->GetName()),
     280             :       mIceCtxHdlr(nullptr),
     281           0 :       mDNSResolver(new NrIceResolver()),
     282             :       mUuidGen(MakeUnique<PCUuidGenerator>()),
     283           0 :       mMainThread(mParent->GetMainThread()),
     284           0 :       mSTSThread(mParent->GetSTSThread()),
     285             :       mProxyResolveCompleted(false),
     286             :       mIceRestartState(ICE_RESTART_NONE),
     287           0 :       mLocalAddrsCompleted(false) {
     288           0 : }
     289             : 
     290             : void
     291           0 : PeerConnectionMedia::InitLocalAddrs()
     292             : {
     293           0 :   if (XRE_IsContentProcess()) {
     294           0 :     CSFLogDebug(logTag, "%s: Get stun addresses via IPC",
     295           0 :                 mParentHandle.c_str());
     296             : 
     297           0 :     nsCOMPtr<nsIEventTarget> target = mParent->GetWindow()
     298           0 :       ? mParent->GetWindow()->EventTargetFor(TaskCategory::Other)
     299           0 :       : nullptr;
     300             : 
     301             :     // We're in the content process, so send a request over IPC for the
     302             :     // stun address discovery.
     303             :     mStunAddrsRequest =
     304           0 :       new StunAddrsRequestChild(new StunAddrsHandler(this), target);
     305           0 :     mStunAddrsRequest->SendGetStunAddrs();
     306             :   } else {
     307             :     // No content process, so don't need to hold up the ice event queue
     308             :     // until completion of stun address discovery. We can let the
     309             :     // discovery of stun addresses happen in the same process.
     310           0 :     mLocalAddrsCompleted = true;
     311             :   }
     312           0 : }
     313             : 
     314             : nsresult
     315           0 : PeerConnectionMedia::InitProxy()
     316             : {
     317             :   // Allow mochitests to disable this, since mochitest configures a fake proxy
     318             :   // that serves up content.
     319             :   bool disable = Preferences::GetBool("media.peerconnection.disable_http_proxy",
     320           0 :                                       false);
     321           0 :   if (disable) {
     322           0 :     mProxyResolveCompleted = true;
     323           0 :     return NS_OK;
     324             :   }
     325             : 
     326             :   nsresult rv;
     327             :   nsCOMPtr<nsIProtocolProxyService> pps =
     328           0 :     do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
     329           0 :   if (NS_FAILED(rv)) {
     330           0 :     CSFLogError(logTag, "%s: Failed to get proxy service: %d", __FUNCTION__, (int)rv);
     331           0 :     return NS_ERROR_FAILURE;
     332             :   }
     333             : 
     334             :   // We use the following URL to find the "default" proxy address for all HTTPS
     335             :   // connections.  We will only attempt one HTTP(S) CONNECT per peer connection.
     336             :   // "example.com" is guaranteed to be unallocated and should return the best default.
     337           0 :   nsCOMPtr<nsIURI> fakeHttpsLocation;
     338           0 :   rv = NS_NewURI(getter_AddRefs(fakeHttpsLocation), "https://example.com");
     339           0 :   if (NS_FAILED(rv)) {
     340           0 :     CSFLogError(logTag, "%s: Failed to set URI: %d", __FUNCTION__, (int)rv);
     341           0 :     return NS_ERROR_FAILURE;
     342             :   }
     343             : 
     344             :   nsCOMPtr<nsIScriptSecurityManager> secMan(
     345           0 :       do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
     346           0 :   if (NS_FAILED(rv)) {
     347           0 :     CSFLogError(logTag, "%s: Failed to get IOService: %d",
     348           0 :         __FUNCTION__, (int)rv);
     349           0 :     CSFLogError(logTag, "%s: Failed to get securityManager: %d", __FUNCTION__, (int)rv);
     350           0 :     return NS_ERROR_FAILURE;
     351             :   }
     352             : 
     353           0 :   nsCOMPtr<nsIPrincipal> systemPrincipal;
     354           0 :   rv = secMan->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
     355           0 :   if (NS_FAILED(rv)) {
     356           0 :     CSFLogError(logTag, "%s: Failed to get systemPrincipal: %d", __FUNCTION__, (int)rv);
     357           0 :     return NS_ERROR_FAILURE;
     358             :   }
     359             : 
     360           0 :   nsCOMPtr<nsIChannel> channel;
     361           0 :   rv = NS_NewChannel(getter_AddRefs(channel),
     362             :                      fakeHttpsLocation,
     363             :                      systemPrincipal,
     364             :                      nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
     365             :                      nsIContentPolicy::TYPE_OTHER);
     366             : 
     367           0 :   if (NS_FAILED(rv)) {
     368           0 :     CSFLogError(logTag, "%s: Failed to get channel from URI: %d",
     369           0 :                 __FUNCTION__, (int)rv);
     370           0 :     return NS_ERROR_FAILURE;
     371             :   }
     372             : 
     373           0 :   nsCOMPtr<nsIEventTarget> target = mParent->GetWindow()
     374           0 :       ? mParent->GetWindow()->EventTargetFor(TaskCategory::Network)
     375           0 :       : nullptr;
     376           0 :   RefPtr<ProtocolProxyQueryHandler> handler = new ProtocolProxyQueryHandler(this);
     377           0 :   rv = pps->AsyncResolve(channel,
     378             :                          nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY |
     379             :                          nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL,
     380           0 :                          handler, target, getter_AddRefs(mProxyRequest));
     381           0 :   if (NS_FAILED(rv)) {
     382           0 :     CSFLogError(logTag, "%s: Failed to resolve protocol proxy: %d", __FUNCTION__, (int)rv);
     383           0 :     return NS_ERROR_FAILURE;
     384             :   }
     385             : 
     386           0 :   return NS_OK;
     387             : }
     388             : 
     389           0 : nsresult PeerConnectionMedia::Init(const std::vector<NrIceStunServer>& stun_servers,
     390             :                                    const std::vector<NrIceTurnServer>& turn_servers,
     391             :                                    NrIceCtx::Policy policy)
     392             : {
     393           0 :   nsresult rv = InitProxy();
     394           0 :   NS_ENSURE_SUCCESS(rv, rv);
     395             : 
     396           0 :   bool ice_tcp = Preferences::GetBool("media.peerconnection.ice.tcp", false);
     397             : 
     398             :   // setup the stun local addresses IPC async call
     399           0 :   InitLocalAddrs();
     400             : 
     401             :   // TODO(ekr@rtfm.com): need some way to set not offerer later
     402             :   // Looks like a bug in the NrIceCtx API.
     403           0 :   mIceCtxHdlr = NrIceCtxHandler::Create("PC:" + mParentName,
     404           0 :                                         mParent->GetAllowIceLoopback(),
     405             :                                         ice_tcp,
     406           0 :                                         mParent->GetAllowIceLinkLocal(),
     407           0 :                                         policy);
     408           0 :   if(!mIceCtxHdlr) {
     409           0 :     CSFLogError(logTag, "%s: Failed to create Ice Context", __FUNCTION__);
     410           0 :     return NS_ERROR_FAILURE;
     411             :   }
     412             : 
     413           0 :   if (NS_FAILED(rv = mIceCtxHdlr->ctx()->SetStunServers(stun_servers))) {
     414           0 :     CSFLogError(logTag, "%s: Failed to set stun servers", __FUNCTION__);
     415           0 :     return rv;
     416             :   }
     417             :   // Give us a way to globally turn off TURN support
     418           0 :   bool disabled = Preferences::GetBool("media.peerconnection.turn.disable", false);
     419           0 :   if (!disabled) {
     420           0 :     if (NS_FAILED(rv = mIceCtxHdlr->ctx()->SetTurnServers(turn_servers))) {
     421           0 :       CSFLogError(logTag, "%s: Failed to set turn servers", __FUNCTION__);
     422           0 :       return rv;
     423             :     }
     424           0 :   } else if (turn_servers.size() != 0) {
     425           0 :     CSFLogError(logTag, "%s: Setting turn servers disabled", __FUNCTION__);
     426             :   }
     427           0 :   if (NS_FAILED(rv = mDNSResolver->Init())) {
     428           0 :     CSFLogError(logTag, "%s: Failed to initialize dns resolver", __FUNCTION__);
     429           0 :     return rv;
     430             :   }
     431           0 :   if (NS_FAILED(rv =
     432             :       mIceCtxHdlr->ctx()->SetResolver(mDNSResolver->AllocateResolver()))) {
     433           0 :     CSFLogError(logTag, "%s: Failed to get dns resolver", __FUNCTION__);
     434           0 :     return rv;
     435             :   }
     436           0 :   ConnectSignals(mIceCtxHdlr->ctx().get());
     437             : 
     438             :   // This webrtc:Call instance will be shared by audio and video media conduits.
     439           0 :   mCall = CreateCall();
     440             : 
     441           0 :   return NS_OK;
     442             : }
     443             : 
     444             : void
     445           0 : PeerConnectionMedia::EnsureTransports(const JsepSession& aSession)
     446             : {
     447           0 :   auto transports = aSession.GetTransports();
     448           0 :   for (size_t i = 0; i < transports.size(); ++i) {
     449           0 :     RefPtr<JsepTransport> transport = transports[i];
     450           0 :     RUN_ON_THREAD(
     451           0 :         GetSTSThread(),
     452           0 :         WrapRunnable(RefPtr<PeerConnectionMedia>(this),
     453             :                      &PeerConnectionMedia::EnsureTransport_s,
     454             :                      i,
     455           0 :                      transport->mComponents),
     456           0 :         NS_DISPATCH_NORMAL);
     457             :   }
     458             : 
     459           0 :   GatherIfReady();
     460           0 : }
     461             : 
     462             : void
     463           0 : PeerConnectionMedia::EnsureTransport_s(size_t aLevel, size_t aComponentCount)
     464             : {
     465           0 :   RefPtr<NrIceMediaStream> stream(mIceCtxHdlr->ctx()->GetStream(aLevel));
     466           0 :   if (!stream) {
     467           0 :     CSFLogDebug(logTag, "%s: Creating ICE media stream=%u components=%u",
     468             :                 mParentHandle.c_str(),
     469             :                 static_cast<unsigned>(aLevel),
     470           0 :                 static_cast<unsigned>(aComponentCount));
     471             : 
     472           0 :     std::ostringstream os;
     473           0 :     os << mParentName << " aLevel=" << aLevel;
     474             :     RefPtr<NrIceMediaStream> stream =
     475           0 :       mIceCtxHdlr->CreateStream(os.str(),
     476           0 :                                 aComponentCount);
     477             : 
     478           0 :     if (!stream) {
     479           0 :       CSFLogError(logTag, "Failed to create ICE stream.");
     480           0 :       return;
     481             :     }
     482             : 
     483           0 :     stream->SetLevel(aLevel);
     484           0 :     stream->SignalReady.connect(this, &PeerConnectionMedia::IceStreamReady_s);
     485           0 :     stream->SignalCandidate.connect(this,
     486           0 :                                     &PeerConnectionMedia::OnCandidateFound_s);
     487           0 :     mIceCtxHdlr->ctx()->SetStream(aLevel, stream);
     488             :   }
     489             : }
     490             : 
     491             : void
     492           0 : PeerConnectionMedia::ActivateOrRemoveTransports(const JsepSession& aSession,
     493             :                                                 const bool forceIceTcp)
     494             : {
     495           0 :   auto transports = aSession.GetTransports();
     496           0 :   for (size_t i = 0; i < transports.size(); ++i) {
     497           0 :     RefPtr<JsepTransport> transport = transports[i];
     498             : 
     499           0 :     std::string ufrag;
     500           0 :     std::string pwd;
     501           0 :     std::vector<std::string> candidates;
     502             : 
     503           0 :     if (transport->mComponents) {
     504           0 :       MOZ_ASSERT(transport->mIce);
     505           0 :       CSFLogDebug(logTag, "Transport %u is active", static_cast<unsigned>(i));
     506           0 :       ufrag = transport->mIce->GetUfrag();
     507           0 :       pwd = transport->mIce->GetPassword();
     508           0 :       candidates = transport->mIce->GetCandidates();
     509             :     } else {
     510           0 :       CSFLogDebug(logTag, "Transport %u is disabled", static_cast<unsigned>(i));
     511             :       // Make sure the MediaPipelineFactory doesn't try to use these.
     512           0 :       RemoveTransportFlow(i, false);
     513           0 :       RemoveTransportFlow(i, true);
     514             :     }
     515             : 
     516           0 :     if (forceIceTcp) {
     517           0 :       candidates.erase(std::remove_if(candidates.begin(),
     518             :                                       candidates.end(),
     519           0 :                                       [](const std::string & s) {
     520           0 :                                         return s.find(" UDP ") != std::string::npos ||
     521           0 :                                                s.find(" udp ") != std::string::npos; }),
     522           0 :                        candidates.end());
     523             :     }
     524             : 
     525           0 :     RUN_ON_THREAD(
     526           0 :         GetSTSThread(),
     527           0 :         WrapRunnable(RefPtr<PeerConnectionMedia>(this),
     528             :                      &PeerConnectionMedia::ActivateOrRemoveTransport_s,
     529             :                      i,
     530           0 :                      transport->mComponents,
     531             :                      ufrag,
     532             :                      pwd,
     533             :                      candidates),
     534           0 :         NS_DISPATCH_NORMAL);
     535             :   }
     536             : 
     537             :   // We can have more streams than m-lines due to rollback.
     538           0 :   RUN_ON_THREAD(
     539           0 :       GetSTSThread(),
     540           0 :       WrapRunnable(RefPtr<PeerConnectionMedia>(this),
     541             :                    &PeerConnectionMedia::RemoveTransportsAtOrAfter_s,
     542             :                    transports.size()),
     543           0 :       NS_DISPATCH_NORMAL);
     544           0 : }
     545             : 
     546             : void
     547           0 : PeerConnectionMedia::ActivateOrRemoveTransport_s(
     548             :     size_t aMLine,
     549             :     size_t aComponentCount,
     550             :     const std::string& aUfrag,
     551             :     const std::string& aPassword,
     552             :     const std::vector<std::string>& aCandidateList) {
     553             : 
     554           0 :   if (!aComponentCount) {
     555           0 :     CSFLogDebug(logTag, "%s: Removing ICE media stream=%u",
     556             :                 mParentHandle.c_str(),
     557           0 :                 static_cast<unsigned>(aMLine));
     558           0 :     mIceCtxHdlr->ctx()->SetStream(aMLine, nullptr);
     559           0 :     return;
     560             :   }
     561             : 
     562           0 :   RefPtr<NrIceMediaStream> stream(mIceCtxHdlr->ctx()->GetStream(aMLine));
     563           0 :   if (!stream) {
     564           0 :     MOZ_ASSERT(false);
     565             :     return;
     566             :   }
     567             : 
     568           0 :   if (!stream->HasParsedAttributes()) {
     569           0 :     CSFLogDebug(logTag, "%s: Activating ICE media stream=%u components=%u",
     570             :                 mParentHandle.c_str(),
     571             :                 static_cast<unsigned>(aMLine),
     572           0 :                 static_cast<unsigned>(aComponentCount));
     573             : 
     574           0 :     std::vector<std::string> attrs;
     575           0 :     for (const auto& candidate : aCandidateList) {
     576           0 :       attrs.push_back("candidate:" + candidate);
     577             :     }
     578           0 :     attrs.push_back("ice-ufrag:" + aUfrag);
     579           0 :     attrs.push_back("ice-pwd:" + aPassword);
     580             : 
     581           0 :     nsresult rv = stream->ParseAttributes(attrs);
     582           0 :     if (NS_FAILED(rv)) {
     583             :       CSFLogError(logTag, "Couldn't parse ICE attributes, rv=%u",
     584           0 :                           static_cast<unsigned>(rv));
     585             :     }
     586             : 
     587           0 :     for (size_t c = aComponentCount; c < stream->components(); ++c) {
     588             :       // components are 1-indexed
     589           0 :       stream->DisableComponent(c + 1);
     590             :     }
     591             :   }
     592             : }
     593             : 
     594             : void
     595           0 : PeerConnectionMedia::RemoveTransportsAtOrAfter_s(size_t aMLine)
     596             : {
     597           0 :   for (size_t i = aMLine; i < mIceCtxHdlr->ctx()->GetStreamCount(); ++i) {
     598           0 :     mIceCtxHdlr->ctx()->SetStream(i, nullptr);
     599             :   }
     600           0 : }
     601             : 
     602           0 : nsresult PeerConnectionMedia::UpdateMediaPipelines(
     603             :     const JsepSession& session) {
     604           0 :   auto trackPairs = session.GetNegotiatedTrackPairs();
     605           0 :   MediaPipelineFactory factory(this);
     606             :   nsresult rv;
     607             : 
     608           0 :   for (auto pair : trackPairs) {
     609           0 :     if (pair.mReceiving) {
     610             : 
     611           0 :       rv = factory.CreateOrUpdateMediaPipeline(pair, *pair.mReceiving);
     612           0 :       if (NS_FAILED(rv)) {
     613           0 :         return rv;
     614             :       }
     615             :     }
     616             : 
     617           0 :     if (pair.mSending) {
     618           0 :       rv = factory.CreateOrUpdateMediaPipeline(pair, *pair.mSending);
     619           0 :       if (NS_FAILED(rv)) {
     620           0 :         return rv;
     621             :       }
     622             :     }
     623             :   }
     624             : 
     625           0 :   for (auto& stream : mRemoteSourceStreams) {
     626           0 :     stream->StartReceiving();
     627             :   }
     628             : 
     629           0 :   return NS_OK;
     630             : }
     631             : 
     632             : void
     633           0 : PeerConnectionMedia::StartIceChecks(const JsepSession& aSession)
     634             : {
     635             :   nsCOMPtr<nsIRunnable> runnable(
     636           0 :       WrapRunnable(
     637           0 :         RefPtr<PeerConnectionMedia>(this),
     638             :         &PeerConnectionMedia::StartIceChecks_s,
     639           0 :         aSession.IsIceControlling(),
     640           0 :         aSession.IsOfferer(),
     641           0 :         aSession.RemoteIsIceLite(),
     642             :         // Copy, just in case API changes to return a ref
     643           0 :         std::vector<std::string>(aSession.GetIceOptions())));
     644             : 
     645           0 :   PerformOrEnqueueIceCtxOperation(runnable);
     646           0 : }
     647             : 
     648             : void
     649           0 : PeerConnectionMedia::StartIceChecks_s(
     650             :     bool aIsControlling,
     651             :     bool aIsOfferer,
     652             :     bool aIsIceLite,
     653             :     const std::vector<std::string>& aIceOptionsList) {
     654             : 
     655           0 :   CSFLogDebug(logTag, "Starting ICE Checking");
     656             : 
     657           0 :   std::vector<std::string> attributes;
     658           0 :   if (aIsIceLite) {
     659           0 :     attributes.push_back("ice-lite");
     660             :   }
     661             : 
     662           0 :   if (!aIceOptionsList.empty()) {
     663           0 :     attributes.push_back("ice-options:");
     664           0 :     for (const auto& option : aIceOptionsList) {
     665           0 :       attributes.back() += option + ' ';
     666             :     }
     667             :   }
     668             : 
     669           0 :   nsresult rv = mIceCtxHdlr->ctx()->ParseGlobalAttributes(attributes);
     670           0 :   if (NS_FAILED(rv)) {
     671           0 :     CSFLogError(logTag, "%s: couldn't parse global parameters", __FUNCTION__ );
     672             :   }
     673             : 
     674           0 :   mIceCtxHdlr->ctx()->SetControlling(aIsControlling ?
     675             :                                      NrIceCtx::ICE_CONTROLLING :
     676           0 :                                      NrIceCtx::ICE_CONTROLLED);
     677             : 
     678           0 :   mIceCtxHdlr->ctx()->StartChecks(aIsOfferer);
     679           0 : }
     680             : 
     681             : bool
     682           0 : PeerConnectionMedia::IsIceRestarting() const
     683             : {
     684           0 :   ASSERT_ON_THREAD(mMainThread);
     685             : 
     686           0 :   return (mIceRestartState != ICE_RESTART_NONE);
     687             : }
     688             : 
     689             : PeerConnectionMedia::IceRestartState
     690           0 : PeerConnectionMedia::GetIceRestartState() const
     691             : {
     692           0 :   ASSERT_ON_THREAD(mMainThread);
     693             : 
     694           0 :   return mIceRestartState;
     695             : }
     696             : 
     697             : void
     698           0 : PeerConnectionMedia::BeginIceRestart(const std::string& ufrag,
     699             :                                      const std::string& pwd)
     700             : {
     701           0 :   ASSERT_ON_THREAD(mMainThread);
     702           0 :   if (IsIceRestarting()) {
     703           0 :     return;
     704             :   }
     705             : 
     706           0 :   RefPtr<NrIceCtx> new_ctx = mIceCtxHdlr->CreateCtx(ufrag, pwd);
     707             : 
     708           0 :   RUN_ON_THREAD(GetSTSThread(),
     709           0 :                 WrapRunnable(
     710           0 :                     RefPtr<PeerConnectionMedia>(this),
     711             :                     &PeerConnectionMedia::BeginIceRestart_s,
     712             :                     new_ctx),
     713           0 :                 NS_DISPATCH_NORMAL);
     714             : 
     715           0 :   mIceRestartState = ICE_RESTART_PROVISIONAL;
     716             : }
     717             : 
     718             : void
     719           0 : PeerConnectionMedia::BeginIceRestart_s(RefPtr<NrIceCtx> new_ctx)
     720             : {
     721           0 :   ASSERT_ON_THREAD(mSTSThread);
     722             : 
     723             :   // hold the original context so we can disconnect signals if needed
     724           0 :   RefPtr<NrIceCtx> originalCtx = mIceCtxHdlr->ctx();
     725             : 
     726           0 :   if (mIceCtxHdlr->BeginIceRestart(new_ctx)) {
     727           0 :     ConnectSignals(mIceCtxHdlr->ctx().get(), originalCtx.get());
     728             :   }
     729           0 : }
     730             : 
     731             : void
     732           0 : PeerConnectionMedia::CommitIceRestart()
     733             : {
     734           0 :   ASSERT_ON_THREAD(mMainThread);
     735           0 :   if (mIceRestartState != ICE_RESTART_PROVISIONAL) {
     736           0 :     return;
     737             :   }
     738             : 
     739           0 :   mIceRestartState = ICE_RESTART_COMMITTED;
     740             : }
     741             : 
     742             : void
     743           0 : PeerConnectionMedia::FinalizeIceRestart()
     744             : {
     745           0 :   ASSERT_ON_THREAD(mMainThread);
     746           0 :   if (!IsIceRestarting()) {
     747           0 :     return;
     748             :   }
     749             : 
     750           0 :   RUN_ON_THREAD(GetSTSThread(),
     751           0 :                 WrapRunnable(
     752           0 :                     RefPtr<PeerConnectionMedia>(this),
     753             :                     &PeerConnectionMedia::FinalizeIceRestart_s),
     754           0 :                 NS_DISPATCH_NORMAL);
     755             : 
     756           0 :   mIceRestartState = ICE_RESTART_NONE;
     757             : }
     758             : 
     759             : void
     760           0 : PeerConnectionMedia::FinalizeIceRestart_s()
     761             : {
     762           0 :   ASSERT_ON_THREAD(mSTSThread);
     763             : 
     764             :   // reset old streams since we don't need them anymore
     765           0 :   for (auto& transportFlow : mTransportFlows) {
     766           0 :     RefPtr<TransportFlow> aFlow = transportFlow.second;
     767           0 :     if (!aFlow) continue;
     768             :     TransportLayerIce* ice =
     769           0 :       static_cast<TransportLayerIce*>(aFlow->GetLayer(TransportLayerIce::ID()));
     770           0 :     ice->ResetOldStream();
     771             :   }
     772             : 
     773           0 :   mIceCtxHdlr->FinalizeIceRestart();
     774           0 : }
     775             : 
     776             : void
     777           0 : PeerConnectionMedia::RollbackIceRestart()
     778             : {
     779           0 :   ASSERT_ON_THREAD(mMainThread);
     780           0 :   if (mIceRestartState != ICE_RESTART_PROVISIONAL) {
     781           0 :     return;
     782             :   }
     783             : 
     784           0 :   RUN_ON_THREAD(GetSTSThread(),
     785           0 :                 WrapRunnable(
     786           0 :                     RefPtr<PeerConnectionMedia>(this),
     787             :                     &PeerConnectionMedia::RollbackIceRestart_s),
     788           0 :                 NS_DISPATCH_NORMAL);
     789             : 
     790           0 :   mIceRestartState = ICE_RESTART_NONE;
     791             : }
     792             : 
     793             : void
     794           0 : PeerConnectionMedia::RollbackIceRestart_s()
     795             : {
     796           0 :   ASSERT_ON_THREAD(mSTSThread);
     797             : 
     798             :   // hold the restart context so we can disconnect signals
     799           0 :   RefPtr<NrIceCtx> restartCtx = mIceCtxHdlr->ctx();
     800             : 
     801             :   // restore old streams since we're rolling back
     802           0 :   for (auto& transportFlow : mTransportFlows) {
     803           0 :     RefPtr<TransportFlow> aFlow = transportFlow.second;
     804           0 :     if (!aFlow) continue;
     805             :     TransportLayerIce* ice =
     806           0 :       static_cast<TransportLayerIce*>(aFlow->GetLayer(TransportLayerIce::ID()));
     807           0 :     ice->RestoreOldStream();
     808             :   }
     809             : 
     810           0 :   mIceCtxHdlr->RollbackIceRestart();
     811           0 :   ConnectSignals(mIceCtxHdlr->ctx().get(), restartCtx.get());
     812             : 
     813             :   // Fixup the telemetry by transferring abandoned ctx stats to current ctx.
     814           0 :   NrIceStats stats = restartCtx->Destroy();
     815           0 :   restartCtx = nullptr;
     816           0 :   mIceCtxHdlr->ctx()->AccumulateStats(stats);
     817           0 : }
     818             : 
     819             : bool
     820           0 : PeerConnectionMedia::GetPrefDefaultAddressOnly() const
     821             : {
     822           0 :   ASSERT_ON_THREAD(mMainThread); // will crash on STS thread
     823             : 
     824           0 :   uint64_t winId = mParent->GetWindow()->WindowID();
     825             : 
     826             :   bool default_address_only = Preferences::GetBool(
     827           0 :     "media.peerconnection.ice.default_address_only", false);
     828           0 :   default_address_only |=
     829           0 :     !MediaManager::Get()->IsActivelyCapturingOrHasAPermission(winId);
     830           0 :   return default_address_only;
     831             : }
     832             : 
     833             : bool
     834           0 : PeerConnectionMedia::GetPrefProxyOnly() const
     835             : {
     836           0 :   ASSERT_ON_THREAD(mMainThread); // will crash on STS thread
     837             : 
     838           0 :   return Preferences::GetBool("media.peerconnection.ice.proxy_only", false);
     839             : }
     840             : 
     841             : void
     842           0 : PeerConnectionMedia::ConnectSignals(NrIceCtx *aCtx, NrIceCtx *aOldCtx)
     843             : {
     844           0 :   aCtx->SignalGatheringStateChange.connect(
     845             :       this,
     846           0 :       &PeerConnectionMedia::IceGatheringStateChange_s);
     847           0 :   aCtx->SignalConnectionStateChange.connect(
     848             :       this,
     849           0 :       &PeerConnectionMedia::IceConnectionStateChange_s);
     850             : 
     851           0 :   if (aOldCtx) {
     852           0 :     MOZ_ASSERT(aCtx != aOldCtx);
     853           0 :     aOldCtx->SignalGatheringStateChange.disconnect(this);
     854           0 :     aOldCtx->SignalConnectionStateChange.disconnect(this);
     855             : 
     856             :     // if the old and new connection state and/or gathering state is
     857             :     // different fire the state update.  Note: we don't fire the update
     858             :     // if the state is *INIT since updates for the INIT state aren't
     859             :     // sent during the normal flow. (mjf)
     860           0 :     if (aOldCtx->connection_state() != aCtx->connection_state() &&
     861           0 :         aCtx->connection_state() != NrIceCtx::ICE_CTX_INIT) {
     862           0 :       aCtx->SignalConnectionStateChange(aCtx, aCtx->connection_state());
     863             :     }
     864             : 
     865           0 :     if (aOldCtx->gathering_state() != aCtx->gathering_state() &&
     866           0 :         aCtx->gathering_state() != NrIceCtx::ICE_CTX_GATHER_INIT) {
     867           0 :       aCtx->SignalGatheringStateChange(aCtx, aCtx->gathering_state());
     868             :     }
     869             :   }
     870           0 : }
     871             : 
     872             : void
     873           0 : PeerConnectionMedia::AddIceCandidate(const std::string& candidate,
     874             :                                      const std::string& mid,
     875             :                                      uint32_t aMLine) {
     876           0 :   RUN_ON_THREAD(GetSTSThread(),
     877           0 :                 WrapRunnable(
     878           0 :                     RefPtr<PeerConnectionMedia>(this),
     879             :                     &PeerConnectionMedia::AddIceCandidate_s,
     880           0 :                     std::string(candidate), // Make copies.
     881           0 :                     std::string(mid),
     882             :                     aMLine),
     883           0 :                 NS_DISPATCH_NORMAL);
     884           0 : }
     885             : 
     886             : void
     887           0 : PeerConnectionMedia::AddIceCandidate_s(const std::string& aCandidate,
     888             :                                        const std::string& aMid,
     889             :                                        uint32_t aMLine) {
     890           0 :   RefPtr<NrIceMediaStream> stream(mIceCtxHdlr->ctx()->GetStream(aMLine));
     891           0 :   if (!stream) {
     892           0 :     CSFLogError(logTag, "No ICE stream for candidate at level %u: %s",
     893           0 :                         static_cast<unsigned>(aMLine), aCandidate.c_str());
     894           0 :     return;
     895             :   }
     896             : 
     897           0 :   nsresult rv = stream->ParseTrickleCandidate(aCandidate);
     898           0 :   if (NS_FAILED(rv)) {
     899             :     CSFLogError(logTag, "Couldn't process ICE candidate at level %u",
     900           0 :                 static_cast<unsigned>(aMLine));
     901           0 :     return;
     902             :   }
     903             : }
     904             : 
     905             : void
     906           0 : PeerConnectionMedia::UpdateNetworkState(bool online) {
     907           0 :   RUN_ON_THREAD(GetSTSThread(),
     908           0 :                 WrapRunnable(
     909           0 :                     RefPtr<PeerConnectionMedia>(this),
     910             :                     &PeerConnectionMedia::UpdateNetworkState_s,
     911             :                     online),
     912           0 :                 NS_DISPATCH_NORMAL);
     913           0 : }
     914             : 
     915             : void
     916           0 : PeerConnectionMedia::UpdateNetworkState_s(bool online) {
     917           0 :   mIceCtxHdlr->ctx()->UpdateNetworkState(online);
     918           0 : }
     919             : 
     920             : void
     921           0 : PeerConnectionMedia::FlushIceCtxOperationQueueIfReady()
     922             : {
     923           0 :   ASSERT_ON_THREAD(mMainThread);
     924             : 
     925           0 :   if (IsIceCtxReady()) {
     926           0 :     for (auto& mQueuedIceCtxOperation : mQueuedIceCtxOperations) {
     927           0 :       GetSTSThread()->Dispatch(mQueuedIceCtxOperation, NS_DISPATCH_NORMAL);
     928             :     }
     929           0 :     mQueuedIceCtxOperations.clear();
     930             :   }
     931           0 : }
     932             : 
     933             : void
     934           0 : PeerConnectionMedia::PerformOrEnqueueIceCtxOperation(nsIRunnable* runnable)
     935             : {
     936           0 :   ASSERT_ON_THREAD(mMainThread);
     937             : 
     938           0 :   if (IsIceCtxReady()) {
     939           0 :     GetSTSThread()->Dispatch(runnable, NS_DISPATCH_NORMAL);
     940             :   } else {
     941           0 :     mQueuedIceCtxOperations.push_back(runnable);
     942             :   }
     943           0 : }
     944             : 
     945             : void
     946           0 : PeerConnectionMedia::GatherIfReady() {
     947           0 :   ASSERT_ON_THREAD(mMainThread);
     948             : 
     949           0 :   nsCOMPtr<nsIRunnable> runnable(WrapRunnable(
     950           0 :         RefPtr<PeerConnectionMedia>(this),
     951             :         &PeerConnectionMedia::EnsureIceGathering_s,
     952           0 :         GetPrefDefaultAddressOnly(),
     953           0 :         GetPrefProxyOnly()));
     954             : 
     955           0 :   PerformOrEnqueueIceCtxOperation(runnable);
     956           0 : }
     957             : 
     958             : void
     959           0 : PeerConnectionMedia::EnsureIceGathering_s(bool aDefaultRouteOnly,
     960             :                                           bool aProxyOnly) {
     961           0 :   if (mProxyServer) {
     962           0 :     mIceCtxHdlr->ctx()->SetProxyServer(*mProxyServer);
     963           0 :   } else if (aProxyOnly) {
     964           0 :     IceGatheringStateChange_s(mIceCtxHdlr->ctx().get(),
     965           0 :                               NrIceCtx::ICE_CTX_GATHER_COMPLETE);
     966           0 :     return;
     967             :   }
     968             : 
     969           0 :   if (mStunAddrs.Length()) {
     970           0 :     mIceCtxHdlr->ctx()->SetStunAddrs(mStunAddrs);
     971             :   }
     972             : 
     973             :   // Start gathering, but only if there are streams
     974           0 :   for (size_t i = 0; i < mIceCtxHdlr->ctx()->GetStreamCount(); ++i) {
     975           0 :     if (mIceCtxHdlr->ctx()->GetStream(i)) {
     976           0 :       mIceCtxHdlr->ctx()->StartGathering(aDefaultRouteOnly, aProxyOnly);
     977           0 :       return;
     978             :     }
     979             :   }
     980             : 
     981             :   // If there are no streams, we're probably in a situation where we've rolled
     982             :   // back while still waiting for our proxy configuration to come back. Make
     983             :   // sure content knows that the rollback has stuck wrt gathering.
     984           0 :   IceGatheringStateChange_s(mIceCtxHdlr->ctx().get(),
     985           0 :                             NrIceCtx::ICE_CTX_GATHER_COMPLETE);
     986             : }
     987             : 
     988             : nsresult
     989           0 : PeerConnectionMedia::AddTrack(DOMMediaStream& aMediaStream,
     990             :                               const std::string& streamId,
     991             :                               MediaStreamTrack& aTrack,
     992             :                               const std::string& trackId)
     993             : {
     994           0 :   ASSERT_ON_THREAD(mMainThread);
     995             : 
     996           0 :   CSFLogDebug(logTag, "%s: MediaStream: %p", __FUNCTION__, &aMediaStream);
     997             : 
     998             :   RefPtr<LocalSourceStreamInfo> localSourceStream =
     999           0 :     GetLocalStreamById(streamId);
    1000             : 
    1001           0 :   if (!localSourceStream) {
    1002           0 :     localSourceStream = new LocalSourceStreamInfo(&aMediaStream, this, streamId);
    1003           0 :     mLocalSourceStreams.AppendElement(localSourceStream);
    1004             :   }
    1005             : 
    1006           0 :   localSourceStream->AddTrack(trackId, &aTrack);
    1007           0 :   return NS_OK;
    1008             : }
    1009             : 
    1010             : nsresult
    1011           0 : PeerConnectionMedia::RemoveLocalTrack(const std::string& streamId,
    1012             :                                       const std::string& trackId)
    1013             : {
    1014           0 :   ASSERT_ON_THREAD(mMainThread);
    1015             : 
    1016           0 :   CSFLogDebug(logTag, "%s: stream: %s track: %s", __FUNCTION__,
    1017           0 :                       streamId.c_str(), trackId.c_str());
    1018             : 
    1019             :   RefPtr<LocalSourceStreamInfo> localSourceStream =
    1020           0 :     GetLocalStreamById(streamId);
    1021           0 :   if (!localSourceStream) {
    1022           0 :     return NS_ERROR_ILLEGAL_VALUE;
    1023             :   }
    1024             : 
    1025           0 :   localSourceStream->RemoveTrack(trackId);
    1026           0 :   if (!localSourceStream->GetTrackCount()) {
    1027           0 :     mLocalSourceStreams.RemoveElement(localSourceStream);
    1028             :   }
    1029           0 :   return NS_OK;
    1030             : }
    1031             : 
    1032             : nsresult
    1033           0 : PeerConnectionMedia::RemoveRemoteTrack(const std::string& streamId,
    1034             :                                        const std::string& trackId)
    1035             : {
    1036           0 :   ASSERT_ON_THREAD(mMainThread);
    1037             : 
    1038           0 :   CSFLogDebug(logTag, "%s: stream: %s track: %s", __FUNCTION__,
    1039           0 :                       streamId.c_str(), trackId.c_str());
    1040             : 
    1041             :   RefPtr<RemoteSourceStreamInfo> remoteSourceStream =
    1042           0 :     GetRemoteStreamById(streamId);
    1043           0 :   if (!remoteSourceStream) {
    1044           0 :     return NS_ERROR_ILLEGAL_VALUE;
    1045             :   }
    1046             : 
    1047           0 :   remoteSourceStream->RemoveTrack(trackId);
    1048           0 :   if (!remoteSourceStream->GetTrackCount()) {
    1049           0 :     mRemoteSourceStreams.RemoveElement(remoteSourceStream);
    1050             :   }
    1051           0 :   return NS_OK;
    1052             : }
    1053             : 
    1054             : void
    1055           0 : PeerConnectionMedia::SelfDestruct()
    1056             : {
    1057           0 :   ASSERT_ON_THREAD(mMainThread);
    1058             : 
    1059           0 :   CSFLogDebug(logTag, "%s: ", __FUNCTION__);
    1060             : 
    1061             :   // Shut down the media
    1062           0 :   for (uint32_t i=0; i < mLocalSourceStreams.Length(); ++i) {
    1063           0 :     mLocalSourceStreams[i]->DetachMedia_m();
    1064             :   }
    1065             : 
    1066           0 :   for (uint32_t i=0; i < mRemoteSourceStreams.Length(); ++i) {
    1067           0 :     mRemoteSourceStreams[i]->DetachMedia_m();
    1068             :   }
    1069             : 
    1070           0 :   if (mStunAddrsRequest) {
    1071           0 :     mStunAddrsRequest->Cancel();
    1072           0 :     mStunAddrsRequest = nullptr;
    1073             :   }
    1074             : 
    1075           0 :   if (mProxyRequest) {
    1076           0 :     mProxyRequest->Cancel(NS_ERROR_ABORT);
    1077           0 :     mProxyRequest = nullptr;
    1078             :   }
    1079             : 
    1080             :   // Shutdown the transport (async)
    1081           0 :   RUN_ON_THREAD(mSTSThread, WrapRunnable(
    1082             :       this, &PeerConnectionMedia::ShutdownMediaTransport_s),
    1083           0 :                 NS_DISPATCH_NORMAL);
    1084             : 
    1085           0 :   CSFLogDebug(logTag, "%s: Media shut down", __FUNCTION__);
    1086           0 : }
    1087             : 
    1088             : void
    1089           0 : PeerConnectionMedia::SelfDestruct_m()
    1090             : {
    1091           0 :   CSFLogDebug(logTag, "%s: ", __FUNCTION__);
    1092             : 
    1093           0 :   ASSERT_ON_THREAD(mMainThread);
    1094             : 
    1095           0 :   mLocalSourceStreams.Clear();
    1096           0 :   mRemoteSourceStreams.Clear();
    1097             : 
    1098           0 :   mMainThread = nullptr;
    1099             : 
    1100             :   // Final self-destruct.
    1101           0 :   this->Release();
    1102           0 : }
    1103             : 
    1104             : void
    1105           0 : PeerConnectionMedia::ShutdownMediaTransport_s()
    1106             : {
    1107           0 :   ASSERT_ON_THREAD(mSTSThread);
    1108             : 
    1109           0 :   CSFLogDebug(logTag, "%s: ", __FUNCTION__);
    1110             : 
    1111             :   // Here we access m{Local|Remote}SourceStreams off the main thread.
    1112             :   // That's OK because by here PeerConnectionImpl has forgotten about us,
    1113             :   // so there is no chance of getting a call in here from outside.
    1114             :   // The dispatches from SelfDestruct() and to SelfDestruct_m() provide
    1115             :   // memory barriers that protect us from badness.
    1116           0 :   for (uint32_t i=0; i < mLocalSourceStreams.Length(); ++i) {
    1117           0 :     mLocalSourceStreams[i]->DetachTransport_s();
    1118             :   }
    1119             : 
    1120           0 :   for (uint32_t i=0; i < mRemoteSourceStreams.Length(); ++i) {
    1121           0 :     mRemoteSourceStreams[i]->DetachTransport_s();
    1122             :   }
    1123             : 
    1124           0 :   disconnect_all();
    1125           0 :   mTransportFlows.clear();
    1126             : 
    1127             : #if !defined(MOZILLA_EXTERNAL_LINKAGE)
    1128           0 :   NrIceStats stats = mIceCtxHdlr->Destroy();
    1129             : 
    1130           0 :   CSFLogDebug(logTag, "Ice Telemetry: stun (retransmits: %d)"
    1131             :                       "   turn (401s: %d   403s: %d   438s: %d)",
    1132             :               stats.stun_retransmits, stats.turn_401s, stats.turn_403s,
    1133           0 :               stats.turn_438s);
    1134             : 
    1135           0 :   Telemetry::ScalarAdd(Telemetry::ScalarID::WEBRTC_NICER_STUN_RETRANSMITS,
    1136           0 :                        stats.stun_retransmits);
    1137           0 :   Telemetry::ScalarAdd(Telemetry::ScalarID::WEBRTC_NICER_TURN_401S,
    1138           0 :                        stats.turn_401s);
    1139           0 :   Telemetry::ScalarAdd(Telemetry::ScalarID::WEBRTC_NICER_TURN_403S,
    1140           0 :                        stats.turn_403s);
    1141           0 :   Telemetry::ScalarAdd(Telemetry::ScalarID::WEBRTC_NICER_TURN_438S,
    1142           0 :                        stats.turn_438s);
    1143             : #endif
    1144             : 
    1145           0 :   mIceCtxHdlr = nullptr;
    1146             : 
    1147             :   // we're holding a ref to 'this' that's released by SelfDestruct_m
    1148           0 :   mMainThread->Dispatch(WrapRunnable(this, &PeerConnectionMedia::SelfDestruct_m),
    1149           0 :                         NS_DISPATCH_NORMAL);
    1150           0 : }
    1151             : 
    1152             : LocalSourceStreamInfo*
    1153           0 : PeerConnectionMedia::GetLocalStreamByIndex(int aIndex)
    1154             : {
    1155           0 :   ASSERT_ON_THREAD(mMainThread);
    1156           0 :   if(aIndex < 0 || aIndex >= (int) mLocalSourceStreams.Length()) {
    1157           0 :     return nullptr;
    1158             :   }
    1159             : 
    1160           0 :   MOZ_ASSERT(mLocalSourceStreams[aIndex]);
    1161           0 :   return mLocalSourceStreams[aIndex];
    1162             : }
    1163             : 
    1164             : LocalSourceStreamInfo*
    1165           0 : PeerConnectionMedia::GetLocalStreamById(const std::string& id)
    1166             : {
    1167           0 :   ASSERT_ON_THREAD(mMainThread);
    1168           0 :   for (size_t i = 0; i < mLocalSourceStreams.Length(); ++i) {
    1169           0 :     if (id == mLocalSourceStreams[i]->GetId()) {
    1170           0 :       return mLocalSourceStreams[i];
    1171             :     }
    1172             :   }
    1173             : 
    1174           0 :   return nullptr;
    1175             : }
    1176             : 
    1177             : LocalSourceStreamInfo*
    1178           0 : PeerConnectionMedia::GetLocalStreamByTrackId(const std::string& id)
    1179             : {
    1180           0 :   ASSERT_ON_THREAD(mMainThread);
    1181           0 :   for (RefPtr<LocalSourceStreamInfo>& info : mLocalSourceStreams) {
    1182           0 :     if (info->HasTrack(id)) {
    1183           0 :       return info;
    1184             :     }
    1185             :   }
    1186             : 
    1187           0 :   return nullptr;
    1188             : }
    1189             : 
    1190             : RemoteSourceStreamInfo*
    1191           0 : PeerConnectionMedia::GetRemoteStreamByIndex(size_t aIndex)
    1192             : {
    1193           0 :   ASSERT_ON_THREAD(mMainThread);
    1194           0 :   MOZ_ASSERT(mRemoteSourceStreams.SafeElementAt(aIndex));
    1195           0 :   return mRemoteSourceStreams.SafeElementAt(aIndex);
    1196             : }
    1197             : 
    1198             : RemoteSourceStreamInfo*
    1199           0 : PeerConnectionMedia::GetRemoteStreamById(const std::string& id)
    1200             : {
    1201           0 :   ASSERT_ON_THREAD(mMainThread);
    1202           0 :   for (size_t i = 0; i < mRemoteSourceStreams.Length(); ++i) {
    1203           0 :     if (id == mRemoteSourceStreams[i]->GetId()) {
    1204           0 :       return mRemoteSourceStreams[i];
    1205             :     }
    1206             :   }
    1207             : 
    1208           0 :   return nullptr;
    1209             : }
    1210             : 
    1211             : RemoteSourceStreamInfo*
    1212           0 : PeerConnectionMedia::GetRemoteStreamByTrackId(const std::string& id)
    1213             : {
    1214           0 :   ASSERT_ON_THREAD(mMainThread);
    1215           0 :   for (RefPtr<RemoteSourceStreamInfo>& info : mRemoteSourceStreams) {
    1216           0 :     if (info->HasTrack(id)) {
    1217           0 :       return info;
    1218             :     }
    1219             :   }
    1220             : 
    1221           0 :   return nullptr;
    1222             : }
    1223             : 
    1224             : 
    1225             : nsresult
    1226           0 : PeerConnectionMedia::AddRemoteStream(RefPtr<RemoteSourceStreamInfo> aInfo)
    1227             : {
    1228           0 :   ASSERT_ON_THREAD(mMainThread);
    1229             : 
    1230           0 :   mRemoteSourceStreams.AppendElement(aInfo);
    1231             : 
    1232           0 :   return NS_OK;
    1233             : }
    1234             : 
    1235             : void
    1236           0 : PeerConnectionMedia::IceGatheringStateChange_s(NrIceCtx* ctx,
    1237             :                                                NrIceCtx::GatheringState state)
    1238             : {
    1239           0 :   ASSERT_ON_THREAD(mSTSThread);
    1240             : 
    1241           0 :   if (state == NrIceCtx::ICE_CTX_GATHER_COMPLETE) {
    1242             :     // Fire off EndOfLocalCandidates for each stream
    1243           0 :     for (size_t i = 0; ; ++i) {
    1244           0 :       RefPtr<NrIceMediaStream> stream(ctx->GetStream(i));
    1245           0 :       if (!stream) {
    1246           0 :         break;
    1247             :       }
    1248             : 
    1249           0 :       NrIceCandidate candidate;
    1250           0 :       NrIceCandidate rtcpCandidate;
    1251           0 :       GetDefaultCandidates(*stream, &candidate, &rtcpCandidate);
    1252           0 :       EndOfLocalCandidates(candidate.cand_addr.host,
    1253           0 :                            candidate.cand_addr.port,
    1254             :                            rtcpCandidate.cand_addr.host,
    1255           0 :                            rtcpCandidate.cand_addr.port,
    1256           0 :                            i);
    1257           0 :     }
    1258             :   }
    1259             : 
    1260             :   // ShutdownMediaTransport_s has not run yet because it unhooks this function
    1261             :   // from its signal, which means that SelfDestruct_m has not been dispatched
    1262             :   // yet either, so this PCMedia will still be around when this dispatch reaches
    1263             :   // main.
    1264           0 :   GetMainThread()->Dispatch(
    1265           0 :     WrapRunnable(this,
    1266             :                  &PeerConnectionMedia::IceGatheringStateChange_m,
    1267             :                  ctx,
    1268             :                  state),
    1269           0 :     NS_DISPATCH_NORMAL);
    1270           0 : }
    1271             : 
    1272             : void
    1273           0 : PeerConnectionMedia::IceConnectionStateChange_s(NrIceCtx* ctx,
    1274             :                                                 NrIceCtx::ConnectionState state)
    1275             : {
    1276           0 :   ASSERT_ON_THREAD(mSTSThread);
    1277             :   // ShutdownMediaTransport_s has not run yet because it unhooks this function
    1278             :   // from its signal, which means that SelfDestruct_m has not been dispatched
    1279             :   // yet either, so this PCMedia will still be around when this dispatch reaches
    1280             :   // main.
    1281           0 :   GetMainThread()->Dispatch(
    1282           0 :     WrapRunnable(this,
    1283             :                  &PeerConnectionMedia::IceConnectionStateChange_m,
    1284             :                  ctx,
    1285             :                  state),
    1286           0 :     NS_DISPATCH_NORMAL);
    1287           0 : }
    1288             : 
    1289             : void
    1290           0 : PeerConnectionMedia::OnCandidateFound_s(NrIceMediaStream *aStream,
    1291             :                                         const std::string &aCandidateLine)
    1292             : {
    1293           0 :   ASSERT_ON_THREAD(mSTSThread);
    1294           0 :   MOZ_ASSERT(aStream);
    1295           0 :   MOZ_RELEASE_ASSERT(mIceCtxHdlr);
    1296             : 
    1297           0 :   CSFLogDebug(logTag, "%s: %s", __FUNCTION__, aStream->name().c_str());
    1298             : 
    1299           0 :   NrIceCandidate candidate;
    1300           0 :   NrIceCandidate rtcpCandidate;
    1301           0 :   GetDefaultCandidates(*aStream, &candidate, &rtcpCandidate);
    1302             : 
    1303             :   // ShutdownMediaTransport_s has not run yet because it unhooks this function
    1304             :   // from its signal, which means that SelfDestruct_m has not been dispatched
    1305             :   // yet either, so this PCMedia will still be around when this dispatch reaches
    1306             :   // main.
    1307           0 :   GetMainThread()->Dispatch(
    1308           0 :     WrapRunnable(this,
    1309             :                  &PeerConnectionMedia::OnCandidateFound_m,
    1310             :                  aCandidateLine,
    1311             :                  candidate.cand_addr.host,
    1312           0 :                  candidate.cand_addr.port,
    1313             :                  rtcpCandidate.cand_addr.host,
    1314           0 :                  rtcpCandidate.cand_addr.port,
    1315           0 :                  aStream->GetLevel()),
    1316           0 :     NS_DISPATCH_NORMAL);
    1317           0 : }
    1318             : 
    1319             : void
    1320           0 : PeerConnectionMedia::EndOfLocalCandidates(const std::string& aDefaultAddr,
    1321             :                                           uint16_t aDefaultPort,
    1322             :                                           const std::string& aDefaultRtcpAddr,
    1323             :                                           uint16_t aDefaultRtcpPort,
    1324             :                                           uint16_t aMLine)
    1325             : {
    1326           0 :   GetMainThread()->Dispatch(
    1327           0 :     WrapRunnable(this,
    1328             :                  &PeerConnectionMedia::EndOfLocalCandidates_m,
    1329             :                  aDefaultAddr,
    1330             :                  aDefaultPort,
    1331             :                  aDefaultRtcpAddr,
    1332             :                  aDefaultRtcpPort,
    1333             :                  aMLine),
    1334           0 :     NS_DISPATCH_NORMAL);
    1335           0 : }
    1336             : 
    1337             : void
    1338           0 : PeerConnectionMedia::GetDefaultCandidates(const NrIceMediaStream& aStream,
    1339             :                                           NrIceCandidate* aCandidate,
    1340             :                                           NrIceCandidate* aRtcpCandidate)
    1341             : {
    1342           0 :   nsresult res = aStream.GetDefaultCandidate(1, aCandidate);
    1343             :   // Optional; component won't exist if doing rtcp-mux
    1344           0 :   if (NS_FAILED(aStream.GetDefaultCandidate(2, aRtcpCandidate))) {
    1345           0 :     aRtcpCandidate->cand_addr.host.clear();
    1346           0 :     aRtcpCandidate->cand_addr.port = 0;
    1347             :   }
    1348           0 :   if (NS_FAILED(res)) {
    1349           0 :     aCandidate->cand_addr.host.clear();
    1350           0 :     aCandidate->cand_addr.port = 0;
    1351           0 :     CSFLogError(logTag, "%s: GetDefaultCandidates failed for level %u, "
    1352             :                         "res=%u",
    1353             :                         __FUNCTION__,
    1354             :                         static_cast<unsigned>(aStream.GetLevel()),
    1355           0 :                         static_cast<unsigned>(res));
    1356             :   }
    1357           0 : }
    1358             : 
    1359             : void
    1360           0 : PeerConnectionMedia::IceGatheringStateChange_m(NrIceCtx* ctx,
    1361             :                                                NrIceCtx::GatheringState state)
    1362             : {
    1363           0 :   ASSERT_ON_THREAD(mMainThread);
    1364           0 :   SignalIceGatheringStateChange(ctx, state);
    1365           0 : }
    1366             : 
    1367             : void
    1368           0 : PeerConnectionMedia::IceConnectionStateChange_m(NrIceCtx* ctx,
    1369             :                                                 NrIceCtx::ConnectionState state)
    1370             : {
    1371           0 :   ASSERT_ON_THREAD(mMainThread);
    1372           0 :   SignalIceConnectionStateChange(ctx, state);
    1373           0 : }
    1374             : 
    1375             : void
    1376           0 : PeerConnectionMedia::IceStreamReady_s(NrIceMediaStream *aStream)
    1377             : {
    1378           0 :   MOZ_ASSERT(aStream);
    1379             : 
    1380           0 :   CSFLogDebug(logTag, "%s: %s", __FUNCTION__, aStream->name().c_str());
    1381           0 : }
    1382             : 
    1383             : void
    1384           0 : PeerConnectionMedia::OnCandidateFound_m(const std::string& aCandidateLine,
    1385             :                                         const std::string& aDefaultAddr,
    1386             :                                         uint16_t aDefaultPort,
    1387             :                                         const std::string& aDefaultRtcpAddr,
    1388             :                                         uint16_t aDefaultRtcpPort,
    1389             :                                         uint16_t aMLine)
    1390             : {
    1391           0 :   ASSERT_ON_THREAD(mMainThread);
    1392           0 :   if (!aDefaultAddr.empty()) {
    1393           0 :     SignalUpdateDefaultCandidate(aDefaultAddr,
    1394             :                                  aDefaultPort,
    1395             :                                  aDefaultRtcpAddr,
    1396             :                                  aDefaultRtcpPort,
    1397           0 :                                  aMLine);
    1398             :   }
    1399           0 :   SignalCandidate(aCandidateLine, aMLine);
    1400           0 : }
    1401             : 
    1402             : void
    1403           0 : PeerConnectionMedia::EndOfLocalCandidates_m(const std::string& aDefaultAddr,
    1404             :                                             uint16_t aDefaultPort,
    1405             :                                             const std::string& aDefaultRtcpAddr,
    1406             :                                             uint16_t aDefaultRtcpPort,
    1407             :                                             uint16_t aMLine) {
    1408           0 :   ASSERT_ON_THREAD(mMainThread);
    1409           0 :   if (!aDefaultAddr.empty()) {
    1410           0 :     SignalUpdateDefaultCandidate(aDefaultAddr,
    1411             :                                  aDefaultPort,
    1412             :                                  aDefaultRtcpAddr,
    1413             :                                  aDefaultRtcpPort,
    1414           0 :                                  aMLine);
    1415             :   }
    1416           0 :   SignalEndOfLocalCandidates(aMLine);
    1417           0 : }
    1418             : 
    1419             : void
    1420           0 : PeerConnectionMedia::DtlsConnected_s(TransportLayer *layer,
    1421             :                                      TransportLayer::State state)
    1422             : {
    1423           0 :   MOZ_ASSERT(layer->id() == "dtls");
    1424           0 :   TransportLayerDtls* dtlsLayer = static_cast<TransportLayerDtls*>(layer);
    1425           0 :   dtlsLayer->SignalStateChange.disconnect(this);
    1426             : 
    1427           0 :   bool privacyRequested = (dtlsLayer->GetNegotiatedAlpn() == "c-webrtc");
    1428           0 :   GetMainThread()->Dispatch(
    1429           0 :     WrapRunnableNM(&PeerConnectionMedia::DtlsConnected_m,
    1430             :                    mParentHandle, privacyRequested),
    1431           0 :     NS_DISPATCH_NORMAL);
    1432           0 : }
    1433             : 
    1434             : void
    1435           0 : PeerConnectionMedia::DtlsConnected_m(const std::string& aParentHandle,
    1436             :                                      bool aPrivacyRequested)
    1437             : {
    1438           0 :   PeerConnectionWrapper pcWrapper(aParentHandle);
    1439           0 :   PeerConnectionImpl* pc = pcWrapper.impl();
    1440           0 :   if (pc) {
    1441           0 :     pc->SetDtlsConnected(aPrivacyRequested);
    1442             :   }
    1443           0 : }
    1444             : 
    1445             : void
    1446           0 : PeerConnectionMedia::AddTransportFlow(int aIndex, bool aRtcp,
    1447             :                                       const RefPtr<TransportFlow> &aFlow)
    1448             : {
    1449           0 :   int index_inner = GetTransportFlowIndex(aIndex, aRtcp);
    1450             : 
    1451           0 :   MOZ_ASSERT(!mTransportFlows[index_inner]);
    1452           0 :   mTransportFlows[index_inner] = aFlow;
    1453             : 
    1454           0 :   GetSTSThread()->Dispatch(
    1455           0 :     WrapRunnable(this, &PeerConnectionMedia::ConnectDtlsListener_s, aFlow),
    1456           0 :     NS_DISPATCH_NORMAL);
    1457           0 : }
    1458             : 
    1459             : void
    1460           0 : PeerConnectionMedia::RemoveTransportFlow(int aIndex, bool aRtcp)
    1461             : {
    1462           0 :   int index_inner = GetTransportFlowIndex(aIndex, aRtcp);
    1463           0 :   NS_ProxyRelease(
    1464             :     "PeerConnectionMedia::mTransportFlows",
    1465           0 :     GetSTSThread(), mTransportFlows[index_inner].forget());
    1466           0 : }
    1467             : 
    1468             : void
    1469           0 : PeerConnectionMedia::ConnectDtlsListener_s(const RefPtr<TransportFlow>& aFlow)
    1470             : {
    1471           0 :   TransportLayer* dtls = aFlow->GetLayer(TransportLayerDtls::ID());
    1472           0 :   if (dtls) {
    1473           0 :     dtls->SignalStateChange.connect(this, &PeerConnectionMedia::DtlsConnected_s);
    1474             :   }
    1475           0 : }
    1476             : 
    1477             : nsresult
    1478           0 : LocalSourceStreamInfo::TakePipelineFrom(RefPtr<LocalSourceStreamInfo>& info,
    1479             :                                         const std::string& oldTrackId,
    1480             :                                         MediaStreamTrack& aNewTrack,
    1481             :                                         const std::string& newTrackId)
    1482             : {
    1483           0 :   if (mPipelines.count(newTrackId)) {
    1484           0 :     CSFLogError(logTag, "%s: Pipeline already exists for %s/%s",
    1485           0 :                 __FUNCTION__, mId.c_str(), newTrackId.c_str());
    1486           0 :     return NS_ERROR_INVALID_ARG;
    1487             :   }
    1488             : 
    1489           0 :   RefPtr<MediaPipeline> pipeline(info->ForgetPipelineByTrackId_m(oldTrackId));
    1490             : 
    1491           0 :   if (!pipeline) {
    1492             :     // Replacetrack can potentially happen in the middle of offer/answer, before
    1493             :     // the pipeline has been created.
    1494             :     CSFLogInfo(logTag, "%s: Replacing track before the pipeline has been "
    1495           0 :                        "created, nothing to do.", __FUNCTION__);
    1496           0 :     return NS_OK;
    1497             :   }
    1498             : 
    1499             :   nsresult rv =
    1500           0 :     static_cast<MediaPipelineTransmit*>(pipeline.get())->ReplaceTrack(aNewTrack);
    1501           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1502             : 
    1503           0 :   mPipelines[newTrackId] = pipeline;
    1504             : 
    1505           0 :   return NS_OK;
    1506             : }
    1507             : 
    1508             : /**
    1509             :  * Tells you if any local track is isolated to a specific peer identity.
    1510             :  * Obviously, we want all the tracks to be isolated equally so that they can
    1511             :  * all be sent or not.  We check once when we are setting a local description
    1512             :  * and that determines if we flip the "privacy requested" bit on.  Once the bit
    1513             :  * is on, all media originating from this peer connection is isolated.
    1514             :  *
    1515             :  * @returns true if any track has a peerIdentity set on it
    1516             :  */
    1517             : bool
    1518           0 : PeerConnectionMedia::AnyLocalTrackHasPeerIdentity() const
    1519             : {
    1520           0 :   ASSERT_ON_THREAD(mMainThread);
    1521             : 
    1522           0 :   for (uint32_t u = 0; u < mLocalSourceStreams.Length(); u++) {
    1523           0 :     for (auto pair : mLocalSourceStreams[u]->GetMediaStreamTracks()) {
    1524           0 :       if (pair.second->GetPeerIdentity() != nullptr) {
    1525           0 :         return true;
    1526             :       }
    1527             :     }
    1528             :   }
    1529           0 :   return false;
    1530             : }
    1531             : 
    1532             : void
    1533           0 : PeerConnectionMedia::UpdateRemoteStreamPrincipals_m(nsIPrincipal* aPrincipal)
    1534             : {
    1535           0 :   ASSERT_ON_THREAD(mMainThread);
    1536             : 
    1537           0 :   for (uint32_t u = 0; u < mRemoteSourceStreams.Length(); u++) {
    1538           0 :     mRemoteSourceStreams[u]->UpdatePrincipal_m(aPrincipal);
    1539             :   }
    1540           0 : }
    1541             : 
    1542             : void
    1543           0 : PeerConnectionMedia::UpdateSinkIdentity_m(MediaStreamTrack* aTrack,
    1544             :                                           nsIPrincipal* aPrincipal,
    1545             :                                           const PeerIdentity* aSinkIdentity)
    1546             : {
    1547           0 :   ASSERT_ON_THREAD(mMainThread);
    1548             : 
    1549           0 :   for (uint32_t u = 0; u < mLocalSourceStreams.Length(); u++) {
    1550           0 :     mLocalSourceStreams[u]->UpdateSinkIdentity_m(aTrack, aPrincipal,
    1551           0 :                                                  aSinkIdentity);
    1552             :   }
    1553           0 : }
    1554             : 
    1555             : void
    1556           0 : LocalSourceStreamInfo::UpdateSinkIdentity_m(MediaStreamTrack* aTrack,
    1557             :                                             nsIPrincipal* aPrincipal,
    1558             :                                             const PeerIdentity* aSinkIdentity)
    1559             : {
    1560           0 :   for (auto& pipeline_ : mPipelines) {
    1561             :     MediaPipelineTransmit* pipeline =
    1562           0 :       static_cast<MediaPipelineTransmit*>(pipeline_.second.get());
    1563           0 :     pipeline->UpdateSinkIdentity_m(aTrack, aPrincipal, aSinkIdentity);
    1564             :   }
    1565           0 : }
    1566             : 
    1567           0 : void RemoteSourceStreamInfo::UpdatePrincipal_m(nsIPrincipal* aPrincipal)
    1568             : {
    1569             :   // This blasts away the existing principal.
    1570             :   // We only do this when we become certain that the all tracks are safe to make
    1571             :   // accessible to the script principal.
    1572           0 :   for (auto& trackPair : mTracks) {
    1573           0 :     MOZ_RELEASE_ASSERT(trackPair.second);
    1574             :     RemoteTrackSource& source =
    1575           0 :       static_cast<RemoteTrackSource&>(trackPair.second->GetSource());
    1576           0 :     source.SetPrincipal(aPrincipal);
    1577             : 
    1578           0 :     RefPtr<MediaPipeline> pipeline = GetPipelineByTrackId_m(trackPair.first);
    1579           0 :     if (pipeline) {
    1580           0 :       MOZ_ASSERT(pipeline->direction() == MediaPipeline::RECEIVE);
    1581           0 :       static_cast<MediaPipelineReceive*>(pipeline.get())
    1582           0 :         ->SetPrincipalHandle_m(MakePrincipalHandle(aPrincipal));
    1583             :     }
    1584             :   }
    1585           0 : }
    1586             : 
    1587             : bool
    1588           0 : PeerConnectionMedia::AnyCodecHasPluginID(uint64_t aPluginID)
    1589             : {
    1590           0 :   for (uint32_t i=0; i < mLocalSourceStreams.Length(); ++i) {
    1591           0 :     if (mLocalSourceStreams[i]->AnyCodecHasPluginID(aPluginID)) {
    1592           0 :       return true;
    1593             :     }
    1594             :   }
    1595           0 :   for (uint32_t i=0; i < mRemoteSourceStreams.Length(); ++i) {
    1596           0 :     if (mRemoteSourceStreams[i]->AnyCodecHasPluginID(aPluginID)) {
    1597           0 :       return true;
    1598             :     }
    1599             :   }
    1600           0 :   return false;
    1601             : }
    1602             : 
    1603             : bool
    1604           0 : SourceStreamInfo::AnyCodecHasPluginID(uint64_t aPluginID)
    1605             : {
    1606             :   // Scan the videoConduits for this plugin ID
    1607           0 :   for (auto& pipeline : mPipelines) {
    1608           0 :     if (pipeline.second->Conduit()->CodecPluginID() == aPluginID) {
    1609           0 :       return true;
    1610             :     }
    1611             :   }
    1612           0 :   return false;
    1613             : }
    1614             : 
    1615             : nsresult
    1616           0 : SourceStreamInfo::StorePipeline(
    1617             :     const std::string& trackId,
    1618             :     const RefPtr<mozilla::MediaPipeline>& aPipeline)
    1619             : {
    1620           0 :   MOZ_ASSERT(mPipelines.find(trackId) == mPipelines.end());
    1621           0 :   if (mPipelines.find(trackId) != mPipelines.end()) {
    1622           0 :     CSFLogError(logTag, "%s: Storing duplicate track", __FUNCTION__);
    1623           0 :     return NS_ERROR_FAILURE;
    1624             :   }
    1625             : 
    1626           0 :   mPipelines[trackId] = aPipeline;
    1627           0 :   return NS_OK;
    1628             : }
    1629             : 
    1630             : void
    1631           0 : RemoteSourceStreamInfo::DetachMedia_m()
    1632             : {
    1633           0 :   for (auto& webrtcIdAndTrack : mTracks) {
    1634           0 :     EndTrack(mMediaStream->GetInputStream(), webrtcIdAndTrack.second);
    1635             :   }
    1636           0 :   SourceStreamInfo::DetachMedia_m();
    1637           0 : }
    1638             : 
    1639             : void
    1640           0 : RemoteSourceStreamInfo::RemoveTrack(const std::string& trackId)
    1641             : {
    1642           0 :   auto it = mTracks.find(trackId);
    1643           0 :   if (it != mTracks.end()) {
    1644           0 :     EndTrack(mMediaStream->GetInputStream(), it->second);
    1645             :   }
    1646             : 
    1647           0 :   SourceStreamInfo::RemoveTrack(trackId);
    1648           0 : }
    1649             : 
    1650             : void
    1651           0 : RemoteSourceStreamInfo::SyncPipeline(
    1652             :   RefPtr<MediaPipelineReceive> aPipeline)
    1653             : {
    1654             :   // See if we have both audio and video here, and if so cross the streams and
    1655             :   // sync them
    1656             :   // TODO: Do we need to prevent multiple syncs if there is more than one audio
    1657             :   // or video track in a single media stream? What are we supposed to do in this
    1658             :   // case?
    1659           0 :   for (auto i = mPipelines.begin(); i != mPipelines.end(); ++i) {
    1660           0 :     if (i->second->IsVideo() != aPipeline->IsVideo()) {
    1661             :       // Ok, we have one video, one non-video - cross the streams!
    1662             :       WebrtcAudioConduit *audio_conduit =
    1663           0 :         static_cast<WebrtcAudioConduit*>(aPipeline->IsVideo() ?
    1664           0 :                                                   i->second->Conduit() :
    1665           0 :                                                   aPipeline->Conduit());
    1666             :       WebrtcVideoConduit *video_conduit =
    1667           0 :         static_cast<WebrtcVideoConduit*>(aPipeline->IsVideo() ?
    1668           0 :                                                   aPipeline->Conduit() :
    1669           0 :                                                   i->second->Conduit());
    1670           0 :       video_conduit->SyncTo(audio_conduit);
    1671           0 :       CSFLogDebug(logTag, "Syncing %p to %p, %s to %s",
    1672             :                           video_conduit, audio_conduit,
    1673           0 :                           i->first.c_str(), aPipeline->trackid().c_str());
    1674             :     }
    1675             :   }
    1676           0 : }
    1677             : 
    1678             : void
    1679           0 : RemoteSourceStreamInfo::StartReceiving()
    1680             : {
    1681           0 :   if (mReceiving || mPipelines.empty()) {
    1682           0 :     return;
    1683             :   }
    1684             : 
    1685           0 :   mReceiving = true;
    1686             : 
    1687           0 :   SourceMediaStream* source = GetMediaStream()->GetInputStream()->AsSourceStream();
    1688           0 :   source->SetPullEnabled(true);
    1689             :   // AdvanceKnownTracksTicksTime(HEAT_DEATH_OF_UNIVERSE) means that in
    1690             :   // theory per the API, we can't add more tracks before that
    1691             :   // time. However, the impl actually allows it, and it avoids a whole
    1692             :   // bunch of locking that would be required (and potential blocking)
    1693             :   // if we used smaller values and updated them on each NotifyPull.
    1694           0 :   source->AdvanceKnownTracksTime(STREAM_TIME_MAX);
    1695           0 :   CSFLogDebug(logTag, "Finished adding tracks to MediaStream %p", source);
    1696             : }
    1697             : 
    1698           0 : RefPtr<MediaPipeline> SourceStreamInfo::GetPipelineByTrackId_m(
    1699             :     const std::string& trackId) {
    1700           0 :   ASSERT_ON_THREAD(mParent->GetMainThread());
    1701             : 
    1702             :   // Refuse to hand out references if we're tearing down.
    1703             :   // (Since teardown involves a dispatch to and from STS before MediaPipelines
    1704             :   // are released, it is safe to start other dispatches to and from STS with a
    1705             :   // RefPtr<MediaPipeline>, since that reference won't be the last one
    1706             :   // standing)
    1707           0 :   if (mMediaStream) {
    1708           0 :     if (mPipelines.count(trackId)) {
    1709           0 :       return mPipelines[trackId];
    1710             :     }
    1711             :   }
    1712             : 
    1713           0 :   return nullptr;
    1714             : }
    1715             : 
    1716             : already_AddRefed<MediaPipeline>
    1717           0 : LocalSourceStreamInfo::ForgetPipelineByTrackId_m(const std::string& trackId)
    1718             : {
    1719           0 :   ASSERT_ON_THREAD(mParent->GetMainThread());
    1720             : 
    1721             :   // Refuse to hand out references if we're tearing down.
    1722             :   // (Since teardown involves a dispatch to and from STS before MediaPipelines
    1723             :   // are released, it is safe to start other dispatches to and from STS with a
    1724             :   // RefPtr<MediaPipeline>, since that reference won't be the last one
    1725             :   // standing)
    1726           0 :   if (mMediaStream) {
    1727           0 :     if (mPipelines.count(trackId)) {
    1728           0 :       RefPtr<MediaPipeline> pipeline(mPipelines[trackId]);
    1729           0 :       mPipelines.erase(trackId);
    1730           0 :       return pipeline.forget();
    1731             :     }
    1732             :   }
    1733             : 
    1734           0 :   return nullptr;
    1735             : }
    1736             : 
    1737             : auto
    1738           0 : RemoteTrackSource::ApplyConstraints(
    1739             :     nsPIDOMWindowInner* aWindow,
    1740             :     const dom::MediaTrackConstraints& aConstraints,
    1741             :     dom::CallerType aCallerType) -> already_AddRefed<PledgeVoid>
    1742             : {
    1743           0 :   RefPtr<PledgeVoid> p = new PledgeVoid();
    1744           0 :   p->Reject(new dom::MediaStreamError(aWindow,
    1745           0 :                                       NS_LITERAL_STRING("OverconstrainedError"),
    1746           0 :                                       NS_LITERAL_STRING("")));
    1747           0 :   return p.forget();
    1748             : }
    1749             : 
    1750             : } // namespace mozilla

Generated by: LCOV version 1.13