void PeerConnectionMedia::StartIceChecks(const JsepSession& session) { std::vector<size_t> numComponentsByLevel; auto transports = session.GetTransports(); for (size_t i = 0; i < transports.size(); ++i) { RefPtr<JsepTransport> transport = transports[i]; if (transport->mState == JsepTransport::kJsepTransportClosed) { CSFLogDebug(logTag, "Transport %s is disabled", transport->mTransportId.c_str()); numComponentsByLevel.push_back(0); // Make sure the MediaPipelineFactory doesn't try to use these. RemoveTransportFlow(i, false); RemoveTransportFlow(i, true); } else { CSFLogDebug(logTag, "Transport %s has %u components", transport->mTransportId.c_str(), static_cast<unsigned>(transport->mComponents)); numComponentsByLevel.push_back(transport->mComponents); } } nsCOMPtr<nsIRunnable> runnable( WrapRunnable( RefPtr<PeerConnectionMedia>(this), &PeerConnectionMedia::StartIceChecks_s, session.IsIceControlling(), session.RemoteIsIceLite(), // Copy, just in case API changes to return a ref std::vector<std::string>(session.GetIceOptions()), numComponentsByLevel)); PerformOrEnqueueIceCtxOperation(runnable); }
void PeerConnectionMedia::ActivateOrRemoveTransports(const JsepSession& aSession) { auto transports = aSession.GetTransports(); for (size_t i = 0; i < transports.size(); ++i) { RefPtr<JsepTransport> transport = transports[i]; std::string ufrag; std::string pwd; std::vector<std::string> candidates; if (transport->mComponents) { MOZ_ASSERT(transport->mIce); CSFLogDebug(logTag, "Transport %u is active", static_cast<unsigned>(i)); ufrag = transport->mIce->GetUfrag(); pwd = transport->mIce->GetPassword(); candidates = transport->mIce->GetCandidates(); } else { CSFLogDebug(logTag, "Transport %u is disabled", static_cast<unsigned>(i)); // Make sure the MediaPipelineFactory doesn't try to use these. RemoveTransportFlow(i, false); RemoveTransportFlow(i, true); } RUN_ON_THREAD( GetSTSThread(), WrapRunnable(RefPtr<PeerConnectionMedia>(this), &PeerConnectionMedia::ActivateOrRemoveTransport_s, i, transport->mComponents, ufrag, pwd, candidates), NS_DISPATCH_NORMAL); } // We can have more streams than m-lines due to rollback. RUN_ON_THREAD( GetSTSThread(), WrapRunnable(RefPtr<PeerConnectionMedia>(this), &PeerConnectionMedia::RemoveTransportsAtOrAfter_s, transports.size()), NS_DISPATCH_NORMAL); }
nsresult PeerConnectionMedia::UpdateTransportFlow( size_t aLevel, bool aIsRtcp, const JsepTransport& aTransport) { if (aIsRtcp && aTransport.mComponents < 2) { RemoveTransportFlow(aLevel, aIsRtcp); return NS_OK; } if (!aIsRtcp && !aTransport.mComponents) { RemoveTransportFlow(aLevel, aIsRtcp); return NS_OK; } nsresult rv; RefPtr<TransportFlow> flow = GetTransportFlow(aLevel, aIsRtcp); if (flow) { if (IsIceRestarting()) { CSFLogInfo(LOGTAG, "Flow[%s]: detected ICE restart - level: %u rtcp: %d", flow->id().c_str(), (unsigned)aLevel, aIsRtcp); RefPtr<PeerConnectionMedia> pcMedia(this); rv = GetSTSThread()->Dispatch( WrapRunnableNM(AddNewIceStreamForRestart_s, pcMedia, flow, aLevel, aIsRtcp), NS_DISPATCH_NORMAL); if (NS_FAILED(rv)) { CSFLogError(LOGTAG, "Failed to dispatch AddNewIceStreamForRestart_s"); return rv; } } return NS_OK; } std::ostringstream osId; osId << mParentHandle << ":" << aLevel << "," << (aIsRtcp ? "rtcp" : "rtp"); flow = new TransportFlow(osId.str()); // The media streams are made on STS so we need to defer setup. auto ice = MakeUnique<TransportLayerIce>(); auto dtls = MakeUnique<TransportLayerDtls>(); dtls->SetRole(aTransport.mDtls->GetRole() == JsepDtlsTransport::kJsepDtlsClient ? TransportLayerDtls::CLIENT : TransportLayerDtls::SERVER); RefPtr<DtlsIdentity> pcid = mParent->Identity(); if (!pcid) { CSFLogError(LOGTAG, "Failed to get DTLS identity."); return NS_ERROR_FAILURE; } dtls->SetIdentity(pcid); const SdpFingerprintAttributeList& fingerprints = aTransport.mDtls->GetFingerprints(); for (const auto& fingerprint : fingerprints.mFingerprints) { std::ostringstream ss; ss << fingerprint.hashFunc; rv = dtls->SetVerificationDigest(ss.str(), &fingerprint.fingerprint[0], fingerprint.fingerprint.size()); if (NS_FAILED(rv)) { CSFLogError(LOGTAG, "Could not set fingerprint"); return rv; } } std::vector<uint16_t> srtpCiphers; srtpCiphers.push_back(SRTP_AES128_CM_HMAC_SHA1_80); srtpCiphers.push_back(SRTP_AES128_CM_HMAC_SHA1_32); rv = dtls->SetSrtpCiphers(srtpCiphers); if (NS_FAILED(rv)) { CSFLogError(LOGTAG, "Couldn't set SRTP ciphers"); return rv; } // Always permits negotiation of the confidential mode. // Only allow non-confidential (which is an allowed default), // if we aren't confidential. std::set<std::string> alpn; std::string alpnDefault = ""; alpn.insert("c-webrtc"); if (!mParent->PrivacyRequested()) { alpnDefault = "webrtc"; alpn.insert(alpnDefault); } rv = dtls->SetAlpn(alpn, alpnDefault); if (NS_FAILED(rv)) { CSFLogError(LOGTAG, "Couldn't set ALPN"); return rv; } nsAutoPtr<PtrVector<TransportLayer> > layers(new PtrVector<TransportLayer>); layers->values.push_back(ice.release()); layers->values.push_back(dtls.release()); RefPtr<PeerConnectionMedia> pcMedia(this); rv = GetSTSThread()->Dispatch( WrapRunnableNM(FinalizeTransportFlow_s, pcMedia, flow, aLevel, aIsRtcp, layers), NS_DISPATCH_NORMAL); if (NS_FAILED(rv)) { CSFLogError(LOGTAG, "Failed to dispatch FinalizeTransportFlow_s"); return rv; } AddTransportFlow(aLevel, aIsRtcp, flow); return NS_OK; }