/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <cstdlib>
#include <cerrno>
#include <deque>
#include <set>
#include <sstream>
#include <vector>
#include "common/browser_logging/CSFLog.h"
#include "base/histogram.h"
#include "common/time_profiling/timecard.h"
#include "jsapi.h"
#include "nspr.h"
#include "nss.h"
#include "pk11pub.h"
#include "nsNetCID.h"
#include "nsILoadContext.h"
#include "nsEffectiveTLDService.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsProxyRelease.h"
#include "prtime.h"
#include "libwebrtcglue/AudioConduit.h"
#include "libwebrtcglue/VideoConduit.h"
#include "libwebrtcglue/WebrtcCallWrapper.h"
#include "MediaTrackGraph.h"
#include "transport/runnable_utils.h"
#include "IPeerConnection.h"
#include "PeerConnectionCtx.h"
#include "PeerConnectionImpl.h"
#include "RemoteTrackSource.h"
#include "nsDOMDataChannelDeclarations.h"
#include "transport/dtlsidentity.h"
#include "sdp/SdpAttribute.h"
#include "jsep/JsepTrack.h"
#include "jsep/JsepSession.h"
#include "jsep/JsepSessionImpl.h"
#include "transportbridge/MediaPipeline.h"
#include "transportbridge/RtpLogger.h"
#include "jsapi/RTCRtpReceiver.h"
#include "jsapi/RTCRtpSender.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Sprintf.h"
#include "mozilla/StaticPrefs_media.h"
#include "mozilla/media/MediaUtils.h"
#ifdef XP_WIN
// We need to undef the MS macro for Document::CreateEvent
# ifdef CreateEvent
# undef CreateEvent
# endif
#endif // XP_WIN
#include "mozilla/dom/Document.h"
#include "nsGlobalWindowInner.h"
#include "nsDOMDataChannel.h"
#include "mozilla/dom/Location.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/glean/DomMediaWebrtcMetrics.h"
#include "mozilla/Preferences.h"
#include "mozilla/PublicSSL.h"
#include "nsXULAppAPI.h"
#include "nsContentUtils.h"
#include "nsDOMJSUtils.h"
#include "nsPrintfCString.h"
#include "nsURLHelper.h"
#include "nsNetUtil.h"
#include "js/ArrayBuffer.h" // JS::NewArrayBufferWithContents
#include "js/GCAnnotations.h" // JS_HAZ_ROOTED
#include "js/RootingAPI.h" // JS::{{,Mutable}Handle,Rooted}
#include "mozilla/PeerIdentity.h"
#include "mozilla/dom/RTCCertificate.h"
#include "mozilla/dom/RTCSctpTransportBinding.h" // RTCSctpTransportState
#include "mozilla/dom/RTCDtlsTransportBinding.h" // RTCDtlsTransportState
#include "mozilla/dom/RTCIceTransportBinding.h" // RTCIceTransportState
#include "mozilla/dom/RTCRtpReceiverBinding.h"
#include "mozilla/dom/RTCRtpSenderBinding.h"
#include "mozilla/dom/RTCStatsReportBinding.h"
#include "mozilla/dom/RTCPeerConnectionBinding.h"
#include "mozilla/dom/PeerConnectionImplBinding.h"
#include "mozilla/dom/RTCDataChannelBinding.h"
#include "mozilla/dom/PluginCrashedEvent.h"
#include "MediaStreamTrack.h"
#include "AudioStreamTrack.h"
#include "VideoStreamTrack.h"
#include "nsIScriptGlobalObject.h"
#include "DOMMediaStream.h"
#include "WebrtcGlobalInformation.h"
#include "mozilla/dom/Event.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/net/DataChannelProtocol.h"
#include "MediaManager.h"
#include "transport/nr_socket_proxy_config.h"
#include "RTCSctpTransport.h"
#include "RTCDtlsTransport.h"
#include "jsep/JsepTransport.h"
#include "nsILoadInfo.h"
#include "nsIPrincipal.h"
#include "mozilla/LoadInfo.h"
#include "nsIProxiedChannel.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/net/WebrtcProxyConfig.h"
#ifdef XP_WIN
// We need to undef the MS macro again in case the windows include file
// got imported after we included mozilla/dom/Document.h
# ifdef CreateEvent
# undef CreateEvent
# endif
#endif // XP_WIN
#include "MediaSegment.h"
#ifdef USE_FAKE_PCOBSERVER
# include
"FakePCObserver.h"
#else
# include
"mozilla/dom/PeerConnectionObserverBinding.h"
#endif
#include "mozilla/dom/PeerConnectionObserverEnumsBinding.h"
#define ICE_PARSING \
"In RTCConfiguration passed to RTCPeerConnection constructor"
using namespace mozilla;
using namespace mozilla::dom;
typedef PCObserverString ObString;
static const char* pciLogTag =
"PeerConnectionImpl";
#ifdef LOGTAG
# undef LOGTAG
#endif
#define LOGTAG pciLogTag
static mozilla::LazyLogModule logModuleInfo(
"signaling");
// Getting exceptions back down from PCObserver is generally not harmful.
namespace {
// This is a terrible hack. The problem is that SuppressException is not
// inline, and we link this file without libxul in some cases (e.g. for our test
// setup). So we can't use ErrorResult or IgnoredErrorResult because those call
// SuppressException... And we can't use FastErrorResult because we can't
// include BindingUtils.h, because our linking is completely broken. Use
// BaseErrorResult directly. Please do not let me see _anyone_ doing this
// without really careful review from someone who knows what they are doing.
class JSErrorResult :
public binding_danger::TErrorResult<
binding_danger::JustAssertCleanupPolicy> {
public:
~JSErrorResult() { SuppressException(); }
} JS_HAZ_ROOTED;
// The WrapRunnable() macros copy passed-in args and passes them to the function
// later on the other thread. ErrorResult cannot be passed like this because it
// disallows copy-semantics.
//
// This WrappableJSErrorResult hack solves this by not actually copying the
// ErrorResult, but creating a new one instead, which works because we don't
// care about the result.
//
// Since this is for JS-calls, these can only be dispatched to the main thread.
class WrappableJSErrorResult {
public:
WrappableJSErrorResult() : mRv(MakeUnique<JSErrorResult>()), isCopy(
false) {}
WrappableJSErrorResult(
const WrappableJSErrorResult& other)
: mRv(MakeUnique<JSErrorResult>()), isCopy(
true) {}
~WrappableJSErrorResult() {
if (isCopy) {
MOZ_ASSERT(NS_IsMainThread());
}
}
operator ErrorResult&() {
return *mRv; }
private:
mozilla::UniquePtr<JSErrorResult> mRv;
bool isCopy;
} JS_HAZ_ROOTED;
}
// namespace
static nsresult InitNSSInContent() {
NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD);
if (!XRE_IsContentProcess()) {
MOZ_ASSERT_UNREACHABLE(
"Must be called in content process");
return NS_ERROR_FAILURE;
}
static bool nssStarted =
false;
if (nssStarted) {
return NS_OK;
}
if (NSS_NoDB_Init(nullptr) != SECSuccess) {
CSFLogError(LOGTAG,
"NSS_NoDB_Init failed.");
return NS_ERROR_FAILURE;
}
if (NS_FAILED(mozilla::psm::InitializeCipherSuite())) {
CSFLogError(LOGTAG,
"Fail to set up nss cipher suite.");
return NS_ERROR_FAILURE;
}
mozilla::psm::DisableMD5();
nssStarted =
true;
return NS_OK;
}
namespace mozilla {
class DataChannel;
}
namespace mozilla {
void PeerConnectionAutoTimer::RegisterConnection() { mRefCnt++; }
void PeerConnectionAutoTimer::UnregisterConnection(
bool aContainedAV) {
MOZ_ASSERT(mRefCnt);
mRefCnt--;
mUsedAV |= aContainedAV;
if (mRefCnt ==
0) {
TimeDuration sample = TimeStamp::Now() - mStart;
if (mUsedAV) {
glean::webrtc::av_call_duration.AccumulateRawDuration(sample);
}
glean::webrtc::call_duration.AccumulateRawDuration(sample);
}
}
bool PeerConnectionAutoTimer::IsStopped() {
return mRefCnt ==
0; }
// There is not presently an implementation of these for nsTHashMap :(
inline void ImplCycleCollectionUnlink(
PeerConnectionImpl::RTCDtlsTransportMap& aMap) {
for (
auto& tableEntry : aMap) {
ImplCycleCollectionUnlink(*tableEntry.GetModifiableData());
}
aMap.Clear();
}
inline void ImplCycleCollectionTraverse(
nsCycleCollectionTraversalCallback& aCallback,
PeerConnectionImpl::RTCDtlsTransportMap& aMap,
const char* aName,
uint32_t aFlags =
0) {
for (
auto& tableEntry : aMap) {
ImplCycleCollectionTraverse(aCallback, *tableEntry.GetModifiableData(),
aName, aFlags);
}
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(PeerConnectionImpl)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PeerConnectionImpl)
tmp->Close();
tmp->BreakCycles();
NS_IMPL_CYCLE_COLLECTION_UNLINK(
mPCObserver, mWindow, mCertificate, mSTSThread, mReceiveStreams,
mOperations, mTransportIdToRTCDtlsTransport, mSctpTransport,
mLastStableSctpTransport, mLastStableSctpDtlsTransport, mKungFuDeathGrip)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PeerConnectionImpl)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(
mPCObserver, mWindow, mCertificate, mSTSThread, mReceiveStreams,
mOperations, mTransceivers, mTransportIdToRTCDtlsTransport,
mSctpTransport, mLastStableSctpTransport, mLastStableSctpDtlsTransport,
mKungFuDeathGrip)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(PeerConnectionImpl)
NS_IMPL_CYCLE_COLLECTING_RELEASE(PeerConnectionImpl)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PeerConnectionImpl)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
already_AddRefed<PeerConnectionImpl> PeerConnectionImpl::Constructor(
const dom::GlobalObject& aGlobal) {
RefPtr<PeerConnectionImpl> pc =
new PeerConnectionImpl(&aGlobal);
CSFLogDebug(LOGTAG,
"Created PeerConnection: %p", pc.get());
return pc.forget();
}
JSObject* PeerConnectionImpl::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
return PeerConnectionImpl_Binding::Wrap(aCx,
this, aGivenProto);
}
nsPIDOMWindowInner* PeerConnectionImpl::GetParentObject()
const {
return mWindow;
}
bool PCUuidGenerator::Generate(std::string* idp) {
nsresult rv;
if (!mGenerator) {
mGenerator = do_GetService(
"@mozilla.org/uuid-generator;1", &rv);
if (NS_FAILED(rv)) {
return false;
}
if (!mGenerator) {
return false;
}
}
nsID id;
rv = mGenerator->GenerateUUIDInPlace(&id);
if (NS_FAILED(rv)) {
return false;
}
char buffer[NSID_LENGTH];
id.ToProvidedString(buffer);
idp->assign(buffer);
return true;
}
bool IsPrivateBrowsing(nsPIDOMWindowInner* aWindow) {
if (!aWindow) {
return false;
}
Document* doc = aWindow->GetExtantDoc();
if (!doc) {
return false;
}
nsILoadContext* loadContext = doc->GetLoadContext();
return loadContext && loadContext->UsePrivateBrowsing();
}
PeerConnectionImpl::PeerConnectionImpl(
const GlobalObject* aGlobal)
: mTimeCard(MOZ_LOG_TEST(logModuleInfo, LogLevel::Error) ? create_timecard()
: nullptr),
mSignalingState(RTCSignalingState::Stable),
mIceConnectionState(RTCIceConnectionState::
New),
mIceGatheringState(RTCIceGatheringState::
New),
mConnectionState(RTCPeerConnectionState::
New),
mWindow(do_QueryInterface(aGlobal ? aGlobal->GetAsSupports() : nullptr)),
mCertificate(nullptr),
mSTSThread(nullptr),
mForceIceTcp(
false),
mTransportHandler(nullptr),
mUuidGen(MakeUnique<PCUuidGenerator>()),
mIceRestartCount(
0),
mIceRollbackCount(
0),
mHaveConfiguredCodecs(
false),
mTrickle(
true)
// TODO(ekr@rtfm.com): Use pref
,
mPrivateWindow(
false),
mActiveOnWindow(
false),
mTimestampMaker(dom::RTCStatsTimestampMaker::Create(mWindow)),
mIdGenerator(
new RTCStatsIdGenerator()),
listenPort(
0),
connectPort(
0),
connectStr(nullptr) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT_IF(aGlobal, mWindow);
mKungFuDeathGrip =
this;
if (aGlobal) {
if (IsPrivateBrowsing(mWindow)) {
mPrivateWindow =
true;
mDisableLongTermStats =
true;
}
mWindow->AddPeerConnection();
mActiveOnWindow =
true;
if (mWindow->GetDocumentURI()) {
mWindow->GetDocumentURI()->GetAsciiHost(mHostname);
nsresult rv;
nsCOMPtr<nsIEffectiveTLDService> eTLDService(
do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID, &rv));
if (eTLDService) {
Unused << eTLDService->GetBaseDomain(mWindow->GetDocumentURI(),
0,
mEffectiveTLDPlus1);
}
mRtxIsAllowed = !media::HostnameInPref(
"media.peerconnection.video.use_rtx.blocklist", mHostname);
mDuplicateFingerprintQuirk = media::HostnameInPref(
"media.peerconnection.sdp.quirk.duplicate_fingerprint.allowlist",
mHostname);
}
}
if (!mUuidGen->Generate(&mHandle)) {
MOZ_CRASH();
}
CSFLogInfo(LOGTAG,
"%s: PeerConnectionImpl constructor for %s", __FUNCTION__,
mHandle.c_str());
STAMP_TIMECARD(mTimeCard,
"Constructor Completed");
mForceIceTcp =
Preferences::GetBool(
"media.peerconnection.ice.force_ice_tcp",
false);
memset(mMaxReceiving,
0,
sizeof(mMaxReceiving));
memset(mMaxSending,
0,
sizeof(mMaxSending));
mJsConfiguration.mCertificatesProvided =
false;
mJsConfiguration.mPeerIdentityProvided =
false;
}
PeerConnectionImpl::~PeerConnectionImpl() {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mTransportHandler,
"PeerConnection should either be closed, or not initted in the "
"first place.");
if (mTimeCard) {
STAMP_TIMECARD(mTimeCard,
"Destructor Invoked");
STAMP_TIMECARD(mTimeCard, mHandle.c_str());
print_timecard(mTimeCard);
destroy_timecard(mTimeCard);
mTimeCard = nullptr;
}
CSFLogInfo(LOGTAG,
"%s: PeerConnectionImpl destructor invoked for %s",
__FUNCTION__, mHandle.c_str());
}
nsresult PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver,
nsGlobalWindowInner* aWindow) {
nsresult res;
MOZ_ASSERT(NS_IsMainThread());
mPCObserver = &aObserver;
// Find the STS thread
mSTSThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &res);
MOZ_ASSERT(mSTSThread);
// We do callback handling on STS instead of main to avoid media jank.
// Someday, we may have a dedicated thread for this.
mTransportHandler = MediaTransportHandler::Create(mSTSThread);
if (mPrivateWindow) {
mTransportHandler->EnterPrivateMode();
}
// Initialize NSS if we are in content process. For chrome process, NSS should
// already been initialized.
if (XRE_IsParentProcess()) {
// This code interferes with the C++ unit test startup code.
nsCOMPtr<nsISupports> nssDummy = do_GetService(
"@mozilla.org/psm;1", &res);
NS_ENSURE_SUCCESS(res, res);
}
else {
NS_ENSURE_SUCCESS(res = InitNSSInContent(), res);
}
// Currently no standalone unit tests for DataChannel,
// which is the user of mWindow
MOZ_ASSERT(aWindow);
mWindow = aWindow;
NS_ENSURE_STATE(mWindow);
PRTime timestamp = PR_Now();
// Ok if we truncate this, but we want it to be large enough to reliably
// contain the location on the tests we run in CI.
char temp[
256];
nsAutoCString locationCStr;
RefPtr<Location> location = mWindow->Location();
res = location->GetHref(locationCStr);
NS_ENSURE_SUCCESS(res, res);
SprintfLiteral(temp,
"%s %" PRIu64
" (id=%" PRIu64
" url=%s)",
mHandle.c_str(),
static_cast<uint64_t>(timestamp),
static_cast<uint64_t>(mWindow ? mWindow->WindowID() :
0),
locationCStr.get() ? locationCStr.get() :
"NULL");
mName = temp;
STAMP_TIMECARD(mTimeCard,
"Initializing PC Ctx");
res = PeerConnectionCtx::InitializeGlobal();
NS_ENSURE_SUCCESS(res, res);
mTransportHandler->CreateIceCtx(
"PC:" + GetName());
mJsepSession =
MakeUnique<JsepSessionImpl>(mName, MakeUnique<PCUuidGenerator>());
mJsepSession->SetRtxIsAllowed(mRtxIsAllowed);
res = mJsepSession->Init();
if (NS_FAILED(res)) {
CSFLogError(LOGTAG,
"%s: Couldn't init JSEP Session, res=%u", __FUNCTION__,
static_cast<
unsigned>(res));
return res;
}
std::vector<UniquePtr<JsepCodecDescription>> preferredCodecs;
SetupPreferredCodecs(preferredCodecs);
mJsepSession->SetDefaultCodecs(preferredCodecs);
std::vector<RtpExtensionHeader> preferredHeaders;
SetupPreferredRtpExtensions(preferredHeaders);
for (
const auto& header : preferredHeaders) {
mJsepSession->AddRtpExtension(header.mMediaType, header.extensionname,
header.direction);
}
if (XRE_IsContentProcess()) {
mStunAddrsRequest =
new net::StunAddrsRequestChild(
new StunAddrsHandler(
this));
}
// Initialize the media object.
mForceProxy = ShouldForceProxy();
// We put this here, in case we later want to set this based on a non-standard
// param in RTCConfiguration.
mAllowOldSetParameters = Preferences::GetBool(
"media.peerconnection.allow_old_setParameters",
false);
// setup the stun local addresses IPC async call
InitLocalAddrs();
mSignalHandler = MakeUnique<SignalHandler>(
this, mTransportHandler.get());
PeerConnectionCtx::GetInstance()->AddPeerConnection(mHandle,
this);
return NS_OK;
}
void PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver,
nsGlobalWindowInner& aWindow,
ErrorResult& rv) {
MOZ_ASSERT(NS_IsMainThread());
nsresult res = Initialize(aObserver, &aWindow);
if (NS_FAILED(res)) {
rv.
Throw(res);
return;
}
}
void PeerConnectionImpl::SetCertificate(
mozilla::dom::RTCCertificate& aCertificate) {
PC_AUTO_ENTER_API_CALL_NO_CHECK();
MOZ_ASSERT(!mCertificate,
"This can only be called once");
mCertificate = &aCertificate;
std::vector<uint8_t> fingerprint;
nsresult rv =
CalculateFingerprint(DtlsIdentity::DEFAULT_HASH_ALGORITHM, &fingerprint);
if (NS_FAILED(rv)) {
CSFLogError(LOGTAG,
"%s: Couldn't calculate fingerprint, rv=%u",
__FUNCTION__,
static_cast<
unsigned>(rv));
mCertificate = nullptr;
return;
}
rv = mJsepSession->AddDtlsFingerprint(DtlsIdentity::DEFAULT_HASH_ALGORITHM,
fingerprint);
if (NS_FAILED(rv)) {
CSFLogError(LOGTAG,
"%s: Couldn't set DTLS credentials, rv=%u",
__FUNCTION__,
static_cast<
unsigned>(rv));
mCertificate = nullptr;
}
if (mUncommittedJsepSession) {
Unused << mUncommittedJsepSession->AddDtlsFingerprint(
DtlsIdentity::DEFAULT_HASH_ALGORITHM, fingerprint);
}
}
const RefPtr<mozilla::dom::RTCCertificate>& PeerConnectionImpl::Certificate()
const {
PC_AUTO_ENTER_API_CALL_NO_CHECK();
return mCertificate;
}
RefPtr<DtlsIdentity> PeerConnectionImpl::Identity()
const {
PC_AUTO_ENTER_API_CALL_NO_CHECK();
MOZ_ASSERT(mCertificate);
return mCertificate->CreateDtlsIdentity();
}
class CompareCodecPriority {
public:
void SetPreferredCodec(
const nsCString& preferredCodec) {
mPreferredCodec = preferredCodec;
}
bool operator()(
const UniquePtr<JsepCodecDescription>& lhs,
const UniquePtr<JsepCodecDescription>& rhs)
const {
// Do we have a preferred codec?
if (!mPreferredCodec.IsEmpty()) {
const bool lhsMatches = mPreferredCodec.EqualsIgnoreCase(lhs->mName) ||
mPreferredCodec.EqualsIgnoreCase(lhs->mDefaultPt);
const bool rhsMatches = mPreferredCodec.EqualsIgnoreCase(rhs->mName) ||
mPreferredCodec.EqualsIgnoreCase(rhs->mDefaultPt);
// If the only the left side matches, prefer it
if (lhsMatches && !rhsMatches) {
return true;
}
}
// If only the left side is strongly preferred, prefer it
return (lhs->mStronglyPreferred && !rhs->mStronglyPreferred);
}
private:
// The preferred codec name or PT number
nsCString mPreferredCodec;
};
class ConfigureCodec {
public:
explicit ConfigureCodec(nsCOMPtr<nsIPrefBranch>& branch)
: mHardwareH264Enabled(
false),
mSoftwareH264Enabled(
false),
mH264Enabled(
false),
mVP9Enabled(
true),
mVP9Preferred(
false),
mAV1Enabled(StaticPrefs::media_webrtc_codec_video_av1_enabled()),
mH264Level(
13),
// minimum suggested for WebRTC spec
mH264MaxBr(
0),
// Unlimited
mH264MaxMbps(
0),
// Unlimited
mVP8MaxFs(
0),
mVP8MaxFr(
0),
mUseTmmbr(
false),
mUseRemb(
false),
mUseTransportCC(
false),
mUseAudioFec(
false),
mRedUlpfecEnabled(
false) {
mSoftwareH264Enabled = PeerConnectionCtx::GetInstance()->gmpHasH264();
if (WebrtcVideoConduit::HasH264Hardware()) {
glean::webrtc::has_h264_hardware
.EnumGet(glean::webrtc::HasH264HardwareLabel::eTrue)
.Add();
branch->GetBoolPref(
"media.webrtc.hw.h264.enabled",
&mHardwareH264Enabled);
}
mH264Enabled = mHardwareH264Enabled || mSoftwareH264Enabled;
glean::webrtc::software_h264_enabled
.EnumGet(
static_cast<glean::webrtc::SoftwareH264EnabledLabel>(
mSoftwareH264Enabled))
.Add();
glean::webrtc::hardware_h264_enabled
.EnumGet(
static_cast<glean::webrtc::HardwareH264EnabledLabel>(
mHardwareH264Enabled))
.Add();
glean::webrtc::h264_enabled
.EnumGet(
static_cast<glean::webrtc::H264EnabledLabel>(mH264Enabled))
.Add();
branch->GetIntPref(
"media.navigator.video.h264.level", &mH264Level);
mH264Level &=
0xFF;
branch->GetIntPref(
"media.navigator.video.h264.max_br", &mH264MaxBr);
branch->GetIntPref(
"media.navigator.video.h264.max_mbps", &mH264MaxMbps);
branch->GetBoolPref(
"media.peerconnection.video.vp9_enabled", &mVP9Enabled);
branch->GetBoolPref(
"media.peerconnection.video.vp9_preferred",
&mVP9Preferred);
branch->GetIntPref(
"media.navigator.video.max_fs", &mVP8MaxFs);
if (mVP8MaxFs <=
0) {
mVP8MaxFs =
12288;
// We must specify something other than 0
}
branch->GetIntPref(
"media.navigator.video.max_fr", &mVP8MaxFr);
if (mVP8MaxFr <=
0) {
mVP8MaxFr =
60;
// We must specify something other than 0
}
// TMMBR is enabled from a pref in about:config
branch->GetBoolPref(
"media.navigator.video.use_tmmbr", &mUseTmmbr);
// REMB is enabled by default, but can be disabled from about:config
branch->GetBoolPref(
"media.navigator.video.use_remb", &mUseRemb);
branch->GetBoolPref(
"media.navigator.video.use_transport_cc",
&mUseTransportCC);
branch->GetBoolPref(
"media.navigator.audio.use_fec", &mUseAudioFec);
branch->GetBoolPref(
"media.navigator.video.red_ulpfec_enabled",
&mRedUlpfecEnabled);
}
void operator()(UniquePtr<JsepCodecDescription>& codec)
const {
switch (codec->Type()) {
case SdpMediaSection::kAudio: {
JsepAudioCodecDescription& audioCodec =
static_cast<JsepAudioCodecDescription&>(*codec);
if (audioCodec.mName ==
"opus") {
audioCodec.mFECEnabled = mUseAudioFec;
}
else if (audioCodec.mName ==
"telephone-event") {
audioCodec.mEnabled =
true;
}
}
break;
case SdpMediaSection::kVideo: {
JsepVideoCodecDescription& videoCodec =
static_cast<JsepVideoCodecDescription&>(*codec);
if (videoCodec.mName ==
"H264") {
// Override level but not for the pure Baseline codec
if (JsepVideoCodecDescription::GetSubprofile(
videoCodec.mProfileLevelId) ==
JsepVideoCodecDescription::kH264ConstrainedBaseline) {
videoCodec.mProfileLevelId &=
0xFFFF00;
videoCodec.mProfileLevelId |= mH264Level;
}
videoCodec.mConstraints.maxBr = mH264MaxBr;
videoCodec.mConstraints.maxMbps = mH264MaxMbps;
// Might disable it, but we set up other params anyway
videoCodec.mEnabled = mH264Enabled;
if (videoCodec.mPacketizationMode ==
0 && !mSoftwareH264Enabled) {
// We're assuming packetization mode 0 is unsupported by
// hardware.
videoCodec.mEnabled =
false;
}
}
else if (videoCodec.mName ==
"red") {
videoCodec.mEnabled = mRedUlpfecEnabled;
}
else if (videoCodec.mName ==
"ulpfec") {
videoCodec.mEnabled = mRedUlpfecEnabled;
}
else if (videoCodec.mName ==
"VP8" || videoCodec.mName ==
"VP9") {
if (videoCodec.mName ==
"VP9") {
if (!mVP9Enabled) {
videoCodec.mEnabled =
false;
break;
}
if (mVP9Preferred) {
videoCodec.mStronglyPreferred =
true;
}
}
videoCodec.mConstraints.maxFs = mVP8MaxFs;
videoCodec.mConstraints.maxFps = Some(mVP8MaxFr);
}
else if (videoCodec.mName ==
"AV1") {
videoCodec.mEnabled = mAV1Enabled;
}
if (mUseTmmbr) {
videoCodec.EnableTmmbr();
}
if (mUseRemb) {
videoCodec.EnableRemb();
}
if (mUseTransportCC) {
videoCodec.EnableTransportCC();
}
}
break;
case SdpMediaSection::kText:
case SdpMediaSection::kApplication:
case SdpMediaSection::kMessage: {
}
// Nothing to configure for these.
}
}
private:
bool mHardwareH264Enabled;
bool mSoftwareH264Enabled;
bool mH264Enabled;
bool mVP9Enabled;
bool mVP9Preferred;
bool mAV1Enabled;
int32_t mH264Level;
int32_t mH264MaxBr;
int32_t mH264MaxMbps;
int32_t mVP8MaxFs;
int32_t mVP8MaxFr;
bool mUseTmmbr;
bool mUseRemb;
bool mUseTransportCC;
bool mUseAudioFec;
bool mRedUlpfecEnabled;
};
nsresult PeerConnectionImpl::ConfigureJsepSessionCodecs() {
nsresult res;
nsCOMPtr<nsIPrefService> prefs =
do_GetService(
"@mozilla.org/preferences-service;1", &res);
if (NS_FAILED(res)) {
CSFLogError(LOGTAG,
"%s: Couldn't get prefs service, res=%u", __FUNCTION__,
static_cast<
unsigned>(res));
return res;
}
nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
if (!branch) {
CSFLogError(LOGTAG,
"%s: Couldn't get prefs branch", __FUNCTION__);
return NS_ERROR_FAILURE;
}
ConfigureCodec configurer(branch);
mJsepSession->ForEachCodec(configurer);
// We use this to sort the list of codecs once everything is configured
CompareCodecPriority comparator;
if (StaticPrefs::media_webrtc_codec_video_av1_experimental_preferred()) {
comparator.SetPreferredCodec(nsCString(
"av1"));
}
// Sort by priority
mJsepSession->SortCodecs(comparator);
return NS_OK;
}
// Data channels won't work without a window, so in order for the C++ unit
// tests to work (it doesn't have a window available) we ifdef the following
// two implementations.
//
// Note: 'media.peerconnection.sctp.force_maximum_message_size' changes
// behaviour triggered by these parameters.
NS_IMETHODIMP
PeerConnectionImpl::EnsureDataConnection(uint16_t aLocalPort,
uint16_t aNumstreams,
uint32_t aMaxMessageSize,
bool aMMSSet) {
PC_AUTO_ENTER_API_CALL(
false);
if (mDataConnection) {
CSFLogDebug(LOGTAG,
"%s DataConnection already connected", __FUNCTION__);
mDataConnection->SetMaxMessageSize(aMMSSet, aMaxMessageSize);
return NS_OK;
}
nsCOMPtr<nsISerialEventTarget> target = GetMainThreadSerialEventTarget();
Maybe<uint64_t> mms = aMMSSet ? Some(aMaxMessageSize) : Nothing();
if (
auto res = DataChannelConnection::Create(
this, target, mTransportHandler,
aLocalPort, aNumstreams, mms)) {
mDataConnection = res.value();
CSFLogDebug(LOGTAG,
"%s DataChannelConnection %p attached to %s",
__FUNCTION__, (
void*)mDataConnection.get(), mHandle.c_str());
return NS_OK;
}
CSFLogError(LOGTAG,
"%s DataConnection Create Failed", __FUNCTION__);
return NS_ERROR_FAILURE;
}
nsresult PeerConnectionImpl::GetDatachannelParameters(
uint32_t* channels, uint16_t* localport, uint16_t* remoteport,
uint32_t* remotemaxmessagesize,
bool* mmsset, std::string* transportId,
bool* client)
const {
// Clear, just in case we fail.
*channels =
0;
*localport =
0;
*remoteport =
0;
*remotemaxmessagesize =
0;
*mmsset =
false;
transportId->clear();
Maybe<
const JsepTransceiver> datachannelTransceiver =
mJsepSession->FindTransceiver([](
const JsepTransceiver& aTransceiver) {
return aTransceiver.GetMediaType() == SdpMediaSection::kApplication;
});
if (!datachannelTransceiver ||
!datachannelTransceiver->mTransport.mComponents ||
!datachannelTransceiver->mTransport.mDtls ||
!datachannelTransceiver->mSendTrack.GetNegotiatedDetails()) {
return NS_ERROR_FAILURE;
}
// This will release assert if there is no such index, and that's ok
const JsepTrackEncoding& encoding =
datachannelTransceiver->mSendTrack.GetNegotiatedDetails()->GetEncoding(
0);
if (NS_WARN_IF(encoding.GetCodecs().empty())) {
CSFLogError(LOGTAG,
"%s: Negotiated m=application with no codec. "
"This is likely to be broken.",
__FUNCTION__);
return NS_ERROR_FAILURE;
}
for (
const auto& codec : encoding.GetCodecs()) {
if (codec->Type() != SdpMediaSection::kApplication) {
CSFLogError(LOGTAG,
"%s: Codec type for m=application was %u, this "
"is a bug.",
__FUNCTION__,
static_cast<
unsigned>(codec->Type()));
MOZ_ASSERT(
false,
"Codec for m=application was not \"application\
"");
return NS_ERROR_FAILURE;
}
if (codec->mName !=
"webrtc-datachannel") {
CSFLogWarn(LOGTAG,
"%s: Codec for m=application was not "
"webrtc-datachannel (was instead %s). ",
__FUNCTION__, codec->mName.c_str());
continue;
}
if (codec->mChannels) {
*channels = codec->mChannels;
}
else {
*channels = WEBRTC_DATACHANNEL_STREAMS_DEFAULT;
}
const JsepApplicationCodecDescription* appCodec =
static_cast<
const JsepApplicationCodecDescription*>(codec.get());
*localport = appCodec->mLocalPort;
*remoteport = appCodec->mRemotePort;
*remotemaxmessagesize = appCodec->mRemoteMaxMessageSize;
*mmsset = appCodec->mRemoteMMSSet;
MOZ_ASSERT(!datachannelTransceiver->mTransport.mTransportId.empty());
*transportId = datachannelTransceiver->mTransport.mTransportId;
*client = datachannelTransceiver->mTransport.mDtls->GetRole() ==
JsepDtlsTransport::kJsepDtlsClient;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
nsresult PeerConnectionImpl::AddRtpTransceiverToJsepSession(
JsepTransceiver& transceiver) {
nsresult res = ConfigureJsepSessionCodecs();
if (NS_FAILED(res)) {
CSFLogError(LOGTAG,
"Failed to configure codecs");
return res;
}
mJsepSession->AddTransceiver(transceiver);
return NS_OK;
}
static Maybe<SdpMediaSection::MediaType> ToSdpMediaType(
const nsAString& aKind) {
if (aKind.EqualsASCII(
"audio")) {
return Some(SdpMediaSection::MediaType::kAudio);
}
else if (aKind.EqualsASCII(
"video")) {
return Some(SdpMediaSection::MediaType::kVideo);
}
return Nothing();
}
already_AddRefed<RTCRtpTransceiver> PeerConnectionImpl::AddTransceiver(
const dom::RTCRtpTransceiverInit& aInit,
const nsAString& aKind,
dom::MediaStreamTrack* aSendTrack,
bool aAddTrackMagic, ErrorResult& aRv) {
// Copy, because we might need to modify
RTCRtpTransceiverInit init(aInit);
Maybe<SdpMediaSection::MediaType> type = ToSdpMediaType(aKind);
if (NS_WARN_IF(!type.isSome())) {
MOZ_ASSERT(
false,
"Invalid media kind");
aRv = NS_ERROR_INVALID_ARG;
return nullptr;
}
JsepTransceiver jsepTransceiver(*type, *mUuidGen);
jsepTransceiver.SetRtxIsAllowed(mRtxIsAllowed);
// Do this last, since it is not possible to roll back.
nsresult rv = AddRtpTransceiverToJsepSession(jsepTransceiver);
if (NS_FAILED(rv)) {
CSFLogError(LOGTAG,
"%s: AddRtpTransceiverToJsepSession failed, res=%u",
__FUNCTION__,
static_cast<
unsigned>(rv));
aRv = rv;
return nullptr;
}
auto& sendEncodings = init.mSendEncodings;
// CheckAndRectifyEncodings covers these six:
// If any encoding contains a rid member whose value does not conform to the
// grammar requirements specified in Section 10 of [RFC8851], throw a
// TypeError.
// If some but not all encodings contain a rid member, throw a TypeError.
// If any encoding contains a rid member whose value is the same as that of a
// rid contained in another encoding in sendEncodings, throw a TypeError.
// If kind is "audio", remove the scaleResolutionDownBy member from all
// encodings that contain one.
// If any encoding contains a scaleResolutionDownBy member whose value is
// less than 1.0, throw a RangeError.
// Verify that the value of each maxFramerate member in sendEncodings that is
// defined is greater than 0.0. If one of the maxFramerate values does not
// meet this requirement, throw a RangeError.
RTCRtpSender::CheckAndRectifyEncodings(sendEncodings,
*type == SdpMediaSection::kVideo, aRv);
if (aRv.Failed()) {
return nullptr;
}
// If any encoding contains a read-only parameter other than rid, throw an
// InvalidAccessError.
// NOTE: We don't support any additional read-only params right now. Also,
// spec shoehorns this in between checks that setParameters also performs
// (between the rid checks and the scaleResolutionDownBy checks).
// If any encoding contains a scaleResolutionDownBy member, then for each
// encoding without one, add a scaleResolutionDownBy member with the value
// 1.0.
for (
const auto& constEncoding : sendEncodings) {
if (constEncoding.mScaleResolutionDownBy.WasPassed()) {
for (
auto& encoding : sendEncodings) {
if (!encoding.mScaleResolutionDownBy.WasPassed()) {
encoding.mScaleResolutionDownBy.Construct(
1.
0f);
}
}
break;
}
}
// Let maxN be the maximum number of total simultaneous encodings the user
// agent may support for this kind, at minimum 1.This should be an optimistic
// number since the codec to be used is not known yet.
size_t maxN =
(*type == SdpMediaSection::kVideo) ? webrtc::kMaxSimulcastStreams :
1;
// If the number of encodings stored in sendEncodings exceeds maxN, then trim
// sendEncodings from the tail until its length is maxN.
// NOTE: Spec has this after all validation steps; even if there are elements
// that we will trim off, we still validate them.
if (sendEncodings.Length() > maxN) {
sendEncodings.TruncateLength(maxN);
}
// If kind is "video" and none of the encodings contain a
// scaleResolutionDownBy member, then for each encoding, add a
// scaleResolutionDownBy member with the value 2^(length of sendEncodings -
// encoding index - 1). This results in smaller-to-larger resolutions where
// the last encoding has no scaling applied to it, e.g. 4:2:1 if the length
// is 3.
// NOTE: The code above ensures that these are all set, or all unset, so we
// can just check the first one.
if (sendEncodings.Length() && *type == SdpMediaSection::kVideo &&
!sendEncodings[
0].mScaleResolutionDownBy.WasPassed()) {
double scale =
1.
0f;
for (
auto it = sendEncodings.rbegin(); it != sendEncodings.rend(); ++it) {
it->mScaleResolutionDownBy.Construct(scale);
scale *=
2;
}
}
// If the number of encodings now stored in sendEncodings is 1, then remove
// any rid member from the lone entry.
if (sendEncodings.Length() ==
1) {
sendEncodings[
0].mRid.Reset();
}
RefPtr<RTCRtpTransceiver> transceiver = CreateTransceiver(
jsepTransceiver.GetUuid(),
jsepTransceiver.GetMediaType() == SdpMediaSection::kVideo, init,
aSendTrack, aAddTrackMagic, aRv);
if (aRv.Failed()) {
// Would be nice if we could peek at the rv without stealing it, so we
// could log...
CSFLogError(LOGTAG,
"%s: failed", __FUNCTION__);
return nullptr;
}
mTransceivers.AppendElement(transceiver);
return transceiver.forget();
}
bool PeerConnectionImpl::CheckNegotiationNeeded() {
MOZ_ASSERT(mSignalingState == RTCSignalingState::Stable);
SyncToJsep();
return !mLocalIceCredentialsToReplace.empty() ||
mJsepSession->CheckNegotiationNeeded();
}
bool PeerConnectionImpl::CreatedSender(
const dom::RTCRtpSender& aSender)
const {
return aSender.IsMyPc(
this);
}
nsresult PeerConnectionImpl::MaybeInitializeDataChannel() {
PC_AUTO_ENTER_API_CALL(
false);
CSFLogDebug(LOGTAG,
"%s", __FUNCTION__);
uint32_t channels =
0;
uint16_t localport =
0;
uint16_t remoteport =
0;
uint32_t remotemaxmessagesize =
0;
bool mmsset =
false;
std::string transportId;
bool client =
false;
nsresult rv = GetDatachannelParameters(&channels, &localport, &remoteport,
&remotemaxmessagesize, &mmsset,
&transportId, &client);
if (NS_FAILED(rv)) {
CSFLogDebug(LOGTAG,
"%s: We did not negotiate datachannel", __FUNCTION__);
return NS_OK;
}
if (channels > MAX_NUM_STREAMS) {
channels = MAX_NUM_STREAMS;
}
rv = EnsureDataConnection(localport, channels, remotemaxmessagesize, mmsset);
if (NS_SUCCEEDED(rv)) {
if (mDataConnection->ConnectToTransport(transportId, client, localport,
remoteport)) {
return NS_OK;
}
// If we inited the DataConnection, call Destroy() before releasing it
mDataConnection->Destroy();
}
mDataConnection = nullptr;
return NS_ERROR_FAILURE;
}
already_AddRefed<nsDOMDataChannel> PeerConnectionImpl::CreateDataChannel(
const nsAString& aLabel,
const nsAString& aProtocol, uint16_t aType,
bool ordered, uint16_t aMaxTime, uint16_t aMaxNum,
bool aExternalNegotiated,
uint16_t aStream, ErrorResult& rv) {
RefPtr<nsDOMDataChannel> result;
rv = CreateDataChannel(aLabel, aProtocol, aType, ordered, aMaxTime, aMaxNum,
aExternalNegotiated, aStream, getter_AddRefs(result));
return result.forget();
}
NS_IMETHODIMP
PeerConnectionImpl::CreateDataChannel(
const nsAString& aLabel,
const nsAString& aProtocol, uint16_t aType,
bool ordered, uint16_t aMaxTime, uint16_t aMaxNum,
bool aExternalNegotiated,
uint16_t aStream, nsDOMDataChannel** aRetval) {
PC_AUTO_ENTER_API_CALL(
false);
MOZ_ASSERT(aRetval);
RefPtr<DataChannel> dataChannel;
DataChannelReliabilityPolicy prPolicy;
switch (aType) {
case IPeerConnection::kDataChannelReliable:
prPolicy = DataChannelReliabilityPolicy::Reliable;
break;
case IPeerConnection::kDataChannelPartialReliableRexmit:
prPolicy = DataChannelReliabilityPolicy::LimitedRetransmissions;
break;
case IPeerConnection::kDataChannelPartialReliableTimed:
prPolicy = DataChannelReliabilityPolicy::LimitedLifetime;
break;
default:
MOZ_ASSERT(
false);
return NS_ERROR_FAILURE;
}
nsresult rv = EnsureDataConnection(
WEBRTC_DATACHANNEL_PORT_DEFAULT, WEBRTC_DATACHANNEL_STREAMS_DEFAULT,
WEBRTC_DATACHANNEL_MAX_MESSAGE_SIZE_REMOTE_DEFAULT,
false);
if (NS_FAILED(rv)) {
return rv;
}
dataChannel = mDataConnection->Open(
NS_ConvertUTF16toUTF8(aLabel), NS_ConvertUTF16toUTF8(aProtocol), prPolicy,
ordered,
prPolicy == DataChannelReliabilityPolicy::LimitedRetransmissions
? aMaxNum
: (prPolicy == DataChannelReliabilityPolicy::LimitedLifetime
? aMaxTime
:
0),
nullptr, nullptr, aExternalNegotiated, aStream);
NS_ENSURE_TRUE(dataChannel, NS_ERROR_NOT_AVAILABLE);
CSFLogDebug(LOGTAG,
"%s: making DOMDataChannel", __FUNCTION__);
Maybe<JsepTransceiver> dcTransceiver =
mJsepSession->FindTransceiver([](
const JsepTransceiver& aTransceiver) {
return aTransceiver.GetMediaType() == SdpMediaSection::kApplication;
});
if (dcTransceiver) {
dcTransceiver->RestartDatachannelTransceiver();
mJsepSession->SetTransceiver(*dcTransceiver);
}
else {
mJsepSession->AddTransceiver(
JsepTransceiver(SdpMediaSection::MediaType::kApplication, *mUuidGen));
}
RefPtr<nsDOMDataChannel> retval;
rv = NS_NewDOMDataChannel(dataChannel.forget(), mWindow,
getter_AddRefs(retval));
if (NS_FAILED(rv)) {
return rv;
}
retval.forget(aRetval);
return NS_OK;
}
NS_IMPL_CYCLE_COLLECTION(PeerConnectionImpl::Operation, mPromise, mPc)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PeerConnectionImpl::Operation)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(PeerConnectionImpl::Operation)
NS_IMPL_CYCLE_COLLECTING_RELEASE(PeerConnectionImpl::Operation)
PeerConnectionImpl::Operation::Operation(PeerConnectionImpl* aPc,
ErrorResult& aError)
: mPromise(aPc->MakePromise(aError)), mPc(aPc) {}
PeerConnectionImpl::Operation::~Operation() =
default;
void PeerConnectionImpl::Operation::Call(ErrorResult& aError) {
RefPtr<dom::Promise> opPromise = CallImpl(aError);
if (aError.Failed()) {
return;
}
// Upon fulfillment or rejection of the promise returned by the operation,
// run the following steps:
// (NOTE: mPromise is p from https://w3c.github.io/webrtc-pc/#dfn-chain,
// and CallImpl() is what returns the promise for the operation itself)
opPromise->AppendNativeHandler(
this);
}
void PeerConnectionImpl::Operation::ResolvedCallback(
JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv) {
// If connection.[[IsClosed]] is true, abort these steps.
// (the spec wants p to never settle in this event)
if (!mPc->IsClosed()) {
// If the promise returned by operation was fulfilled with a
// value, fulfill p with that value.
mPromise->MaybeResolveWithClone(aCx, aValue);
// Upon fulfillment or rejection of p, execute the following
// steps:
// (Static analysis forces us to use a temporary)
RefPtr<PeerConnectionImpl> pc = mPc;
pc->RunNextOperation(aRv);
}
}
void PeerConnectionImpl::Operation::RejectedCallback(
JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv) {
// If connection.[[IsClosed]] is true, abort these steps.
// (the spec wants p to never settle in this event)
if (!mPc->IsClosed()) {
// If the promise returned by operation was rejected with a
// value, reject p with that value.
mPromise->MaybeRejectWithClone(aCx, aValue);
// Upon fulfillment or rejection of p, execute the following
// steps:
// (Static analysis forces us to use a temporary)
RefPtr<PeerConnectionImpl> pc = mPc;
pc->RunNextOperation(aRv);
}
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(PeerConnectionImpl::JSOperation,
PeerConnectionImpl::Operation, mOperation)
NS_IMPL_ADDREF_INHERITED(PeerConnectionImpl::JSOperation,
PeerConnectionImpl::Operation)
NS_IMPL_RELEASE_INHERITED(PeerConnectionImpl::JSOperation,
PeerConnectionImpl::Operation)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PeerConnectionImpl::JSOperation)
NS_INTERFACE_MAP_END_INHERITING(PeerConnectionImpl::Operation)
PeerConnectionImpl::JSOperation::JSOperation(PeerConnectionImpl* aPc,
dom::ChainedOperation& aOp,
ErrorResult& aError)
: Operation(aPc, aError), mOperation(&aOp) {}
RefPtr<dom::Promise> PeerConnectionImpl::JSOperation::CallImpl(
ErrorResult& aError) {
// Static analysis will not let us call this without a temporary :(
RefPtr<dom::ChainedOperation> op = mOperation;
return op->Call(aError);
}
already_AddRefed<dom::Promise> PeerConnectionImpl::Chain(
dom::ChainedOperation& aOperation, ErrorResult& aError) {
MOZ_RELEASE_ASSERT(!mChainingOperation);
mChainingOperation =
true;
RefPtr<Operation> operation =
new JSOperation(
this, aOperation, aError);
if (aError.Failed()) {
return nullptr;
}
RefPtr<Promise> promise = Chain(operation, aError);
if (aError.Failed()) {
return nullptr;
}
mChainingOperation =
false;
return promise.forget();
}
// This is kinda complicated, but it is what the spec requires us to do. The
// core of what makes this complicated is the requirement that |aOperation| be
// run _immediately_ (without any Promise.Then!) if the operations chain is
// empty.
already_AddRefed<dom::Promise> PeerConnectionImpl::Chain(
const RefPtr<Operation>& aOperation, ErrorResult& aError) {
// If connection.[[IsClosed]] is true, return a promise rejected with a newly
// created InvalidStateError.
if (IsClosed()) {
CSFLogDebug(LOGTAG,
"%s:%d: Peer connection is closed", __FILE__, __LINE__);
RefPtr<dom::Promise> error = MakePromise(aError);
if (aError.Failed()) {
return nullptr;
}
error->MaybeRejectWithInvalidStateError(
"Peer connection is closed");
return error.forget();
}
// Append operation to [[Operations]].
mOperations.AppendElement(aOperation);
// If the length of [[Operations]] is exactly 1, execute operation.
if (mOperations.Length() ==
1) {
aOperation->Call(aError);
if (aError.Failed()) {
return nullptr;
}
}
// This is the promise p from https://w3c.github.io/webrtc-pc/#dfn-chain
return do_AddRef(aOperation->GetPromise());
}
void PeerConnectionImpl::RunNextOperation(ErrorResult& aError) {
// If connection.[[IsClosed]] is true, abort these steps.
if (IsClosed()) {
return;
}
// Remove the first element of [[Operations]].
mOperations.RemoveElementAt(
0);
// If [[Operations]] is non-empty, execute the operation represented by the
// first element of [[Operations]], and abort these steps.
if (mOperations.Length()) {
// Cannot call without a temporary :(
RefPtr<Operation> op = mOperations[
0];
op->Call(aError);
return;
}
// If connection.[[UpdateNegotiationNeededFlagOnEmptyChain]] is false, abort
// these steps.
if (!mUpdateNegotiationNeededFlagOnEmptyChain) {
return;
}
// Set connection.[[UpdateNegotiationNeededFlagOnEmptyChain]] to false.
mUpdateNegotiationNeededFlagOnEmptyChain =
false;
// Update the negotiation-needed flag for connection.
UpdateNegotiationNeeded();
}
void PeerConnectionImpl::SyncToJsep() {
for (
const auto& transceiver : mTransceivers) {
transceiver->SyncToJsep(*mJsepSession);
}
}
void PeerConnectionImpl::SyncFromJsep() {
CSFLogDebug(LOGTAG,
"%s", __FUNCTION__);
mJsepSession->ForEachTransceiver(
[
this, self = RefPtr<PeerConnectionImpl>(
this)](
const JsepTransceiver& jsepTransceiver) {
if (jsepTransceiver.GetMediaType() ==
SdpMediaSection::MediaType::kApplication) {
return;
}
CSFLogDebug(LOGTAG,
"%s: Looking for match", __FUNCTION__);
RefPtr<RTCRtpTransceiver> transceiver;
for (
auto& temp : mTransceivers) {
if (temp->GetJsepTransceiverId() == jsepTransceiver.GetUuid()) {
CSFLogDebug(LOGTAG,
"%s: Found match", __FUNCTION__);
transceiver = temp;
break;
}
}
if (!transceiver) {
if (jsepTransceiver.IsRemoved()) {
return;
}
CSFLogDebug(LOGTAG,
"%s: No match, making new", __FUNCTION__);
dom::RTCRtpTransceiverInit init;
init.mDirection = RTCRtpTransceiverDirection::Recvonly;
IgnoredErrorResult rv;
transceiver = CreateTransceiver(
jsepTransceiver.GetUuid(),
jsepTransceiver.GetMediaType() == SdpMediaSection::kVideo, init,
nullptr,
false, rv);
if (NS_WARN_IF(rv.Failed())) {
MOZ_ASSERT(
false);
return;
}
mTransceivers.AppendElement(transceiver);
}
CSFLogDebug(LOGTAG,
"%s: Syncing transceiver", __FUNCTION__);
transceiver->SyncFromJsep(*mJsepSession);
});
}
already_AddRefed<dom::Promise> PeerConnectionImpl::MakePromise(
ErrorResult& aError)
const {
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);
return dom::Promise::Create(global, aError);
}
void PeerConnectionImpl::UpdateNegotiationNeeded() {
// If the length of connection.[[Operations]] is not 0, then set
// connection.[[UpdateNegotiationNeededFlagOnEmptyChain]] to true, and abort
// these steps.
if (mOperations.Length() !=
0) {
mUpdateNegotiationNeededFlagOnEmptyChain =
true;
return;
}
// Queue a task to run the following steps:
GetMainThreadSerialEventTarget()->Dispatch(NS_NewRunnableFunction(
__func__, [
this, self = RefPtr<PeerConnectionImpl>(
this)] {
// If connection.[[IsClosed]] is true, abort these steps.
if (IsClosed()) {
return;
}
// If the length of connection.[[Operations]] is not 0, then set
// connection.[[UpdateNegotiationNeededFlagOnEmptyChain]] to true, and
// abort these steps.
if (mOperations.Length()) {
mUpdateNegotiationNeededFlagOnEmptyChain =
true;
return;
}
// If connection's signaling state is not "stable", abort these steps.
if (mSignalingState != RTCSignalingState::Stable) {
return;
}
// If the result of checking if negotiation is needed is false, clear
// the negotiation-needed flag by setting
// connection.[[NegotiationNeeded]] to false, and abort these steps.
if (!CheckNegotiationNeeded()) {
mNegotiationNeeded =
false;
return;
}
// If connection.[[NegotiationNeeded]] is already true, abort these
// steps.
if (mNegotiationNeeded) {
return;
}
// Set connection.[[NegotiationNeeded]] to true.
mNegotiationNeeded =
true;
// Fire an event named negotiationneeded at connection.
ErrorResult rv;
mPCObserver->FireNegotiationNeededEvent(rv);
}));
}
RefPtr<dom::RTCRtpTransceiver> PeerConnectionImpl::GetTransceiver(
const std::string& aTransceiverId) {
for (
const auto& transceiver : mTransceivers) {
if (transceiver->GetJsepTransceiverId() == aTransceiverId) {
return transceiver;
}
}
return nullptr;
}
void PeerConnectionImpl::NotifyDataChannel(
already_AddRefed<DataChannel> aChannel) {
PC_AUTO_ENTER_API_CALL_NO_CHECK();
RefPtr<DataChannel> channel(aChannel);
MOZ_ASSERT(channel);
CSFLogDebug(LOGTAG,
"%s: channel: %p", __FUNCTION__, channel.get());
RefPtr<nsDOMDataChannel> domchannel;
nsresult rv = NS_NewDOMDataChannel(channel.forget(), mWindow,
getter_AddRefs(domchannel));
NS_ENSURE_SUCCESS_VOID(rv);
JSErrorResult jrv;
mPCObserver->NotifyDataChannel(*domchannel, jrv);
}
void PeerConnectionImpl::NotifyDataChannelOpen(DataChannel*) {
mDataChannelsOpened++;
}
void PeerConnectionImpl::NotifyDataChannelClosed(DataChannel*) {
mDataChannelsClosed++;
}
void PeerConnectionImpl::NotifySctpConnected() {
if (!mSctpTransport) {
MOZ_ASSERT(
false);
return;
}
mSctpTransport->UpdateState(RTCSctpTransportState::Connected);
}
void PeerConnectionImpl::NotifySctpClosed() {
if (!mSctpTransport) {
MOZ_ASSERT(
false);
return;
}
mSctpTransport->UpdateState(RTCSctpTransportState::Closed);
}
NS_IMETHODIMP
PeerConnectionImpl::CreateOffer(
const RTCOfferOptions& aOptions) {
JsepOfferOptions options;
// convert the RTCOfferOptions to JsepOfferOptions
if (aOptions.mOfferToReceiveAudio.WasPassed()) {
options.mOfferToReceiveAudio =
mozilla::Some(size_t(aOptions.mOfferToReceiveAudio.Value()));
}
if (aOptions.mOfferToReceiveVideo.WasPassed()) {
options.mOfferToReceiveVideo =
mozilla::Some(size_t(aOptions.mOfferToReceiveVideo.Value()));
}
options.mIceRestart = mozilla::Some(aOptions.mIceRestart ||
!mLocalIceCredentialsToReplace.empty());
return CreateOffer(options);
}
static void DeferredCreateOffer(
const std::string& aPcHandle,
const JsepOfferOptions& aOptions) {
PeerConnectionWrapper wrapper(aPcHandle);
if (wrapper.impl()) {
if (!PeerConnectionCtx::GetInstance()->isReady()) {
MOZ_CRASH(
"Why is DeferredCreateOffer being executed when the "
"PeerConnectionCtx isn't ready?");
}
wrapper.impl()->CreateOffer(aOptions);
}
}
// Have to use unique_ptr because webidl enums are generated without a
// copy c'tor.
static std::unique_ptr<dom::PCErrorData> buildJSErrorData(
const JsepSession::Result& aResult,
const std::string& aMessage) {
std::unique_ptr<dom::PCErrorData> result(
new dom::PCErrorData);
result->mName = *aResult.mError;
result->mMessage = NS_ConvertASCIItoUTF16(aMessage.c_str());
return result;
}
// Used by unit tests and the IDL CreateOffer.
NS_IMETHODIMP
PeerConnectionImpl::CreateOffer(
const JsepOfferOptions& aOptions) {
PC_AUTO_ENTER_API_CALL(
true);
if (!PeerConnectionCtx::GetInstance()->isReady()) {
// Uh oh. We're not ready yet. Enqueue this operation.
PeerConnectionCtx::GetInstance()->queueJSEPOperation(
WrapRunnableNM(DeferredCreateOffer, mHandle, aOptions));
STAMP_TIMECARD(mTimeCard,
"Deferring CreateOffer (not ready)");
return NS_OK;
}
CSFLogDebug(LOGTAG,
"CreateOffer()");
nsresult nrv = ConfigureJsepSessionCodecs();
if (NS_FAILED(nrv)) {
CSFLogError(LOGTAG,
"Failed to configure codecs");
return nrv;
}
STAMP_TIMECARD(mTimeCard,
"Create Offer");
GetMainThreadSerialEventTarget()->Dispatch(NS_NewRunnableFunction(
__func__, [
this, self = RefPtr<PeerConnectionImpl>(
this), aOptions] {
std::string offer;
SyncToJsep();
UniquePtr<JsepSession> uncommittedJsepSession(mJsepSession->Clone());
JsepSession::Result result =
uncommittedJsepSession->CreateOffer(aOptions, &offer);
JSErrorResult rv;
if (result.mError.isSome()) {
std::string errorString = uncommittedJsepSession->GetLastError();
CSFLogError(LOGTAG,
"%s: pc = %s, error = %s", __FUNCTION__,
mHandle.c_str(), errorString.c_str());
mPCObserver->OnCreateOfferError(
*buildJSErrorData(result, errorString), rv);
}
else {
mJsepSession = std::move(uncommittedJsepSession);
mPCObserver->OnCreateOfferSuccess(ObString(offer.c_str()), rv);
}
}));
return NS_OK;
}
NS_IMETHODIMP
PeerConnectionImpl::CreateAnswer() {
PC_AUTO_ENTER_API_CALL(
true);
CSFLogDebug(LOGTAG,
"CreateAnswer()");
STAMP_TIMECARD(mTimeCard,
"Create Answer");
// TODO(bug 1098015): Once RTCAnswerOptions is standardized, we'll need to
// add it as a param to CreateAnswer, and convert it here.
JsepAnswerOptions options;
GetMainThreadSerialEventTarget()->Dispatch(NS_NewRunnableFunction(
__func__, [
this, self = RefPtr<PeerConnectionImpl>(
this), options] {
std::string answer;
SyncToJsep();
UniquePtr<JsepSession> uncommittedJsepSession(mJsepSession->Clone());
JsepSession::Result result =
uncommittedJsepSession->CreateAnswer(options, &answer);
JSErrorResult rv;
if (result.mError.isSome()) {
std::string errorString = uncommittedJsepSession->GetLastError();
CSFLogError(LOGTAG,
"%s: pc = %s, error = %s", __FUNCTION__,
mHandle.c_str(), errorString.c_str());
mPCObserver->OnCreateAnswerError(
*buildJSErrorData(result, errorString), rv);
}
else {
mJsepSession = std::move(uncommittedJsepSession);
mPCObserver->OnCreateAnswerSuccess(ObString(answer.c_str()), rv);
}
}));
return NS_OK;
}
dom::RTCSdpType ToDomSdpType(JsepSdpType aType) {
switch (aType) {
case kJsepSdpOffer:
return dom::RTCSdpType::Offer;
case kJsepSdpAnswer:
return dom::RTCSdpType::Answer;
case kJsepSdpPranswer:
return dom::RTCSdpType::Pranswer;
case kJsepSdpRollback:
return dom::RTCSdpType::Rollback;
}
MOZ_CRASH(
"Nonexistent JsepSdpType");
}
JsepSdpType ToJsepSdpType(dom::RTCSdpType aType) {
switch (aType) {
case dom::RTCSdpType::Offer:
return kJsepSdpOffer;
case dom::RTCSdpType::Pranswer:
return kJsepSdpPranswer;
case dom::RTCSdpType::Answer:
return kJsepSdpAnswer;
case dom::RTCSdpType::Rollback:
return kJsepSdpRollback;
}
MOZ_CRASH
# >
NS_IMETHODIMP
:SetLocalDescription ,
constcharaSDP
include/.java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for l
ength 39
#mozillaDomMediaWebrtcMetrics
CSFLogErrorinclude.
returnjava.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
}
STAMP_TIMECARD(mTimeCard, "include"/RTCRtpReceiverBindingjava.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
(()) {
mRequestedPrivacy = Some(PrincipalPrivacy::Private".h
}
mozillaJsepTransport
. true
sdpEntry// got imported after we included mozilla/dom/Document.h
sdpEntryincludeMediaSegment
auto appendHistoryinclude//PeerConnectionObserverBinding
if!.AppendElementsdpEntryfallible{
mozalloc_handle_oom(0);
}
# java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
mLocalRequestedSDP = aSDP;
SyncToJsep JSErrorResult : binding_danger:TErrorResult
JsepSdpType sdpType;
switch// ErrorResult, but creating a new one instead, which works because we don't
case public
sdpType = mozilla::kJsepSdpOffer;
break
case :kActionAnswer
sdpType
break;
case IPeerConnection::kActionPRAnswer:
sdpType = mozilla::kJsepSdpPranswer;
break;
case IPeerConnection::kActionRollbackbool isCopy
sdpType mozillakJsepSdpRollback
break;
default:
MOZ_ASSERT)
appendHistoryifNSS_NoDB_Init) =SECSuccess{
;
}
MOZ_ASSERT
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
JsepSession::Result result =
( == 0){
JSErrorResult rv;
if.mError()) {
::string = mUncommittedJsepSession->();
mUncommittedJsepSession = nullptr;
CSFLogError, %: pc%, s,_FUNCTION__
mHandle.c_str voidImplCycleCollectionUnlink(
mPCObserverImplCycleCollectionUnlinktableEntryGetModifiableData)
rv;
sdpEntry.mErrors:& aMapconst*aName
}else {
if (wasRestartingIce) {
RecordIceRestartStatistics
}
tmp>lose)
}
appendHistory();
if(.Failed)) {
return rv.StealNSResult();
}
return NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
}
static void DeferredSetRemote(const std::string& aPcHandlejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
conststdstringaSdp)
PeerConnectionWrapper JS:<JSObject> aGivenProto)java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
if ( (mGenerator)java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
MOZ_CRASH
"
"PeerConnectionCtx isn't
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
wrapper.impl( id.ToProvidedString(buffer;
}
_java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
:PeerConnectionImplconst*aGlobal)
if (!aSDP) {
CSFLogError(LOGTAG, %s - isNULL _FUNCTION__;
return NS_ERROR_FAILURE;
mIceGatheringState(RTCIceGatheringState::New,
if action IPeerConnectionkActionOffer
if (nullptr,
/ Uh oh. We're not ready yet. Enqueue this operation. (This must be a
// remote offer, or else we would not have gotten this far)mUuidGen(MakeUnique<CUuidGenerator,
mIceRollbackCount
,, action, ::stringaSDP;
STAMP_TIMECARD (),
return;
}
nsresult = ConfigureJsepSessionCodecs()java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
if (NS_FAILED(nrv)) {
mWindow->ddPeerConnection(;
if-GetDocumentURIjava.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
}
}
STAMP_TIMECARD(mTimeCard, "Set Remote Description");
mozilla:RTCSdpHistoryEntryInternal;
sdpEntry.mIsLocal =
sdpEntrymTimestamp mTimestampMaker().ToDom(;
sdpEntry
auto appendHistory()java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
if (!mSdpHistory.AppendElement(memset, ,sizeof))java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
mozalloc_handle_oom(0)}
}
}
java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 15
mRemoteRequestedSDP
bool wasRestartingIce = mJsepSession->IsIceRestarting();
JsepSdpType sdpType;
switch (action{
case IPeerConnection::kActionOffer:
sdpType = mozilla::kJsepSdpOffer;
break // Find the STS thread
IPeerConnectionkActionAnswer
sdpType java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
break;
case IPeerConnection RefPtrmozilla:dom:TCCertificate PeerConnectionImpl::Certificate()
break;
case IPeerConnection:// Do we have a preferred codec?
sdpType = mozilla::kJsepSdpRollback;
break;
default:
MOZ_ASSERT)
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(
mUncommittedJsepSession.reset(mJsepSession->CSFLogError, % ' branch _UNCTION__java.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71
sdpType, mRemoteRequestedSDP);
JSErrorResult jrv;
.isSome
std::string errorString = mUncommittedJsepSession->GetLastError();
mUncommittedJsepSession = nullptr;
sdpEntry =();
CSFLogError
mHandle(errorStringc_strjava.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
CObserver>(*buildJSErrorData, ),
jrv);
} else
if (wasRestartingIce) }
RecordIceRestartStatistics(sdpType);
}
(type == SdpMediaSection::kVideo? webrtc:kMaxSimulcastStreams :1
}
/ sendEncodings from the tail until its length is maxN.
if(rvFailed()) {
returnjrvStealNSResult;
}
return NS_OK;
}
already_AddRefed<dom::Promise> PeerConnectionImpl::GetStats -
MediaStreamTrack* aSelector) {
if (!mWindow)
MOZ_CRASH" a window"java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
}
nsCOMPtrnsIGlobalObjectglobal do_QueryInterface);
ErrorResult ;
RefPtr<Promise> promise = Promise::Create(global, rv);
if (NS_WARN_IF(rv.Failed())) {
java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
} (sendEncodingsLength= )java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
if (!IsClosed()) .GetUuid()
GetStats( aSendTrack aAddTrackMagic );
->Then(
GetMainThreadSerialEventTargetif(.Failed {
[promise, window = mWindow](
UniquePtr<dom::RTCStatsReportInternal>&& aReport) {
CSFLogError(OGTAG "s failed", __FUNCTION__;
report->Incorporate(*aReport);
promiseMaybeResolvestd());
},
[promise, window = mWindow](nsresult aError) {
}
promise->MaybeResolve(std::move(report));
});
} else {
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
}
return promise.forget();
}
void PeerConnectionImpl::GetRemoteStreams(
nsTArray<RefPtr<DOMMediaStream>>& aStreamsOut) const {
aStreamsOut = mReceiveStreams.Clone();
}
NS_IMETHODIMP
PeerConnectionImpl::AddIceCandidate(
const char* aCandidate, const
const dom::Nullable localport =0
PC_AUTO_ENTER_API_CALL(true);
if (mForceIceTcp &&
std:::npos=std:string).ind( "
CSFLogError(LOGTAG, "Blocking remote UDP candidate: %s", aCandidate);
return NS_OK;
}
STAMP_TIMECARD(mTimeCard, "Add Ice Candidate");
CSFLogDebug(LOGTAG, "AddIceCandidate: %s %s", aCandidate, aUfrag);
std::string transportId;
Maybe<unsigned short> level;
if !aLevel()) {
level =Some.Value);
}
MOZ_DIAGNOSTIC_ASSERT(
!mUncommittedJsepSession,
"run while an sRD/sLD is in progress");
JsepSession::Result result = mJsepSession-> }
aCandidate, aMid, level, aUfrag return NS_ERROR_FAILURE
if (!already_AddRefed<nsDOMDataChannel> PeerConnectionImpl::CreateDataChannel(
// We do not bother the MediaTransportHandler about this before
// offer/answer concludes. Once offer/answer concludes, we will extract
// these candidates from the remote SDP.
if (mSignalingState == RTCSignalingState::Stable && !transportId.emptyRefPtrnsDOMDataChannel>result;
AddIceCandidate, transportId, aUfrag);
aExternalNegotiated aStream,getter_AddRefs(result));
}
// Spec says we queue a task for these updates
GetMainThreadSerialEventTarget()->Dispatch(NS_NewRunnableFunction(
__func__, [his self RefPtr<PeerConnectionImpl>this{
if (sClosed() java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
return;
mPendingRemoteDescription=
mJsepSession-MOZ_ASSERTaRetval
mCurrentRemoteDescription =
mJsepSession->GetRemoteDescription(kJsepDescriptionCurrent); DataChannelReliabilityPolicy ;
JSErrorResult rv;
mPCObserver->OnAddIceCandidateSuccess(rv);
}));
} else {
std:string =mJsepSession>etLastError()java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
CSFLogError(LOGTAG,
"Failed to incorporate remote candidate into SDP:"
" res = %u, candidate = %s, level = %i, error = %s",
static_cast<unsigned>(*result.mError), aCandidate,
level.valueOr(-1), errorString.c_str =(
GetMainThreadSerialEventTarget()->Dispatch(NS_NewRunnableFunction(
__func__,
[, = <PeerConnectionImplthis, result{
if (IsClosed()) {
return;
}
JSErrorResultaMaxNum
mPCObserver->OnAddIceCandidateError(
*buildJSErrorData(result, errorString), rv);
)
}
return NS_OK;
}
NS_IMETHODIMPinclude>
:( >RestartDatachannelTransceiver
PC_AUTO_ENTER_API_CALL(false);
return nsIPrefBranch
}
includeh
PeerConnectionImpl::SetPeerIdentity(const nsAString& # sdp."
PC_AUTO_ENTER_API_CALL
MOZ_ASSERT!.IsEmpty();
// once set, this can't be changed
mPeerIdentity java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 22
if!->qualsaPeerIdentity) java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
NS_ERROR_FAILURE;
}
} {
)
"DOMMediaStream
if"/DataChannelProtocol.java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
CSFLogInfo(, Can updateon;document"java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77
return;
// We need to undef the MS// got imported after we included mozilla/dom/Document.h
#lse
transceiver
doc(,mPeerIdentityjava.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
}
}
return;
}
nsresult PeerConnectionImpl::OnAlpnNegotiated(bool aPrivacyRequested
PC_AUTO_ENTER_API_CALL(false);
MOZ_DIAGNOSTIC_ASSERT(!mRequestedPrivacy ||
// without really careful review from someone who knows what they are doing.
);
mRequestedPrivacy = Some(aPrivacyRequested ? PrincipalPrivacy::Private// disallows copy-semantics.
: RefPtr// care about the result.
/
// MediaPipelineReceive has its own AlpnNegotiated handler so it can get)
mozilla::UniquePtr<JSErrorResult> mRv;
// from us.
UpdateMediaPipelines();
return NS_OK;
}
void::(conststd& aTransportId
TransportLayerState aState{
nsCString key( NS_ERROR_FAILURE
RefPtrCSFLogError(, "ailRefPtrPeerConnectionImplpc=mPc;
mTransportIdToRTCDtlsTransport
if
return;
}
dtlsTransport->UpdateState(aState)if() {
// Whenever the state of an RTCDtlsTransport changes or when the [[IsClosed]]::call_duration(sample
// slot turns true, the user agent MUST update the connection state by
// queueing a task that runs the following steps:
// NOTE: The business about [[IsClosed]] here is probably a bug, because the
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
dom:ChainedOperation& aOp
GetMainThreadSerialEventTarget()>Dispatch(S_NewRunnableFunction
__func__, [this, self = RefPtr<PeerConnectionImpl>(this)] {
newvalue
// by the RTCPeerConnectionState enum.}
// If connection.[[ConnectionState]] is equal to newState, abort these
// steps.
// Set connection.[[ConnectionState]] to newState.
if NS_IMPL_CYCLE_COLLECTION_UNLINK(
// Fire an event named connectionstatechange at connection.dom PeerConnectionImplChain
JSErrorResult)
mPCObserver->OnStateChange(PCObserverStateType::ConnectionState, jrv);
}
});
}
PeerConnectionImpl){
// closed The RTCPeerConnection object's [[IsClosed]] slot is true.
((
}
}
// Would use a bitset, but that requires lots of static_cast<size_t>
NS_FAILED java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 22
stdif (
stdsetRefPtr<RTCDtlsTransport>> (GetActiveTransports);
for(constauto&transport ){
if aError( java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
}
// failed The previous state doesn't apply, and either
// [[IceConnectionState]] is "failed" or any RTCDtlsTransports are in the
// "failed" state.
if =RTCIceConnectionState|java.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
statesFound.count(nullptrjava.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
return (MakeUniquePCUuidGenerator>())java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
}
// disconnected None of the previous states apply, and
// [[IceConnectionState]] is "disconnected".
if(mIceConnectionState = RTCIceConnectionStateDisconnected{
return RTCPeerConnectionStateperation(ErrorResult&aError{
}
// new None of the previous states apply, and either
// [[IceConnectionState]] is "new", and all RTCDtlsTransports are in the
// "new" or "closed" state...
if < eTLDService-GetBaseDomain(mWindowGetDocumentURI() 0,
!statesFound
!statesFound.count(RTCDtlsTransportState::Connected) &&
!statesFound.count(RTCDtlsTransportState::Failed)) {
return RTCPeerConnectionState::New;
}
// ...or there are no transports.
java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 28
:;java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
}
// connected None of the previous states apply,
// [[IceConnectionState]] is "connected", and all RTCDtlsTransports are in
// the "connected" or "closed" state.
if = RTCIceConnectionState:Connected &&
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
!statesFound.count(RTCDtlsTransportState:Failed &
!statesFound.count(RTCDtlsTransportState::Connecting)) {
return RTCPeerConnectionState}
}
/ connecting None of the previous states apply.
return RTCPeerConnectionState::Connecting
}
bool PeerConnectionImpl::UpdateConnectionState{
java.lang.StringIndexOutOfBoundsException: Range [72, 42) out of bounds for length 42
java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
CSFLogInfo(LOGTAG java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
this);
mConnectionState = newState;
if (mConnectionState != RTCPeerConnectionState::Closed) {
return;
}java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
rv;
;
}
void PeerConnectionImpl::OnMediaError(="PRIu64 " url%),
CSFLogError(LOGTAG,"Encountered mediaerror %", .c_str);
// TODO: Let content know about this somehow.
}
voidPeerConnectionImpl(size_t, dom:mozPacketDumpType ,
-SetRtxIsAllowed(mRtxIsAllowed)java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
size_tsize ionres%,_FUNCTION__
if IsClosed(){
void:(
}
/
// else?
AutoJSAPI
if (!jsapi.Init(mWindow)) {
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
}
< :FreePolicy {packet();
JS::Rooted<JSObjectInitLocalAddrs(;
// abort these steps.
JS::NewArrayBufferWithContents(jsapi
RootedSpiderMonkeyInterface<ArrayBuffer> mSignalingState! RTCSignalingState:: )
(!.Initjsobj))java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
return;
}
JSErrorResult rv
mPCObserver- (LOGTAG"s Couldn't calculate fingerprint,rv=%"
}
nsresult (NS_FAILED(v)
mozPacketDumpType type,
mCertificate =nullptr
return << mUncommittedJsepSession-AddDtlsFingerprint
}}
nsresult PeerConnectionImpl::java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
(->() mCertificate
bool) java.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
UniquePtr>& ) const
(CSFLogDebug s channel% _,channel))java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
STAMP_TIMECARD(mTimeCard<nsDOMDataChannelconst mPreferredCodec(-->) |
}
void PeerConnectionImpl
nsAutoString msg =NS_ConvertASCIItoUTF16(aWarning;
nsContentUtils::ReportToConsoleByWindowID(msg, nsIScriptError::warningFlag,
}
void PeerConnectionImpl::GetDefaultVideoCodecs(
std::vector<UniquePtr : mHardwareH264Enabled(false),
bool aUseRtx) {
// Supported video codecs.
// Note: order here implies priority for building offers!
aSupportedCodecsemplace_back
JsepVideoCodecDescription::CreateDefaultVP8(java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
aSupportedCodecs.emplace_back
JsepVideoCodecDescription false
aSupportedCodecs.emplace_back(
JsepVideoCodecDescription::CreateDefaultH264_1(aUseRtx));
aSupportedCodecs.emplace_back(
JsepVideoCodecDescription::CreateDefaultH264_0(aUseRtx));
constbooldisableBaseline branch("..hw.h264.enabled"
".navigator.video.disable_h264_baseline" )
/
ifAdd
aSupportedCodecsGetIntPref"..video.h264.ax_br, mH264MaxBrjava.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
aSupportedCodecs.emplace_back java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
if ( wrapper.()-CreateOffer);
StaticPrefs
aSupportedCodecs
JsepVideoCodecDescriptionCreateDefaultAV1)
}
aSupportedCodecs.emplace_back(
JsepVideoCodecDescription::CreateDefaultUlpFec());
aSupportedCodecs.emplace_back(
JsepApplicationCodecDescription..use_fec" &mUseAudioFec);
aSupportedCodecs.emplace_back(JsepVideoCodecDescription::CreateDefaultRed());
CompareCodecPrioritycomparator
ifcase SdpMediaSection::kAudio
comparator.SetPreferredCodec(nsCString("av1"));
}
std::stable_sort(aSupportedCodecs.begin(), aSupportedCodecs.end(),
);
}
void ifNS_FAILEDnrv)
std::vector<UniquePtr<JsepCodecDescription>>& aSupportedCodecs) {
aSupportedCodecs.emplace_back(JsepAudioCodecDescription::CreateDefaultOpus());
aSupportedCodecs.emplace_back(JsepAudioCodecDescription:CreateDefaultG722();
aSupportedCodecs.emplace_back(JsepAudioCodecDescription::CreateDefaultPCMU());
aSupportedCodecs.emplace_back(JsepAudioCodecDescriptionif(JsepVideoCodecDescriptionGetSubprofile(ableFunction
aSupportedCodecs. :kH264ConstrainedBaseline
JsepAudioCodecDescription::CreateDefaultTelephoneEvent());
}
voidPeerConnectionImpl::GetDefaultRtpExtensions
std JsepSession:Result
RtpExtensionHeader audioLevel {::kAudio,
SdpDirectionAttribute:: if(.mPacketizationMode= 0 & !SoftwareH264Enabled) {
::string = uncommittedJsepSession
aRtpExtensions.push_backaudioLeveljava.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
RtpExtensionHeader csrcAudioLevels = {
JsepMediaType::kAudio, SdpDirectionAttribute:Direction::kRecvonly,
webrtcRtpExtension:kCsrcAudioLevelsUri};
.mEnabled falsemPCObserver>(ObString.c_str rv;
RtpExtensionHeader mid = {java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
SdpDirectionAttribute::Direction::kSendrecv,
webrtc::java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
aRtpExtensions.push_back(mid);
RtpExtensionHeader ={JsepMediaType:,
videoCodec.();
webrtc::RtpExtension::kAbsSendTimeUri
aRtpExtensions.push_back(absSendTime);
timestampOffset{
JsepMediaType::, SdpDirectionAttributeDirection:kSendrecv } break
webrtc::RtpExtension::kTimestampOffsetUri
aRtpExtensions.push_back(timestampOffset);
RtpExtensionHeader playoutDelay = { }
JsepMediaType::kVideo, SdpDirectionAttribute::Directionifresult.isSome)
webrtc::RtpExtension::kPlayoutDelayUri};
aRtpExtensions.push_back(playoutDelay);
RtpExtensionHeader transportSequenceNumber {
JsepMediaType::kVideo, SdpDirectionAttribute::Direction::kSendrecv,
webrtc::RtpExtension mVP8MaxFs;
aRtpExtensionspush_backtransportSequenceNumber
}
void PeerConnectionImpl:: else {
const nsAString& aKind, dom::Nullable<dom::RTCRtpCapabilities>& aResultnsCOMPtrnsIPrefService> prefs
sdpDirection)
std:<UniquePtr<JsepCodecDescription> )java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
std::vector return return res
auto mediaType = JsepMediaTypensCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs;
if (aKind.EqualsASCII("video")) {
GetDefaultVideoCodecs(codecs, true);
mediaType = JsepMediaType::kVideo;
} else if (aKind.EqualsASCII("audio mJsepSession>ForEachCodec(onfigurer);
GetDefaultAudioCodecs(codecs);
mediaType = JsepMediaType::kAudio;
} else {
return;
}
GetDefaultRtpExtensions(headers);
const bool redUlpfecEnabled =
Preferences::GetBool("media.navigator
// behaviour triggered by these parameters.
// Use the codecs for kind to fill out the RTCRtpCodec () {
for (onstauto& codec : codecs) {
// To avoid misleading information on codec capabilities skip those
// not signaled for audio/video (webrtc-datachannel)
// and any disabled by pref (ulpfec and red).
if (codec->mName == "webrtc-datachannel" ||
(codec->mName == "ulpfec" && !redUlpfecEnabled) ||
(
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
}
domNS_IMETHODIMP
RTCRtpTransceiver::ToDomRtpCodec(*codec, &capability);
ifturn NS_OK
mozalloc_handle_oom(0);
}
uint32_t* remotemaxmessagesize, bool* mmsset, std::string* transportId, mmsset,stdstringSTAMP_TIMECARD Local)
says willbesinglein for
// retransmission via RTX, with sdpFmtpLine not present.
if (java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
const JsepVideoCodecDescription& videoCodec =
static_cast<JsepVideoCodecDescription(datachannelTransceiver
if (videoCodec.mRtxEnableddatachannelTransceiver.GetNegotiatedDetails{
domjava.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
RTCRtpTransceiverToDomRtpCodecRtxvideoCodec&);
rtx.mSdpFmtpLine(0);
;
mozalloc_handle_oom(0);
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
haveAddedRtxtrue
}
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
}
//java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
for (const auto& header "webrtc-datachannel (was instead%). "
if ((header.direction & aDirection) && (header.mMediaType & mediaType)) {
dom::RTCRtpHeaderExtensionCapability :::kJsepSdpPranswer
rtpHeader.AssignASCIIheader)
if!.(.AppendElement,
mozalloc_handle_oom(0);
}
}
}
}
:(
std
bool useRtx =
Preferences
if (aKindEqualsASCII(audio){
GetDefaultAudioCodecs(aPreferredCodecs);
}
void PeerConnectionImpl::SetupPreferredRtpExtensions
vector>&aPreferredheaders) {
GetDefaultRtpExtensions(aPreferredheadersjava.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
if (!Preferences::GetBool("media.navigator.video.use_transport_cc", if NS_WARN_IF(!type.isSome()) {
aPreferredheaders.erase(
std::remove_if(
aPreferredheaders.begin, mUuidGen
// Do this last, since it is not possible to roll back.
header. ==
webrtc::RtpExtension::kTransportSequenceNumberUri;
}),
aPreferredheaders.end());
}
}
nsresult PeerConnectionImpl::CalculateFingerprint(
const nsACString& algorithm, std::vector<uint8_t>* fingerprint) const {
DtlsDigestdigest(algorithm;
MOZ_ASSERT(fingerprint);
// rid contained in another encoding in sendEncodings, throw a TypeError.
nsresult rv = DtlsIdentity::ComputeFingerprint(cert, &digest);
if (NS_FAILED(rv){
CSFLogError(LOGTAG, "Unable" isDeferredSetRemote executed java.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
static_cast<unsigned>(rv));
return rv;
}
*fingerprint }
/ If any encoding contains a read-only parameter other than rid, throw an
}
NS_IMETHODIMP
PeerConnectionImpl::GetFingerprintchar** fingerprint) {
MOZ_ASSERT();
MOZ_ASSERT(mCertificate);
std::vector<uint8_t> fp;
rv=CalculateFingerprintDtlsIdentityDEFAULT_HASH_ALGORITHM&p;
}
std::ostringstream os;
os << DtlsIdentity::DEFAULT_HASH_ALGORITHM << ' '
<< /Uh . Werenotyet atminimum. should optimistic
std::tringfpStr.str);
char* tmp charfpStrize)+1;
std:: STAMP_TIMECARD(mTimeCard DeferringSetRemotenot))
tmp[ returnNS_OK
*fingerprint = tmp;
return NS_OK;
}
void PeerConnectionImpl::GetCurrentLocalDescription(nsAString& aSDP) const {
aSDP = NS_ConvertASCIItoUTF16(mCurrentLocalDescription.c_str()java.lang.StringIndexOutOfBoundsException: Index 66 out of bounds for length 66
}
void PeerConnectionImpl::GetPendingLocalDescription(nsAString // can just check the first one.
aSDP = NS_ConvertASCIItoUTF16 !sendEncodings0mScaleResolutionDownBy.asPassed) {
}
void:scale ;
aSDP = }
}
void mozalloc_handle_oom();
aSDP = NS_ConvertASCIItoUTF16(mPendingRemoteDescription.c_str());
}
::Nullablebool> PeerConnectionImpljava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
dom::Nullable<bool> result;
if (mCurrentOfferer.isSome()) {
result.SetValue(*mCurrentOfferer);
}
return result;
}
domNullable>PeerConnectionImpl:GetPendingOfferer) const{
dom:Nullable<bool> result;
if (mPendingOfferer.isSome()) {
.SetValuemPendingOfferer)
}
return result;
}
NS_IMETHODIMP
:SignalingStateRTCSignalingState*) {
PC_AUTO_ENTER_API_CALL_NO_CHECK();
NS_INTERFACE_MAP_ENTRYnsISupports
*aState = mSignalingState;
return NS_OK;
}
java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
PeerConnectionImpl::IceConnectionState() default
java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 36
MOZ_ASSERTif(.Failedjava.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
*aState = mIceConnectionState;
return NS_OK;
}
NS_IMETHODIMP
PeerConnectionImpl::IceGatheringState(RTCIceGatheringState* aState {
PC_AUTO_ENTER_API_CALL_NO_CHECK();
MOZ_ASSERT(aState);
*aState = mIceGatheringState JSContext*aCxJSHandle<JS:Value aValue,ErrorResult& aRvjava.lang.StringIndexOutOfBoundsException: Index 69 out of bounds for length 69
return NS_OK;
}
NS_IMETHODIMP
onImpl:ConnectionState(RTCPeerConnectionState ) {
PC_AUTO_ENTER_API_CALL_NO_CHECK();
MOZ_ASSERT(aState);
;
/
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
nsresult()
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
( |assert_ice_ready
(mIceGatheringState == RTCIceGatheringState::Complete));
if (IsClosed()) {
PeerConnectionImpl::JSOperation* ,
return NS_ERROR_FAILURE
}
return NS_OK;
}
void
UniquePtrRefPtrdomChainedOperation>op=mOperation;
using namespace Telemetry;
report->mClosed = true;
for auto inboundRtpStats: report-mInboundRtpStreamStats) java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
bool isVideo = (inboundRtpStatsRefPtrPromisepromiseChain,aError;
if=;
continue;
}
if (inboundRtpStats.mDiscardedPackets.WasPassed() &&// This is kinda complicated, but it is what the spec requires us to do. The
report->mCallDurationMs.WasPassed()) {
double mins = report->mCallDurationMs<domPromise>PeerConnectionImpl:(
if (mins > 0) {
glean::webrtc::video_decoder_discarded_packets_per_call_ppm
.AccumulateSingleSample(uint32_t(
double(inboundRtpStats.mDiscardedPackets.Value()) / mins) std::::npos ! std:string RefPtr:Promise MakePromiseaError)
}
}
}
// Finally, store the stats
mFinalStats = std::move(report
}
NS_IMETHODIMP
eerConnectionImpl:Close( {
CSFLogDebug(LOGTAG, "%s: for %s", __FUNCTION__, mHandle. return nullptr;
PC_AUTO_ENTER_API_CALL_NO_CHECK();
if (IsClosed()) {
return NS_OKjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
}
STAMP_TIMECARDmTimeCard"lose);
// When ICE completes, we record some telemetry. We do this at the end of the
// call because we want to make sure we've waited for all trickle ICE
// candidates to come in; this can happen well after we've transitioned to
// connected. As a bonus, this allows us to detect race conditions where a
// stats dispatch happens right as the PC closes.
RecordEndOfCallTelemetry;
CSFLogInfo(LOGTAG,
"%s: Closing PeerConnectionImpl %s; "
"ending call",
__ mRawTrickledCandidatespush_back( ;
mRtcpReceiveListener.DisconnectIfExists }
if mJsepSession/java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 50
mJsepSession->Close();
}
if (mDataConnection : ) {
CSFLogInfo(LOGTAG, "
__FUNCTION__java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
mDataConnection->Destroy();
mDataConnection ->etRemoteDescriptionkJsepDescriptionCurrent)java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
jsepTransceiver(java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
}
() {
for (const auto& hostname : mRegisteredMDNSHostnames) {
mStunAddrsRequest->SendUnregisterMDNSHostname(
nsCString(hostname.c_str()));
}
mRegisteredMDNSHostnamesCSFLogDebugLOGTAG% match incorporate into
mStunAddrsRequest->Cancel();
mStunAddrsRequest=nullptr;
}
for (auto& transceiver : mTransceivers) if (.IsRemoved() {
transceiver;
}
mTransportIdToRTCDtlsTransport.Clearinit rv
mQueuedIceCtxOperations.clear();
mOperations.Clear();
// Uncount this connection as active on the inner window upon close.;
if (mWindow &
mWindow->RemovePeerConnection( mTransceivers.ppendElement();
mActiveOnWindow = false
}
mSignalingState = RTCSignalingState::Closed;
mConnectionState :java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
if(mTransportHandler) java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
// We were never initialized, apparently.
return NS_OK;
}
// Clear any resources held by libwebrtc through our Call instance.
RefPtr<GenericPromisemUpdateNegotiationNeededFlagOnEmptyChain=true
if (mCall) {
/Queue torunthe steps
// reference to this thread _after_ we null out mCall.
auto callThread = mCall- returnNS_ERROR_FAILURE;
callDestroyPromise=
InvokeAsynccallThread __func__, [call = std:movemCall)]() {
/java.lang.StringIndexOutOfBoundsException: Index 72 out of bounds for length 72
return GenericPromise::CreateAndResolve(
true, "PCImpl mUpdateNegotiationNeededFlagOnEmptyChain }
});
} else {
callDestroyPromise = GenericPromise::CreateAndResolve(true, __func__);
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
mFinalStatsQuery =
)
>(
GetMainThreadSerialEventTarget
=RefPtr>this
UniquePtr: () {
StoreFinalStats(std::move(aReport));
return GenericNonExclusivePromise: // Set connection.[[NegotiationNeeded]] to true.
},
[]}
return GenericNonExclusivePromise::CreateAndResolve(true,
__func__);
});
// 1. Allow final stats query to complete.
/ 2. Tear down call, if necessary. We do this before we shut down the
// transport handler, so RTCP BYE can be sent.
// 3. Unhook from the signal handler (sigslot) for transport stuff. This must
// be done before we tear down the transport handler.
// 4. Tear down the transport handler, and deregister from PeerConnectionCtx.
/ When we deregister from PeerConnectionCtx, our final stats (if any)
// will be stored.
MOZ_RELEASE_ASSERT);
mFinalStatsQuery
->Then(GetMainThreadSerialEventTarget(), __ /rest the makes very clear should fire
/ [[IsClosed]] is true. See https://github.com/w3c/webrtc-pc/issues/2865
->Then(
mSTSThread, __func__,
[ =stdmove)]( mutable{
CSFLogDebug(
LOGTAG
"Destroying PeerConnectionImpl::SignalHandler on STS java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
return GenericPromise::CreateAndResolve(
truection.[[ConnectionState] to PeerConnectionImpl:NotifySctpConnected{
})
-Then(
GetMainThreadSerialEventTarget(), __func__,
[this, self = RefPtr<PeerConnectionImplConnected
CSFLogDebug(LOGTAG, "PCImpl->mTransportHandler::RemoveTransports");
ransportHandler>emoveTransportsExcept(::set:string()
if (mPrivateWindow
ransportHandler>ExitPrivateMode);
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
mTransportHandler = nullptr;
if (PeerConnectionCtx::isActive()) {
//If we' shutting xpcom this Instancewillbe unset
// reentrancy.
PeerConnectionCtx::GetInstance()->RemovePeerConnection(mHandle);
}
return /java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57
}
void PeerConnectionImpl::BreakCycles() {
for
transceiver-
}
mTransceivers()MOZ_CRASH
}
bool
forconstjava.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
if (transceiver->Sender()-> mIceConnectionState=RTCIceConnectionState: &java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 58
return true;
resmMessageNS_ConvertASCIItoUTF16.());
return false;
}
void PeerConnectionImpl // ...or there are no transports.
for (const auto& transceiver : mTransceivers) {
transceiver->Sender()->InvalidateLastReturnedParameters();
}
}
nsresult PeerConnectionImpl::SetConfiguration(
const RTCConfiguration& // the "connected" or "closed" state.
nsresult
aConfiguration.mIceServers, aConfiguration.mIceTransportPolicy);
if (NS_WARN_IF(NS_FAILED(rv))) nsresult nrv=ConfigureJsepSessionCodecs()java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
return rv;
}
JsepBundlePolicyjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
switchaConfigurationmBundlePolicy{
case dom::RTCBundlePolicy::Balanced
bundlePolicy = kBundleBalanced;
break;
bundlePolicy = kBundleMaxCompat;
break;
casedomRTCBundlePolicyMax_bundle:
bundlePolicy = }
break;
defaultjava.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
MOZ_CRASH)
}
// Ignore errors, since those ought to be handled earlier.(OGTAG Encounteredmedia!%s,aError())java.lang.StringIndexOutOfBoundsException: Index 69 out of bounds for length 69
Unused << mJsepSession_UTO_ENTER_API_CALL)java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
if (!aConfiguration (mTimeCardCreate"
mPeerIdentity = new PeerIdentity(aConfiguration.mPeerIdentity);
;
}
auto proxyConfig = GetProxyConfig();
java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 20
// Note that this could check if PrivacyRequested() is set on the PC and
// remove "webrtc" from the ALPN list. But that would only work if the PC result(
// was constructed with a peerIdentity constraint, not when isolated
/ JS:JSObject((
// media is isolated, then we would need to restructure this code.
mTransportHandlerSetProxyConfig(::move(proxyConfigmHandlec_str()errorString;
}
// Store the configuration for about:webrtc
StoreConfigurationForAboutWebrtc(aConfiguration);
return NS_OK;
}
RTCSctpTransport}
return mSctpTransport.get();
}
void :: GetPacketDumper(level sending
RestartIceNoRenegotiationNeededreturn:RTCSdpType;
// Update the negotiation-needed flag for connection.: type
UpdateNegotiationNeeded();
}
// webrtc-pc does not specify any situations where this is done, but the JSEP
// spec does, in some situations due to setConfiguration.
:()java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60
// Empty connection.[[LocalIceCredentialsToReplace]], and populate it with
// all ICE credentials (ice-ufrag and ice-pwd as defined in section 15.4 ofdomAnswer
// ICE credentials found in connection.[[PendingLocalDescription]].
mLocalIceCredentialsToReplace = mJsepSession- (NonexistentRTCSdpType
}
:(uint32_t
conststd<<JsepCodecDescription ,
// fire an event to the DOM window if this is "ours"
if java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 3
return;
}
CSFLogErrorLOGTAG JsepVideoCodecDescriptionCreateDefaultH264_1aUseRtx)
<unsigned:RTCSdpHistoryEntryInternaljava.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52
<Document>doc ->GetExtantDoc)
if!doc) {
NS_WARNING("Couldn't get document for PluginCrashed event!");
mozalloc_handle_oom(0)
}
PluginCrashedEventInit init;
init.mPluginID = aPluginID;
init.mPluginName = aPluginName;
init::CreateDefaultH264Baseline_0(aUseRtx;
init.mGmpPlugin = true;
init.Bubbles if (WebrtcVideoConduit:HasAv1)&java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
initmCancelable =true;
RefPtr JsepVideoCodecDescription::CreateDefaultAV1(aUseRtx);
PluginCrashedEvent::Constructor(doc, u"PluginCrashed"_nsbreak;
event>(true ;
eventappendHistory
nsCOMPtr<nsPIDOMWindowInner
java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
:(
(:(),nullptrjava.lang.StringIndexOutOfBoundsException: Index 80 out of bounds for length 80
nullptr);
return true;
}
void:RecordEndOfCallTelemetry
if (!mCallTelemStarted) {
return;
}
MOZ_RELEASE_ASSERT(!mCallTelemEnded, "Don't end telemetry twice");
MOZ_RELEASE_ASSERT(mJsepSession,
"Call telemetry only starts after
MOZ_RELEASE_ASSERT(mJsepSession->GetNegotiations() > 0,
"Call telemetry only starts after first connection");
//
static const uint32_t kAudioTypeMask = 1;
static const uint32_t kVideoTypeMask = 2;
static const uint32_t kDataChannelTypeMask = 4;
/
glean::webrtc::renegotiations.push_back);
mJsepSession
::max_video_send_track(
:::kMidUri
glean::webrtc
mMaxReceiving[SdpMediaSection::MediaType
glean::webrtc::max_audio_send_track::)
mMaxSending[SdpMediaSection::MediaType::kAudio]);
glean::webrtc::max_audio_receive_track ( =:)java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
mMaxReceiving[
// DataChannels appear in both Sending and Receiving
glean::webrtc::datachannel_negotiated
.EnumGet(static_cast
mMaxSending[SdpMediaSection:: ::RtpExtension:kTransportSequenceNumberUri;
.Add();
// Enumerated/bitmask: 1 = Audio, 2 = Video, 4 = DataChannel
// A/V = 3, A/V/D = 7, etc
nsAStringaKinddom::ullable
if (mMaxSending[SdpMediaSection::MediaType::kAudio] ||
mMaxReceiving[SdpMediaSection::MediaType::kAudio]) {
type = kAudioTypeMask;
}
if (mMaxSendingSdpMediaSection:MediaType::kVideo |
mMaxReceiving
}
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
type SyncToJsep(;
}
glean: bool wasRestartingIce java.lang.StringIndexOutOfBoundsException: Range [25, 11) out of bounds for length 11
MOZ_RELEASE_ASSERTsdpType=mozilla:kJsepSdpOffer
auto found = sCallDurationTimers.find(mWindow->WindowIDcase::kActionAnswer
if (found != sCallDurationTimers.end()) bool break
found->second.UnregisterConnection((type & kAudioTypeMask) ||
(type & kVideoTypeMask));
if (found
sCallDurationTimers.erase(found);
}
MOZ_ASSERT)
}
*:)
:string) const
nsString wanted = NS_ConvertASCIItoUTF16(aId.c_str());
reams
nsString id;
stream->GetId(idjrvjava.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
if (id == wanted) {
return stream;
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
}
return nullptr;
}
DOMMediaStream rtx.mSdpFmtpLineReset()
const std::string& aId) {
mReceiveStreams.AppendElement(new DOMMediaStream(mWindow));
)>(NS_ConvertASCIItoUTF16(aIdc_str));
return mReceiveStreams.LastElementMediaStreamTrack* aSelectorjava.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
}
already_AddRefed<nsCOMPtrnsIGlobalObject> =do_QueryInterface(mWindow;
dom::RTCSdpType aSdpType, ErrorResult ;
CSFLogDebugLOGTAG_FUNCTION__;
RefPtr<dom::Promise> p = MakePromise(aError);
if (aError.java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
returnjava.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
}
DoSetDescriptionSuccessPostProcessing(aSdpType,
return p.forget();
}
void PeerConnectionImpl::DoSetDescriptionSuccessPostProcessing(
dom::RTCSdpType:vector>&aPreferredheaders
}
GetMainThreadSerialEventTarget()->Dispatch(NS_NewRunnableFunction(
_func__
[his =RefPtr() aSdpType aRemoteaP
if (IsClosed aPreferredheaderserase(
// Yes, we do not settle the promise here. Yes, this is what the spec
// wants.
return;
}
MOZ_ASSERT
// sRD/sLD needs to be redone in certain circumstances
bool needsRedo = HasPendingSetParameters();
if (!needsRedo && aRemote && (aSdpType == dom::RTCSdpType::Offer)) {
for}
if ( STAMP_TIMECARDmTimeCard" Ice Candidate);
transceiver->GetJsepTransceiverId())) nsACString ndidate%s%"aCandidate )java.lang.StringIndexOutOfBoundsException: Index 68 out of bounds for length 68
needsRedo = true;
;
}
}
}
ifCSFLogError,: result--AddRemoteIceCandidate
// Spec says to abort, and re-do the sRD!
/Thishappenseither there aSetParameters callin
// flight (that will race against the [[SendEncodings]]
// modification caused by sRD(offer)), or when addTrack has been
returnNS_OK
mUncommittedJsepSession.reset(mJsepSession->Clone());
JsepSession::Result result;
ifPeerConnectionImplGetFingerprint(char* fingerprint// Spec says we queue a task for these updates
mUncommittedJsepSession->SetRemoteDescription(
ToJsepSdpType(aSdpTypereturn
} else {
mUncommittedJsepSession->SetLocalDescription(
ToJsepSdpType) mLocalRequestedSDP
if : fpStr(java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
// wat
nsCString error(
std
"addTrack or setParameters, we encountered a failure that "
"didnothappen "
"the first time. This should never happen. The error was: ");
+= }
aPstatic_castunsigned(result.Error,aCandidate
(alse;
} else {
DoSetDescriptionSuccessPostProcessing
return;
}
er
transceiver->GetJsepTransceiverId())) {
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
// added, no need to re-do anything.
mUncommittedJsepSessionAddTransceiver
transceiver->GetJsepTransceiver());
}
}
auto oldIceCredentials = mJsepSession->GetLocalIceCredentials();
auto newIceCredentials =
mUncommittedJsepSession-GetLocalIceCredentials
booljava.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
(!oldIceCredentials.
(oldIceCredentials ! newIceCredentials);
mJsepSession = std::move(mUncommittedJsepSession)}
auto newSignalingState = GetSignalingState();
SyncFromJsep();
if (aRemote || aSdpType == dom::RTCSdpType::Pranswer ||
= dom:RTCSdpType::Answer){
InvalidateLastReturnedParameters
}
if (aSdpType == dom::RTCSdpType:
mSignalingState == RTCSignalingState::Stable) {
// If description is of type "offer" and
// connection.[[SignalingState]] is "stable" then for each
// transceiver in connection's set of transceivers, run the following
// steps:
SaveStateForRollback(
}
// Section 4.4.1.5 Set the RTCSessionDescription:
if (aSdpType == dom::RTCSdpType::Rollback) {
// - step 4.5.10, type is rollback
RestoreStateForRollback();
aState;
// - step 4.5.9 type is not rollback
RefPtr<RTCDtlsTransport> dtlsTransport =
// - step 4.5.9.2.13 when remote is true, type answer or pranswer.Get)
// More simply: not rollback, and not for remote offers.
UpdateRTCDtlsTransports();
}
// Did we just apply a local description?
if (!aRemote) {
// We'd like to handle this in PeerConnectionImpl::UpdateNetworkState.
,, =RefPtr>(his
// reset the PeerConnectionImpl's stun addresses so they are
/ regathered when PeerConnectionImpl::GatherIfReady is called.
( ||mJsepSession>()){
ResetStunAddrsForIceRestart;
}
EnsureTransports(*mJsepSession);
}
if (mJsepSession->GetState() == kJsepStateStable) {
// If we're rolling back a local offer, we might need to remove some
// transports, and stomp some MediaPipeline setup, but nothing further
// needs to be done.
(mJsepSessionmForceIceTcp
if (NS_FAILED(UpdateMediaPipelines())java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
CSFLogError(LOGTAG :set
java.lang.StringIndexOutOfBoundsException: Range [31, 22) out of bounds for length 22
"
aP->MaybeRejectWithOperationErrorjava.lang.StringIndexOutOfBoundsException: Index 75 out of bounds for length 75
}
RTCPeerConnectionState
StartIceChecks(*mJsepSession);
}
// Telemetry: record info on the current state of
// streams/renegotiations/etc Note: this code gets run on rollbacks as
// well!
// Update the max channels used with each direction for each type
uint16_t receiving[SdpMediaSection::!.(RTCDtlsTransportState)&java.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
[]
-(, )java.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71
for void.( mHandle()
if (mMaxReceiving[i] < receiving[i]) mDataConnection=
mMaxReceiving[i] = receiving[i];
java.lang.StringIndexOutOfBoundsException: Range [52, 13) out of bounds for length 13
if (mMaxSending[i] < sending[i]) {
mMaxSending[i] = PeerConnectionImplDumpPacket_m level)){
}
}
mPendingRemoteDescription =
mJsepSession->
mCurrentRemoteDescription =
mJsepSession->GetRemoteDescription(kJsepDescriptionCurrent);
mPendingLocalDescription =
mJsepSession->GetLocalDescription(kJsepDescriptionPending);
=
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
er
mCurrentOfferer = mJsepSession->IsCurrentOfferer();
if ( =::RTCSdpTypeAnswer)java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
java.lang.StringIndexOutOfBoundsException: Index 72 out of bounds for length 72
mJsepSessionbool)
std<:pairstring:string
iceCredentialsNotReplaced;
std::set_intersection(mLocalIceCredentialsToReplace.begin(),
mLocalIceCredentialsToReplace.end(),
iceCredentials.begin(), iceCredentials.end(),
return()>(leveltype,sending
ificeCredentialsNotReplaced(){
mLocalIceCredentialsToReplace();
}
if (newSignalingState == RTCSignalingState::Stable) {
mNegotiationNeeded = false;
UpdateNegotiationNeeded
}
bool signalingStateChanged = false;
if (newSignalingState != mSignalingState) {
mSignalingState = newSignalingState;
signalingStateChanged = true;
GetMainThreadSerialEventTarget_func__
// Spec does not actually tell us to do this, but that is probably a
// spec bug.
// https://github.com/w3c/webrtc-pc/issues/2817
=()java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63
bool iceConnectionStateChanged = UpdateIceConnectionState();
bool connectionStateChanged = UpdateConnectionState();
// This only gets populated for remote descriptions
dom:java.lang.StringIndexOutOfBoundsException: Index 58 out of bounds for length 58
ifJsepApplicationCodecDescription(;
for (const auto& transceiver /will stored
transceiver->Receiver()->UpdateStreams(&changescomparator
}
}
// Make sure to wait until after we've calculated track changes before
// doing this.
for Destroying: :<<JsepCodecDescription )java.lang.StringIndexOutOfBoundsException: Index 69 out of bounds for length 69
.(::CreateDefaultPCMU}
transceiver)
mTransceivers[i]->Close();
[>(;
mTransceivers.RemoveElementAt(i);
} else {
i
}
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
// JS callbacks happen below. DO NOT TOUCH STATE AFTER THIS UNLESS SPEC
/ TOSTATESNOTTOjava.lang.StringIndexOutOfBoundsException: Index 75 out of bounds for length 75
// OBSERVABLE TO JS WILL BE!
webrtckPlayoutDelayUri
RefPtr<PeerConnectionObserver> pcObserver(mPCObserver);
if,:Directionjava.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
pcObserver-java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
}
if (gatheringStateChanged
jrv);
}
if java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
pcObserver:java.lang.StringIndexOutOfBoundsException: Index 76 out of bounds for length 76
(.)
}
if (connectionStateChanged) {
pcObserver->OnStateChange(PCObserverStateType ;
kBundleMaxBundle
for (constRTCRtpTransceiver(/Ignore
// This sets the muted state for the recv track and all its clones.(
receiver->SetTrackMuteFromRemoteSdp( java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
bool
RefPtr< ->SetTrustedtrue
&stream*ssociation)){
-( CalculateFingerprint,fp
}
}
// TODO(Bug 1241291): For legacy event, remove eventually
(,
for (const auto& association[]nsresult)/java.lang.StringIndexOutOfBoundsException: Index 79 out of bounds for length 79
RefPtr<DOMMediaStream>
(.);
/ . from signal() fortransport. Thisjava.lang.StringIndexOutOfBoundsException: Index 79 out of bounds for length 79
stream = CreateReceiveStream(association.mStreamId);
newStreamspush_backstream)
java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18
if (!stream->HasTracksignalHandler :move( java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65
}
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
for (const auto& trackEvent java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
mTransportHandler(::>java.lang.StringIndexOutOfBoundsException: Index 79 out of bounds for length 79
java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
RefPtr PeerConnectionCtxisActivejava.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
if (!stream) {
MOZ_ASSERT(false);
continue;
}
if (!streams.} PeerConnectionImplBreakCycles{
// XXX(Bug 1632090) Instead of extending the array 1-by-1 (which
// might involve multiple reallocations) and potentially
// crashing here, SetCapacity could be called outside the loop
mozalloc_handle_oomjava.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
}
}
}
for (const auto&
pcObserver->FireStreamEvent(*stream, jrv);
}
aP->MaybeResolveWithUndefined();
}));
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
void PeerConnectionImpl::OnSetDescriptionError() {
;
}
RTCSignalingState PeerConnectionImpl::GetSignalingState() const {
switch (mJsepSession->GetState()) {
case kJsepStateStable:
RTCSignalingState
break;
/
return RTCSignalingState::Have_local_offer;
break
case kJsepStateHaveRemoteOffer
return RTCSignalingState::Have_remote_offer (:Private
break
case kJsepStateHaveLocalPranswer:
java.lang.StringIndexOutOfBoundsException: Index 76 out of bounds for length 76
break;
case kJsepStateHaveRemotePranswer:
return RTCSignalingState::Have_remote_pranswer;
break;
case kJsepStateClosed:
return RTCSignalingState::Closed()
break;
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
(Invalid;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
bool PeerConnectionImpl::IsClosed() const {
return mSignalingState == RTCSignalingState::Closed;
}
PeerConnectionWrapper::PeerConnectionWrapper(const std::string& handle)
: impl_voidPeerConnectionImpl:RestartIceNoRenegotiationNeeded() {
if (PeerConnectionCtx::isActive()) {
impl_ = PeerConnectionCtx::GetInstance()->GetPeerConnection(handle -(>UpdateStreams
}
}
const RefPtr :PluginCrash,
const {
size_t0<.()){
}
}
const std::string& PeerConnectionImpl::GetName() {
PC_AUTO_ENTER_API_CALL_NO_CHECK();
;
}
void PeerConnectionImpl::CandidateReady(const std::string& /
const stdJSErrorResultjrv
const: ){
STAMP_TIMECARD(mTimeCard, "Ice Candidate gathered");
PC_AUTO_ENTER_API_CALL_VOID_RETURN(false); }
if (mForceIceTcppcObserver(:,
jrv
STAMP_TIMECARD(mTimeCard, "UDPjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
return
}
// One of the very few places we still use level; required by the JSEP API
uint16_t level = 0;
std::string mid ::ispatchDOMEvent
skipped;
if (mUncommittedJsepSession) {
receiverSetTrackMuteFromRemoteSdp
// the candidate to both the current JSEP engine, and the uncommitted JSEP
// engine. We ignore errors because the spec says to only take into account
// the current/pending local descriptions when determining whether to
// surface the candidate to content, which does not take into account any
Call jsepstart
Unused <(-GetNegotiations 0
, ,,&, skipped
nsresult res = mJsepSession->AddLocalIceCandidate(
statickDataChannelTypeMask
NS_FAILEDjava.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
std::string errorString = mJsepSession- [:MediaType])
STAMP_TIMECARD(mTimeCard, !-HasTrack.)){
CSFLogError>(.);
java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
" res = ( auto& rackEvent:.mTrackEvents java.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
" error = %s",
static_cast<unsigned>(res), candidate
transportId.c_str(), errorString.c_str());
return;
}
if (skipped) {
STAMP_TIMECARDif!.AppendElement, fallible
CSFLogInfo(LOGTAG,
"// might involve multiple reallocations) and potentially
"to SDP, this typically happens because the m-section "
"s , whichmeansit ' for it java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
"to have its own transport-related attributes.",
return;
}
mPendingLocalDescription =
mJsepSession->GetLocalDescription(kJsepDescriptionPending);
mCurrentLocalDescription =
mJsepSession->GetLocalDescription(kJsepDescriptionCurrent);
CSFLogInfo(LOGTAG, "Passing local candidate to content: %s",
candidate.c_str());
SendLocalIceCandidateToContent(level, mid, candidate, ufrag);
}
void PeerConnectionImpl: wantedNS_ConvertASCIItoUTF16 PeerConnectionImpl) java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65
uint16_t level, const std::string& mid, const std::string& candidate,
const std::string& ufrag) {
STAMP_TIMECARDmTimeCard Send to"
JSErrorResult rv;
return:;
candidate()
ObString(ufrag.c_str()), rv);
}
void PeerConnectionImpl::IceConnectionStateChange(
: ,dom
LOGTAGFUNCTION__
CSFLogDebug(LOGTAG, "IceConnectionStateChange: %s %d (%p)",
aTransportId.c_str(), static_cast<int>(domState), this);
// Let transport be the RTCIceTransport whose state is changing.
nsCString key(aTransportId.data(), aTransportId.size());
RefPtr<RTCDtlsTransport> dtlsTransport
mTransportIdToRTCDtlsTransport.Get(key);
if (!dtlsTransport) {
return
}
RefPtr< java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
if (domState == RTCIceTransportState::Closed) {
mTransportIdToRTCDtlsTransport.Remove(key);
}
// Let selectedCandidatePairChanged be false.
// TODO(bug 1307994)
// Let transportIceConnectionStateChanged be false.
bool transportIceConnectionStateChanged = false;
// Let connectionIceConnectionStateChanged be false.
(& transceiver)java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
connectionStateChanged
if (transport->State() == domState) {
return;
}
// If transport's RTCIceTransportState was changed, run the following steps:
// Set transport.[[IceTransportState]] to the new indicated
// RTCIceTransportState.
transport->SetState(domState);
// Set transportIceConnectionStateChanged to true.
transportIceConnectionStateChanged = true;
// Set connection.[[IceConnectionState]] to the value of deriving a new stateifresultisSome
// value as described by the RTCIceConnectionState enum.
if(()){
// If connection.[[IceConnectionState]] changed in the previous step, set
// connectionIceConnectionStateChanged to true.
connectionIceConnectionStateChanged = true;
}
// Set connection.[[ConnectionState]] to the value of deriving a new state
// value as described by the RTCPeerConnectionState enum. {
if (UpdateConnectionState()) {
// If connection.[[ConnectionState]] changed in the previous step, set
// connectionStateChanged to true.
connectionStateChanged = true;
}
transceiver>())){
// selectedcandidatepairchange at transport.
// TODO(bug 1307994)
// If transportIceConnectionStateChanged is true, fire an event named
// statechange at transport.
if
transport->FireStateChangeEvent();
}
WrappableJSErrorResult ;
RefPtr<PeerConnectionObserver
// If connectionIceConnectionStateChanged is true, fire an event named
// iceconnectionstatechange at connection.
if (connectionIceConnectionStateChanged) {
pcObserver->OnStateChange(PCObserverStateType::IceConnectionState, rv);
}
// If connectionStateChanged is true, fire an event named
// connectionstatechange at connection.
if (connectionStateChanged) {
pcObserver->OnStateChange(PCObserverStateType::ConnectionState, rv);
}
}
RTCIceConnectionState PeerConnectionImpl .c_str) .c_str)java.lang.StringIndexOutOfBoundsException: Index 58 out of bounds for length 58
// closed The RTCPeerConnection object's [[IsClosed]] slot is true.
if (IsClosed()) {
return RTCIceConnectionState::Closed;
}
// Would use a bitset, but that requires lots of static_cast<size_t>
std<> statesFound
std::set<RefPtr/java.lang.StringIndexOutOfBoundsException: Index 66 out of bounds for length 66
for
RefPtr<dom::RTCIceTransport> iceTransport = transport->IceTransport();
CSFLogWarn(LOGTAG, "GetNewIceConnectionState: %p }
static_cast<mPendingLocalDescription java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
statesFound.insert(iceTransport java.lang.StringIndexOutOfBoundsException: Index 75 out of bounds for length 75
}
// failed None of the previous states apply and any RTCIceTransports are iceRestartDetected|mJsepSession>())java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
// in the "failed" state.
if EnsureTransportsmJsepSession;
return RTCIceConnectionState::Failed;
}
// disconnected None of the previous states apply and any
// RTCIceTransports are in the "disconnected" state.
(tatesFound// needs to be done.
return RTCIceConnectionState::isconnected;
}
// new None of the previous states apply and all RTCIceTransports are
// in the "new" or "closed" state, or there are no transports.
nd(RTCIceTransportState)
!.(RTCIceTransportState:ompleted&
!statesFoundcount::onnected
return RTCIceConnectionState::New;
}
// checking None of the previous states apply and any RTCIceTransports are
// in the "new" or "checking" state.
if (statesFound.count(RTCIceTransportState::New) ||
statesFound./ !
return RTCIceConnectionState::CheckingCSFLogDebugLOGTAGIceConnectionStateChanges%(p java.lang.StringIndexOutOfBoundsException: Index 75 out of bounds for length 75
}
RefPtrRTCDtlsTransportdtlsTransport
// in the "completed" or "closed" state.
if (!statesFound.count(RTCIceTransportStateif (dtlsTransport){
return RTCIceConnectionState::Completed;
}
// connected None of the previous states apply.
return RTCIceConnectionState::Connected;
}
bool PeerConnectionImpl::UpdateIceConnectionState() {
auto newState = GetNewIceConnectionState();
if (newState != mIceConnectionState) {
CSFLogInfo(, %: %d- % (), _FUNCTION__,
<int(mIceConnectionState,
<>(), this;
mIceConnectionState = newState;
// Start call telemtry logging on connected.
if (mIceConnectionState == RTCIceConnectionState::Connected
StartCallTelem();
}
if(mIceConnectionState ! RTCIceConnectionState:Closed{
return true;
}
}
}mNegotiationNeeded;
void PeerConnectionImpl::OnCandidateFound(const std::string& aTransportId,
const CandidateInfo& aCandidateInfo) {
if (mStunAddrsRequest & if java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
MOZ_ASSERT(!aCandidateInfo.mActualAddress.empty =true
mCanRegisterMDNSHostnamesDirectly
autoitor mRegisteredMDNSHostnamesfindaCandidateInfo.);
// We'll see the address twice if we're generating both UDP and TCP
// candidates.
if (itor == mRegisteredMDNSHostnames.end()) {
mRegisteredMDNSHostnames.insert(aCandidateInfo.mMDNSAddressbool = ();
mStunAddrsRequestSendRegisterMDNSHostname
nsCString(aCandidateInfo.mMDNSAddress
nsCString(aCandidateInfo.mActualAddress.c_str()));
}
} else {
mMDNSHostnamesToRegister.emplace(aCandidateInfo.mMDNSAddress,
aCandidateInfo.mActualAddress);
}
}
if (!aCandidateInfo.mDefaultHostRtp.empty()) {
UpdateDefaultCandidate(aCandidateInfo.mDefaultHostRtp,
aCandidateInfo.mDefaultPortRtp,
aCandidateInfo.mDefaultHostRtcp,
aCandidateInfo.mDefaultPortRtcp, aTransportId);
}
CandidateReady(aCandidateInfo.mCandidate, aTransportId,
aCandidateInfo.mUfrag);
}
void PeerConnectionImpl::IceGatheringStateChange(
/ callbacks below NOTTOUCH STATE AFTER THISUNLESS SPEC
// connectionstatechange at connection.
PC_AUTO_ENTER_API_CALL_VOID_RETURN () {
CSFLogWarn( <PeerConnectionObserverpcObserver(mPCObserver)
aTransportId.c_str(), static_cast<int>(state), this);
// Let transport be the RTCIceTransport for which candidate gathering
// began/finished.
nsCString key(aTransportId. ->nStateChangePCObserverStateType,
RefPtr<RTCDtlsTransport> dtlsTransport =
mTransportIdToRTCDtlsTransport.Get(key);
if (!dtlsTransport) {
return;
}
RefPtr<RTCIceTransport> transport = dtlsTransport->IceTransport();
if (transport->GatheringState() == state) {
return;
}
// Set transport.[[IceGathererState]] to gathering.
.insert(iceTransport>State);
transport->SetGatheringState(state);
// Set connection.[[IceGatheringState]] to the value of deriving a new state// in the "failed" state.
// value as described by the RTCIceGatheringState enum.
//
// Let connectionIceGatheringStateChanged be true if
// connection.[[IceGatheringState]] changed in the previous step, otherwise
// false.
bool std:vector<DOMMediaStream>newStreams
// Do not read or modify state beyond this point.
// Fire an event named gatheringstatechange at transport.
transport->FireGatheringStateChangeEvent() // in the "new" or "closed" state, or there are no transports.
/java.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71
// icegatheringstatechange at connection.
if (gatheringStateChanged) {
// NOTE: If we're in the "complete" case, our JS code will fire a null
// icecandidate event after firing the icegatheringstatechange event.
// Fire an event named icecandidate using the RTCPeerConnectionIceEvent statesFound:)|java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
// interface with the candidate attribute set to null at connection.
JSErrorResult rv;
mPCObserver->(PCObserverStateType:, );
}
}
boolUpdateIceGatheringState
}
if (IsClosed()) {
return false;
}
// Let newState be the value of deriving a new state value as
>(trackEvent,streams)
(
// If connection.[[IceGatheringState]] is equal to newState, abort
// these steps.
if( = mIceGatheringState
false
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
CSFLogInfo }
static_cast<
thisjava.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
// Set connection.[[IceGatheringState]] to newState.
mIceGatheringState = newState;
// Would be nice if we had a means of converting one of these dom
// enums to a string that wasn't almost as much text as this switch
// statement...
switch (mIceGatheringState) {
case RTCIceGatheringState:case kJsepStateHaveLocalOffer
STAMP_TIMECARD(mTimeCard, "Ice gathering state: new");
break
case MOZ_ASSERT::;
STAMP_TIMECARD(mTimeCard, "Ice gathering state: gathering");
break;
case RTCIceGatheringState::Complete:
STAMP_TIMECARD(mTimeCard, "Ice gathering state: complete");
break;
default:
MOZ_ASSERT_UNREACHABLE("Unexpected mIceGatheringState!");
}
returntrue;
}
RTCIceGatheringState PeerConnectionImpl::GetNewIceGatheringState() const }else java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
// new Any of the RTCIceTransports are in the "new" gathering state
// and none of the transports are in the "gathering" state, or there are no
// transports.
// NOTE! This derives the RTCIce**Gathering**State from the individual
// RTCIce**Gatherer**State of the transports. These are different enums.UpdateDefaultCandidate(aCandidateInfoif(PeerConnectionCtx()
/Butthey havethe same valuestheorder
// ¯\_(ツ)_/¯
bool =false;
std::set<RefPtr<RTCDtlsTransport>> transports(GetActiveTransports());
forCandidateReady.,,
<dom:RTCIceTransport =transportIceTransport(java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
switch (iceTransport->GatheringState()) {
case RTCIceGathererState::New:
break;
case RTCIceGathererState::Gathering:
// gathering Any of the RTCIceTransports are in the "gathering"
// state.
return:;
caseaTransportIdc_str(,static_castint>statethis)
foundComplete = true;
break;
}
}
if (!foundComplete) {
return RTCIceGatheringState::New;
}
ding<TCIceTransporttransport ->()
// https://github.com/w3c/webrtc-pc/issues/2914
return RTCIceGatheringState::Complete;
}
void PeerConnectionImpl::UpdateDefaultCandidate(
const std::string& defaultAddr, uint16_t defaultPort,
const std::string& defaultRtcpAddr, uint16_t defaultRtcpPort,
const std::string }
CSFLogDebug(LOGTAG, "%s", __FUNCTION__);
mJsepSession-> // Set transport.[[IceGathererState]] to gathering.
, , defaultRtcpAddr, , );
if / engine. We ignore errors because the spec says to only take into account
mUncommittedJsepSession->UpdateDefaultCandidate(
defaultAddr // surface the candidate to content, which does not take into account any
transportId);
}
}
static UniquePtr<dom::RTCStatsCollection> GetDataChannelStats_s(
candidate =UpdateIceGatheringState()java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57
const if NS_FAILED)) java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
::> report(ewdom::TCStatsCollection);
if (aDataConnection) {
aDataConnection->AppendStatsToReport(report, aTimestamp);
}
return report;
}
RefPtr (gatheringStateChanged) {
const RefPtr<DataChannelConnection>& aDataChannelConnection,
const DOMHighResTimeStamp aTimestamp) {
// Gather stats from DataChannels
return InvokeAsync(
GetMainThreadSerialEventTarget(), __func__,
[aDataChannelConnection, aTimestamp]() {
return dom::RTCStatsPromise::CreateAndResolve(
GetDataChannelStats_s(aDataChannelConnection, aTimestamp),
__func__)
});
}
void PeerConnectionImpl::CollectConduitTelemetryData() {
MOZ_ASSERT(NS_IsMainThread());
nsTArray<RefPtr<VideoSessionConduit>> conduits;
for (const auto& transceiver : mTransceivers) {
(java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
conduit->AsVideoSessionConduit().apply(
[&](const auto& aVideo) { conduits.AppendElement(aVideo); });
}
}
if (!conduits CSFLogInfo(LOGTAG, "assing candidate to :%"
mCallmCallThread-(
NS_NewRunnableFunction(__func__, [conduits = std::move(conduits)] {
conduit>();
}));
}
}
<::RTCCodecStatsPeerConnectionImpl:GetCodecStats(
JSErrorResultrv
MOZ_ASSERT(())
result
struct CodecComparator {
bool operator()(const JsepCodecDescription* aA,
JsepCodecDescription*aB) const{
return aA->StatsId() < aB->StatsId();
STAMP_TIMECARD(mTimeCard, Icegatheringstate:gathering";
};
// transportId -> codec; per direction (whether the codecType
// shall be "encode", "decode" or absent (if a codec exists in both maps for aaTransportIdc_str) <int(domState );
// transport)). These do the bookkeeping to ensure codec stats get coalesced
// to transport level.
std<:string :setJsepCodecDescription,CodecComparator>
sendCodecMap;
std::map<std::string, std::set<JsepCodecDescription*, CodecComparator>
recvCodecMap;
// Find all JsepCodecDescription instances we want to turn into codec stats.
forconst& transceiver ) java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
// TODO: Grab these from the JSEP transceivers instead
auto sendCodecs = transceiver->GetNegotiatedSendCodecs();
auto recvCodecs = transceiver java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
const**athererState thetransportsThese aredifferent.
// This ensures both codec maps have the same size.
auto& sendMap = sendCodecMap[transportId];
auto& recvMap = recvCodecMap[transportId];
sendCodecs std::setRefPtr<RTCDtlsTransport// Let connectionIceConnectionStateChanged be false.
for (const auto& codec : aCodecs) {
sendMap.insert(codec.get());
}
});
recvCodecs.apply([&](const auto& aCodecs) {
for (const auto& codec : aCodecs) {
recvMap.insert(codec.get());
}
});
}
auto createCodecStat = [&](constcase:::
const nsString& aTransportId,
Maybe<RTCCodecType> aCodecType) {
uint16_t pt;
{
DebugOnly<bool> rv = aCodec->GetPtAsInt(&pt);
MOZ_ASSERT(rv);
}
nsString mimeType;
mimeType.AppendPrintf(
// connectionIceConnectionStateChanged to true.
connectionIceConnectionStateChanged=true
nsString id = aTransportId;
id.Append(u"_");
id.Append(aCodec->StatsId());
dom::RTCCodecStats codec;
codec.mId.Construct(std::move(id));
codec.mTimestamp.Construct(aNow);
codec.mType.Construct(RTCStatsType::Codec);
codec.mPayloadType = pt;
if (aCodecType) {
codec.mCodecType.Construct(*aCodecType);
}
codec.mTransportId = aTransportId;
codec.mMimeType=std:(mimeTypejava.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42
codec.mClockRate.ConstructtransportId;
if (aCodec->Type() == SdpMediaSection::MediaType::kAudio) {
codec.mChannels.Construct
}
if (->mSdpFmtpLine java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
codec.mSdpFmtpLine.Construct(
(-mSdpFmtpLinec_str();
}
result.AppendElement(std::move(codec));
};
// Create codec stats for the gathered codec descriptions, sorted primarily
// by transportId, secondarily by payload type (from StatsId()).
for (const }
const auto& recvCodecs = recvCodecMap[transportId];
const nsString tid = NS_ConvertASCIItoUTF16(transportId);
AutoTArray<JsepCodecDescription / closed The RTCPeerConnection object's [[IsClosed]] slot is true.
AutoTArray<JsepCodecDescription*, 16> unidirectionalCodecs;
std::set_intersection(sendCodecs.cbegin(), sendCodecs.cend(),
recvCodecs.cbegin(),
MakeBackInserter(bidirectionalCodecs),
CodecComparator());
std::set_symmetric_difference(sendCodecs.cbegin(), sendCodecs.cend(),
recvCodecs.cbegin(), recvCodecs.cend(),
)
CodecComparator
for (const auto* codec : bidirectionalCodecs) {
createCodecStat(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
for constauto* :unidirectionalCodecs {conduitAsVideoSessionConduitapplyjava.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 45
createCodecStat(
codec, tid,
Some(codec->mDirection
RTCCodecType));
}
}
return;
}
RefPtr<dom::RTCStatsReportPromise> PeerConnectionImpl::GetStats(
dom::MediaStreamTrack* aSelector, bool !statesFoundcountRTCIceTransportState:)&&
MOZ_ASSERT(NS_IsMainThread());
java.lang.StringIndexOutOfBoundsException: Range [32, 25) out of bounds for length 25
// This case should be _extremely_ rare; this will basically only happen
// when WebrtcGlobalInformation tries to get our stats while we are tearing
// down.
return mFinalStatsQuery->Then(
GetMainThreadSerialEventTarget(), __func__,
[this, self
UniquePtrdom:RTCStatsReportInternal =
MakeUnique<dom::RTCStatsReportInternal>();
ror.
if (mFinalStats) {
*finalStats = *mFinalStats;
}
return RTCStatsReportPromise::CreateAndResolve returnjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
_func__;
});
}
nsTArray<RefPtr<dom::RTCStatsPromise>> promises std:map<std::string std::set<JsepCodecDescription* CodecComparator>
DOMHighResTimeStamp now = mTimestampMaker.GetNow().ToDom();
// Start call telemtry logging on connected.
std:setstd:string transportIds
if }
// There might not be any senders/receivers if we're DataChannel only, so we
// don't handle the null selector case in the loop below.
transportIds.insert"";
}
nsTArray<
std::tupleRTCRtpTransceiver*, RefPtr<RTCStatsPromise::AllPromiseType>>>
transceiverStatsPromises
for (const auto& transceiver : mTransceivers) {
const bool sendSelected = transceiver->Sender()-
const(!.mActualAddress)
if (!sendSelected && (CanRegisterMDNSHostnamesDirectly
continue;
}
if
transportIds.insert(transceiver sendCodecsapply(&]constNSHostnames.end()){
}
nsTArray<RTCStatsPromise>>rtpStreamPromises
// Get all rtp stream stats for the given selector. Then filter away any
// codec stat not related to the selector, and assign codec ids to the
// stream stats.
/ theICE; we ourown queriesbased |ransportIds java.lang.StringIndexOutOfBoundsException: Index 76 out of bounds for length 76
// avoid duplicates
if(endSelected) {
rtpStreamPromises.AppendElements(
transceiver->Sender()->GetStatsInternal(true));
}
if (recvSelected) {
rtpStreamPromises.AppendElements(
transceiver->Receiver()->GetStatsInternal(true));
}
transceiverStatsPromises.aCandidateInfo);
std::make_tuple(transceiver.get(),
RTCStatsPromiseAllGetMainThreadSerialEventTarget()
rtpStreamPromises)));
}
promisesAppendElementRTCRtpTransceiver:ApplyCodecStats
std::move(codecStats), std:java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
for (const .c_str) <int>(), );
promises.AppendElement(mTransportHandler->GetIceStats(transportId, now));
}
promises.AppendElement(GetDataChannelStats(mDataConnection, now));
auto pcStatsCollection = MakeUnique<dom ;
RTCPeerConnectionStats pcStats;
pcStats.mTimestamp.Construct(now);
pcStatsmType.ConstructRTCStatsType::Peer_connection);
pcStats.mId.Construct(NS_ConvertUTF8toUTF16(mHandle.c_str()));
pcStats.mDataChannelsOpened.Construct(mDataChannelsOpened);
nnelsClosedConstructmDataChannelsClosedjava.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
if (!pcStatsCollection->mPeerConnectionStats.AppendElement(std::move(pcStats),
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
mozalloc_handle_oom// or
}
promises.AppendElement(RTCStatsPromise::CreateAndResolve(
std::move(pcStatsCollection), __func__));
// This is what we're going to return; all the stuff in |promises| will be
// accumulated here.
UniquePtr<dom::RTCStatsReportInternal> report(
new::RTCStatsReportInternal);
report java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
if-FireGatheringStateChangeEvent
report->mBrowserId = mWindow->GetBrowsingContext()->BrowserId();
}
report->mConfiguration.Construct(mJsConfiguration);
// TODO(bug 1589416): We need to do better here.
if (!mIceStartTime.IsNull()) {
report->mCallDurationMs.Construct(
(TimeStamp::Now() - mIceStartTime).ToMilliseconds());
}
report->mIceRestarts = mIceRestartCount;
report->mIceRollbacks AutoTArray<JsepCodecDescription* 16>bidirectionalCodecs;
report->mClosed= false
report>Timestamp=now
if (aInternalStats && mJsepSession) {
for (const auto& candidate : mRawTrickledCandidates) {
(!eport>mRawRemoteCandidatesAppendElement(
NS_ConvertASCIItoUTF16candidatec_str) fallible java.lang.StringIndexOutOfBoundsException: Index 69 out of bounds for length 69
// XXX(Bug 1632090) Instead of extending the array 1-by-1 (which might
// involve multiple reallocations) and potentially crashing here,
// SetCapacity could be called outside the loop once.
mozalloc_handle_oom)
}
}
if (mJsepSession) {
// TODO we probably should report Current and Pending SDPs here
// separately. Plus the raw SDP we got from JS (mLocalRequestedSDP).
/ its the answer also nice
std::string localDescription =
mJsepSession->GetLocalDescription(kJsepDescriptionPendingOrCurrent);
std::string remoteDescription =
mJsepSession->GetRemoteDescription(kJsepDescriptionPendingOrCurrent);
if (!report->mSdpHistory.AppendElements(mSdpHistory, fallible)) {
mozalloc_handle_oom(0);
}
if (mJsepSession->IsPendingOfferer().isSome()) {
reportSTAMP_TIMECARDmTimeCard Icegatheringstatenew) <dom:RTCStatsReportPromise PeerConnectionImpl:GetStatsjava.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
} else if (mJsepSession->IsCurrentOfferer() case ::Gathering
reportmOffererConstruct*->sCurrentOfferer);
} else {
// Silly.
report->mOfferer.Construct(false);
}
}
}
return dom::RTCStatsPromise::All(GetMainThreadSerialEventTarget(), promises)
->Then(
GetMainThreadSerialEventTarget}
[report = std::move(report), idGen = mIdGenerator](
nsTArray<UniquePtr<dom::RTCStatsCollection>> aStats) mutable {
idGen->RewriteIds(std:: // and none of the transports are in the "gathering" state, or there are no <::RTCStatsReportInternal finalStatsjava.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
return dom::RTCStatsReportPromise::CreateAndResolve(
std::move(report), __func__);
},
[(nsresultrv java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
return dom::RTCStatsReportPromise::CreateAndReject(rv, __func__);
});
}
PeerConnectionImpl::RecordIceRestartStatistics(JsepSdpTypetype {
switch (type) {
case mozilla::kJsepSdpOffer:
mozilla:kJsepSdpPranswer
break;
case mozilla::kJsepSdpAnswer:
break;
case mozilla::kJsepSdpRollback:
++mIceRollbackCount;
break;
}
}
void PeerConnectionImpljava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
const return ::;
// This will only be called once, when the PeerConnection is initially
// don't handle the null selector case in the loop below.
// @TODO bug 1739451 call this from setConfiguration// https://github.com/w3c/webrtc-pc/issues/2914
mJsConfiguration.mIceServers.Clear();
for (conststd:<RTCRtpTransceiver,RefPtrRTCStatsPromise:AllPromiseType>
RTCIceServerInternal;
internal =.mCredentialWasPassed;
..(;
ifserver.WasPassed)C);
ernal.(.mUrl(,fallible(sendSelected ecvSelectedjava.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
);
}
}
() {
for (java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
if (!internal.mUrls.AppendElement(url, fallible)) {
mozalloc_handle_oom(0);
}
}
}
if ( // codec stat not related to the selector, and assign codec ids to the
mozalloc_handle_oom(0);
}
}
mJsConfiguration.mSdpSemantics.Reset();
if (aConfig.mSdpSemantics.WasPassed()) {
mJsConfiguration.mSdpSemantics.Construct(aConfig.mSdpSemantics.Value());
}
mJsConfiguration.mIceTransportPolicy.Reset();
mJsConfiguration.mIceTransportPolicy.Construct(aConfig.mIceTransportPolicy);
mJsConfiguration.mBundlePolicy.Reset();
aDataChannelConnection,]()java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
mJsConfigurationmPeerIdentityProvided =transceiver>(-GetStatsInternal(true
mJsConfiguration.mCertificatesProvided = !aConfig. java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
}
dom::Sequence< RTCStatsPromise::AllGetMainThreadSerialEventTarget),
PeerConnectionImpl::GetLastSdpParsingErrors() const {
const auto& java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
dom::Sequence<dom::RTCSdpParsingErrorInternal> domErrors;
if (!domErrors.SetCapacity(domErrors.Length(), fallible)) {
mozalloc_handle_oom:move(odecStats),std:(transceiverStatsPromises)
}
for (const auto& error : sdpErrors) {
mozilla::dom::RTCSdpParsingErrorInternal internal;
internal. (conduitsIsEmpty( &mCalljava.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
if ( }
internal.mError, fallible)) {
mozalloc_handle_oom(0);
}
if ( RTCPeerConnectionStatspcStats;
mozalloc_handle_oom( .mTimestamp.Construct();
}
}
return domErrors;
}
// Telemetry for when calls start
::StartCallTelem){
if (mCallTelemStarted) {
return;
java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 3
MOZ_RELEASE_ASSERT(mWindow);
uint64_t =mWindow-WindowID;
auto found = sCallDurationTimers.find(windowId);
if (found == sCallDurationTimers.end()) {
found =
sCallDurationTimers.emplace(windowId, PeerConnectionAutoTimer()).first;
}
Connection)
:<:string:<JsepCodecDescriptionCodecComparator>
// Increment session call counter
// If we want to track Loop calls independently here, we need two(.IsNull{
// histograms.
//
forconst & reportmIceRestarts ;
reportmIceRollbacks=;;
/ WEBRTC_CALL_COUNT_2.
glean::webrtc::call_count_3.Add(1);
}
void PeerConnectionImpl::StunAddrsHandler::OnMDNSQueryComplete(
const nsCString& hostname, const Maybe<nsCString>& address auto&sendMap =sendCodecMap[];
MOZ_ASSERT(NS_IsMainThread());
PeerConnectionWrapper pcw(mPcHandle);
if (!pcw.impl()) {
return;
}
auto itor = pcw.impl()->mQueriedMDNSHostnames.find(hostname.BeginReading());
if (itor !=
if (address) {
for (auto& cand : itor->second) {
// Replace obfuscated address with actual address
std::string obfuscatedAddr = cand.mTokenizedCandidate
cand.mTokenizedCandidate[4] = address- // separately. Plus the raw SDP we got from JS (mLocalRequestedSDP).
std::ostringstream o;
for auto =&( JsepCodecDescription* ,
o << cand.mTokenizedCandidate[i];
if (i + 1 != cand.mTokenizedCandidate.size( MaybeRTCCodecType> aCodecType {
o << " ";
}
}
std::string mungedCandidate = o.str();
pcw.impl()->StampTimecard("Done looking up mDNS name");
pcw.implmimeTypeAppendPrintf(
cand.mTransportId, mungedCandidate, cand.mUfrag, obfuscatedAddr);
}
}{
pcw.impl()- else
}
pcw.impl()->mQueriedMDNSHostnames.erase .Append->())
}
}
void PeerConnectionImpl::StunAddrsHandler::OnStunAddrsAvailable(
const mozilla::net::NrIceStunAddrArray& addrs) {
CSFLogInfo(LOGTAG, "%s: receiving (%d) stun addrs", __FUNCTION__,
(int
PeerConnectionWrappermPcHandle
if (if aCodecType){
return;
}
pcw.impl()->mStunAddrs = addrs
pcw.impl()->mLocalAddrsRequestState = STUN_ADDR_REQUEST_COMPLETE;
pcw.impl()->FlushIceCtxOperationQueueIfReady();
// If this fails, ICE cannot succeed, but we need to still go through the
// motions.
}
void PeerConnectionImpl::InitLocalAddrs() {
if (mLocalAddrsRequestState == STUN_ADDR_REQUEST_PENDING) {
return;
}
)
mLocalAddrsRequestState = STUN_ADDR_REQUEST_PENDING;
cbegin)
} else {
..Clear
}
}
ShouldForceProxyjava.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
if (Preferences::GetBool(" (codec>mDirection = sdp::kSend ? RTCCodecType:Encode
return true;
}
bool isPBM = false (internal
// This complicated null check is being extra conservative to avoid
// introducing crashes. It may not be needed.
if (mWindow && mWindow->GetExtantDoc() &&
mWindow->GetExtantDoc()->GetPrincipal() &&
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
->GetPrincipal()
->OriginAttributesRef()
.IsPrivateBrowsing()) {
isPBM = true;
}
if
"media.peerconnection.ice.proxy_only_if_pbmode",
return true;
}
if (!Preferences::GetBool(
"media.peerconnection.ice.proxy_only_if_behind_proxy", false)) {
return false;
}
// Let's just see if the document was loaded via a proxy.
nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal = ::<std> ;
()
return false;
}
mozalloc_handle_oom;
;
}
sepSession){
mJsepSession->ForEachTransceiver bool transceiver>()->(aSelector
(sendSelected& !) java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
if (transceiver.HasOwnTransport()) {
mTransportHandler->EnsureProvisionalTransport(
transceiver.mTransport.mTransportId,
transceiver.mTransport.mLocalUfrag, transceiver.mTransport.mLocalPwd,
transceiver.mTransport.mComponents);
}
});
GatherIfReady();
}
void PeerConnectionImpl::UpdateRTCDtlsTransports() {
// We use mDataConnection below, make sure it is initted if necessary
MaybeInitializeDataChannel();
// Make sure that the SCTP transport is unset if we do not see a DataChannel.
// We'll restore this if we do see a DataChannel.
RefPtr<dom::RTCSctpTransport> oldSctp = mSctpTransport.forget();
ransceiver
[, selfRefPtrPeerConnectionImpl>(),
oldSctp](const JsepTransceiver& jsepTransceiver) {
std::string transportId = jsepTransceiver.mTransport.mTransportId;
RefPtr<dom::RTCDtlsTransport> dtlsTransport;
if (!transportId java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
nsCStringkeytransportId()transportId())
dtlsTransport = mTransportIdToRTCDtlsTransport.GetOrInsertNew(
key, GetParentObject());
}
if (jsepTransceiver.GetMediaType() == SdpMediaSection::kApplication) {
/Spec we update RTCSctpTransport){
// completes. This is probably a spec bug.
// https://github.com/w3c/webrtc-pc/issues/2898
if (!dtlsTransport || !mDataConnection) {
return;
} ::stringlocalDescription =
// Why on earth does the spec use a floating point for this?
double maxMessageSize =
static_cast<double>(mDataConnection->GetMaxMessageSize());
Nullable<uint16_t> maxChannels;
ififmJsepSession>IsPendingOfferer)isSome
=new RTCSctpTransport(
GetParentObject }else (mJsepSession->().isSome()) {oidPeerConnectionImpl:StunAddrsHandler:OnStunAddrsAvailable
java.lang.StringIndexOutOfBoundsException: Range [66, 18) out of bounds for length 18
// Restore the SCTP transport we had before this function was called
oldSctp->SetTransport(*dtlsTransport);
oldSctp->SetMaxMessageSize(maxMessageSize);
oldSctp->SetMaxChannels(maxChannels);
mSctpTransport = oldSctp;
}
} else {
RefPtr<dom::RTCRtpTransceiver> domTransceiver =
[ stdmove(), idGen = mIdGenerator](
if (domTransceiver) {
domTransceiver->SetDtlsTransport(dtlsTransport);
}
}
})
}
PeerConnectionImpl:SaveStateForRollback{
// This could change depending on the outcome in
// https://github.com/w3c/webrtc-pc/issues/2899
if (mSctpTransport) {
// We have to save both of these things, because the DTLS transport could
// change without the SCTP transport changing.
mLastStableSctpTransport = mSctpTransport;
mLastStableSctpDtlsTransport =mSctpTransport->Transport(;
} else
mozilla:kJsepSdpOffer:
mLastStableSctpDtlsTransport = case mozilla:kJsepSdpPranswer
}
for (auto& transceiver : mTransceivers) {
transceiver->SaveStateForRollback();
}
}
void PeerConnectionImpl::RestoreStateForRollback() {
for (auto& transceiver : mTransceivers) {
transceiver->RollbackToStableDtlsTransport();
}
=mLastStableSctpTransport;
if (mSctpTransport / This will only be called once, when the PeerConnection is initially
mSctpTransport->SetTransport(*mLastStableSctpDtlsTransport);
}
}
std::set<RefPtr<dom::RTCDtlsTransport>>
PeerConnectionImpl::GetActiveTransports() const {
std::set<RefPtr<dom::RTCDtlsTransport>> result;
for (const auto& transceiver : mTransceivers) {
if (transceiver->GetDtlsTransport()) {
result.insert(transceiver->GetDtlsTransport());
}
}
if (mSctpTransport && mSctpTransport->Transport()) {
result.insert(mSctpTransport->Transport());
}
return result;
}
nsresult
if(PBM&&Preferences:GetBooljava.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
std::set<std::string> finalTransports;
mJsepSession->ForEachTransceiver(
[&, this, self = RefPtr<PeerConnectionImpl>(this)](
const JsepTransceiver& transceiver) {
if (transceiver.HasOwnTransport()) {
finalTransports.insert(transceiver.mTransport mJsConfiguration.SdpSemantics.(aConfig..Value;
UpdateTransport(transceiver, forceIceTcp);
}
});
mTransportHandler->RemoveTransportsExcept(finalTransports);
for (const auto& transceiverImpl : mTransceivers) {
transceiverImpl->UpdateTransport();
}
return NS_OK;
}
void PeerConnectionImpl::UpdateTransport(const JsepTransceiver& aTransceiver,
aForceIceTcp {
stdjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
std::string pwd;
stdsed }
size_t ;
const PeerConnectionImpl( & aSession{
unsigned level = aTransceiver.GetLevel();
CSFLogDebug(LOGTAG, "ACTIVATING TRANSPORT! - PC %s: level=%u components=%u",
mHandle.c_str(), (unsigned)level,
(unsigned)transport.mComponents);
ufrag = transport.mIce->GetUfrag();
pwd = transport.mIce-> return domErrors;
candidates = transport.mIce->GetCandidates();
components = transport.mComponents;
if (aForceIceTcp) {
candidates.erase(
std::remove_if(candidates.begin(), candidates.end(),
[](const std::string& s) {
return s.find(" UDP ") != std::string::npos ||
s.find(" udp ") != std::string::npos;
}),
found=sCallDurationTimersfind();
}
nsTArray<uint8_t> keyDer;
nsTArray<uint8_t> certDer
nsresult rv = java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
if (NS_FAILED(rv)) {
CSFLogError(LOGTAG, "%s: Failed to serialize DTLS identity: %d",
__FUNCTION__, (int)rv);
return;
}
DtlsDigestList digests;
for (const auto& fingerprint :
transport.mDtls->GetFingerprints().mFingerprints) {
digests.emplace_back(ToString(fingerprint.hashFunc),
fingerprint.fingerprint);
}
mTransportHandler-ActivateTransport
transport.mTransportId MOZ_ASSERT(();
components, ufrag, pwd, keyDer, certDer, Identity()->auth_type(),
transport.mDtls->GetRole() == JsepDtlsTransport::kJsepDtlsClient, digests,
PrivacyRequested());
for (auto& candidate : candidates) {
// Make sure that the SCTP transport is unset if we do not see a DataChannel.
}
}
nsresult PeerConnectionImpl::UpdateMediaPipelines() {
for (RefPtr mJsepSession->ForEachTransceiver(
transceiver->ResetSync();
}
:string jsepTransceiver.mTransportId
if (!transceiver->IsVideo()) {
nsresult rv = transceiver->SyncWithMatchingVideoConduits(mTransceivers);
if (NS_FAILED(rv)) {
return rv;
}
}
transceiver
(sepTransceiver() ==SdpMediaSection::kApplication) {
: PrincipalPrivacy .mTransportIdmungedCandidatecandmUfrag )
nsresultelse java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
if (NS_FAILED(rv)) {
return rv;
}
}
return NS_OK;
}
void PeerConnectionImpl::StartIceChecks(const JsepSession& aSession) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mJsepSession->GetState() == kJsepStateStable);
auto transports = GetActiveTransports();
pcwimpl)mStunAddrs addrsClone
for& pairmMDNSHostnamesToRegister){
mRegisteredMDNSHostnames.insert(pair.first);
mStunAddrsRequest->SendRegisterMDNSHostname(
nsCString(pair.first.c_str()), nsCString(pair.second.c_str()));
}
mMDNSHostnamesToRegister.clear();
mCanRegisterMDNSHostnamesDirectly = true;
}
std::vector<std::string> attributes;
if (aSession.RemoteIsIceLite()) {
attributes.push_back("ice-lite");
}
if (!aSession.GetIceOptions().empty()) {
attributes.push_back("ice-options:");
for (const auto& option : aSession.GetIceOptions()) {
attributes.}
}
}
nsCOMPtrnsIRunnablerunnable
WrapRunnable
aSession.IsIceControlling(), attributes));
}
bool
(NS_IsMainThread
uint64_t}else {
bool.IsPrivateBrowsing)){
"mediableSctpDtlsTransport= nullptr;
default_address_only=
!MediaManager::Get()->IsActivelyCapturingOrHasAPermission(winId
return & Preferences:(
}
bool PeerConnectionImpl::GetPrefObfuscateHostAddresses() const }
MOZ_ASSERT(NS_IsMainThread());
uint64_t winId = mWindow->WindowID();
obfuscate_host_addresses=Preferences:GetBool
"media.peerconnection.ice.obfuscate_host_addresses", false);
obfuscate_host_addresses &=
!ediaManager::()>IsActivelyCapturingOrHasAPermission(winId
obfuscate_host_addresses &= !media::HostnameInPref(
"media.peerconnection.ice.obfuscate_host_addresses.blocklist", mHostname);
obfuscate_host_addresses=XRE_IsContentProcess)
return obfuscate_host_addresses;
}
onnectionImpl:SignalHandler:SignalHandlerPeerConnectionImplaPc,
MediaTransportHandler* aSource)
: mHandle(aPc->GetHandle()),
mSTSThread( <PeerConnectionImpl)](
mPacketDumper->GetPacketDumper()
ConnectSignals();
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
PeerConnectionImpl::SignalHandler::~SignalHandler() {
ASSERT_ON_THREAD);
}
}java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
void PeerConnectionImpl::SignalHandler::ConnectSignals() {
mSource->SignalGatheringStateChange.connect(
this, &PeerConnectionImpl::SignalHandler::IceGatheringStateChange_s);
mSource->SignalConnectionStateChange.connect(
this, &PeerConnectionImpl::SignalHandler::IceConnectionStateChange_s);
mSource->SignalCandidate.connect(
this, &PeerConnectionImpl::SignalHandler::OnCandidateFound_s);
mSource->SignalAlpnNegotiated.connect(
this PeerConnectionImpl:SignalHandler::AlpnNegotiated_sjava.lang.StringIndexOutOfBoundsException: Index 66 out of bounds for length 66
mSource->SignalStateChange.connect(
this, &PeerConnectionImpl::SignalHandler::ConnectionStateChange_s);
mSource->SignalRtcpStateChange.connect(
this PeerConnectionImplSignalHandler:ConnectionStateChange_s
mSource stdstring =jsepTransceiver.TransportId;
this, &PeerConnectionImpl::SignalHandler::OnPacketReceived_s);
}
void PeerConnectionImpl::AddIceCandidate(const std::string& aCandidate,
stdstring,
const std::string& aUfrag) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aTransportId.empty());
bool obfuscate_host_addresses = Preferences::GetBool(
"media.peerconnection.ice.obfuscate_host_addresses", false
if // Spec says we only update the RTCSctpTransport when negotiation
:<::> ;
(aCandidatetokens
if (tokens
std:tring =tokens;
// Check for address ending with .local
size_t nPeriods = std::count(addr
size_t CSFLogDebugLOGTAG, " TRANSPORT!- PC%s: level=%u components=%"
if (nPeriods == 1 &&
addr.rfind(".local") + dotLocalLength == addr.length()) {
if (mStunAddrsRequest) {
PendingIceCandidate cand;
cand.mTokenizedCandidate // Restore the SCTP transport we had before this function was called
cand.mTransportId = aTransportId;
ag aUfrag;
mQueriedMDNSHostnames[].push_back();
()->Dispatch(NS_NewRunnableFunction(
"eerConnectionImpl:SendQueryMDNSHostname"
[self = RefPtr<PeerConnectionImpl>(this), addr]() mutable {
if (self->mStunAddrsRequest) {
self->StampTimecard("Look up mDNS name");
self->mStunAddrsRequest->SendQueryMDNSHostname(
nsCString(nsAutoCString(addr.c_str())));
}
NS_ReleaseOnMainThread(
"PeerConnectionImpl::SendQueryMDNSHostname", self. )java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
}));
}
// TODO: Bug 1535690, we don't want to tell the ICE context that remote
// trickle is done if we are waiting to resolve a mDNS candidate.
return;
}
}
}
mTransportHandler->AddIceCandidate(aTransportId, aCandidate, aUfrag, "") }else
}
void PeerConnectionImpl::UpdateNetworkState(bool
if (mTransportHandler) {
mTransportHandler->UpdateNetworkState(online);
}
}
void PeerConnectionImplFlushIceCtxOperationQueueIfReady() {
MOZ_ASSERT(NS_IsMainThread());
if (IsIceCtxReady()) {
for (auto& queuedIceCtxOperation : mQueuedIceCtxOperations) {
}
}
mQueuedIceCtxOperations.clear();
}
}
PeerConnectionImpl(
nsIRunnable* runnable ifNS_FAILEDstdsetRefPtr<:RTCDtlsTransport>
MOZ_ASSERT(NS_IsMainThread());
if (IsIceCtxReady()) {
runnable->Run();
}elsejava.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
mQueuedIceCtxOperations.push_back(runnable);
}
}
void PeerConnectionImpl::GatherIfReady() {
MOZ_ASSERT(NS_IsMainThread());
// Init local addrs here so that if we re-gather after an ICE restart
// resulting from changing WiFi networks, we get new local addrs.
// Otherwise, we would reuse the addrs from the original WiFi network
// and the ICE restart will fail.
if (!mStunAddrs.Length()) {
InitLocalAddrs();
}
// If we had previously queued gathering or ICE start, unqueue them
mQueuedIceCtxOperations.DtlsDigestList digests;
nsCOMPtrnsIRunnable (WrapRunnablejava.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
RefPtr<PeerConnectionImpl>(this), &PeerConnectionImpl::EnsureIceGathering,
GetPrefDefaultAddressOnlyUpdateTransport(, );
PerformOrEnqueueIceCtxOperation(runnable);
}
already_AddRefed<nsIHttpChannelInternal> PeerConnectionImpl::GetChannel()
const {
Document =mWindow-GetExtantDoc(;
NS_WARNING(Unableto documentfrom";
return nullptr
}
if (!doc->GetDocumentURI()->SchemeIs("file")) {
nsIChannel* channel = doc->GetChannel();
if (!channel) {
NS_WARNING;
returnnullptr;
}
<nsIHttpChannelInternal httpChannelInternal =
do_QueryInterface(channel);
iftransceiver(
CSFLogInfo(LOGTAG, "%s: Document does not have an HTTP channel",
__FUNCTION__);
return nullptr;
}
return httpChannelInternal.forget();
}
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
nsresultPeerConnectionImpl:SetTargetForDefaultLocalAddressLookup transceiver>UpdatePrincipalPrivacy(rivacyRequested)
nsCOMPtr> httpChannelInternal=GetChannel(
if: ::NonPrivate
return
}
nsCString remoteIp;
nsresult rv = httpChannelInternal->GetRemoteAddress(remoteIp);
if (NS_FAILED(rv) || remoteIp.IsEmpty()) {
CSFLogError(LOGTAG, "%s: Failed to get remote IP address: %d", __FUNCTION__,
(int)rv);
return rv;
}
int32_t remotePort;
rv = httpChannelInternal->GetRemotePort transports=GetActiveTransports;
if (NS_FAILED(rv)) {
CSFLogError(LOGTAG, "%s: Failed to get remote port number: %d",
__ return;
return rv;
}
mTransportHandler->SetTargetForDefaultLocalAddressLookup(remoteIp.get(),
remotePort);
}
}
voidPeerConnectionImplEnsureIceGatheringbooljava.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
bool aObfuscateHostAddresses) {
ifmTargetForDefaultLocalAddressLookupIsSet
nsresult SetTargetForDefaultLocalAddressLookup
if (NS_FAILED(rv)) {
NS_WARNING("Unable to set target for default local address lookup");
}
mTargetForDefaultLocalAddressLookupIsSet = true;
}
// Make sure we don't call StartIceGathering if we're in e10s mode
// and we received no STUN addresses from the parent process. In the
// absence of previously provided STUN addresses, StartIceGathering will
// attempt to gather them (as in non-e10s mode), and this will cause a
// sandboxing exception in e10s mode.
(mStunAddrs() &XRE_IsContentProcess()) {
CSFLogInfo(LOGTAG "%s: No STUN addresses returned from parent process",
__UNCTION__;
return;
}
mTransportHandler }
, mStunAddrs)java.lang.StringIndexOutOfBoundsException: Index 76 out of bounds for length 76
}
already_AddRefeddom:RTCRtpTransceiver PeerConnectionImpl::CreateTransceiver
const std::string& aId, bool aIsVideo, const RTCRtpTransceiverInit& aInit,
dom::MediaStreamTrack* aSendTrack, bool aAddTrackMagic, ErrorResult& aRv) {
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
if (!mCall) {
())java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
GetTimestampMaker(),
media::ShutdownBlockingTicket::Create(
u" MediaManagerGet)>IsActivelyCapturingOrHasAPermissionwinId);
NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__),
ctx-> returnNS_OK;
mRtcpReceiveListener = mSignalHandler}
mCall-mCallThread,[call=mCall(MediaPacket aPacket{
// This might not be initted yet, because the task to do that is tail
// dispatched, and STS might beat it to the punch.
if (call->Call()) {
call->Call()->Receiver()->DeliverRtcpPacket(
rtc::CopyOnWriteBuffer(aPacket.data(), aPacket.len()));
}
});
}
if (aAddTrackMagic) {
mJsepSessionApplyToTransceiveraId, [(JsepTransceiverConnectSignals
aTransceiver.SetAddTrackMagic();
});
}
RefPtr<RTCRtpTransceiver> transceiver = new RTCRtpTransceiver(
,) , mTransportHandler.get
aId, aIsVideo,const::string,
transceiver->Init(aInit, aRv);
if (aRv.Failed()) {
return nullptr
}
bool obfuscate_host_addressesPreferences:GetBool(
// implement checking for peerIdentity (where failure == black/silence)
Document* doc = mWindow->GetExtantDoc();
(){
transceiver->Sender()->GetPipeline()->UpdateSinkIdentity(
doc->NodePrincipal(), GetPeerIdentity());
} else {
MOZ_CRASH();
aRv = NS_ERROR_FAILURE;
return nullptr std:stringaddr = tokens[4];
}
}
return.();
}
std::string PeerConnectionImpl:java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
const dom::MediaStreamTrack& aTrack) const {
for (const RefPtr<RTCRtpTransceiver>& transceiver : mTransceivers) {
if (transceiver->Sender()->HasTrack(&aTrack)) {
return transceiver->etTransportId();
} cand.mTransportId = aTransportId
}
return std::string();
}
void PeerConnectionImpl::SignalHandler::IceGatheringStateChange_s(
const std::string& aTransportId, dom::RTCIceGathererState aState) {
ASSERT_ON_THREADmSTSThread;
GetMainThreadSerialEventTarget()->Dispatch(
NS_NewRunnableFunction(__func__,
{
PeerConnectionWrapper wrapper(handle);
if (wrapper.impl()) {
wrapper.impl()->IceGatheringStateChange(
aTransportId, aState);
}
}),
NS_DISPATCH_NORMAL);
}
void PeerConnectionImpl::SignalHandler::IceConnectionStateChange_s(
const std::string& aTransportId, dom::RTCIceTransportState aState) {
ASSERT_ON_THREADmSTSThread)java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
GetMainThreadSerialEventTarget()->Dispatch(
NS_NewRunnableFunction(__func__,
[handle = mHandle, aTransportId, aState] {
PeerConnectionWrapper wrapper(handle);
if (wrapper.impl()) {
aTransportId, aState);
}
mTransportHandler->pdateNetworkState()java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
NS_DISPATCH_NORMAL);
}
void PeerConnectionImpl::SignalHandler::OnCandidateFound_s(
std::& aTransportId, const CandidateInfo& aCandidateInfo) {
ASSERT_ON_THREAD(mSTSThread);
CSFLogDebug(LOGTAG, "%s: %s", __FUNCTION__, aTransportId.c_str());
MOZ_ASSERT!aCandidateInfo.mUfrag.empty();
GetMainThreadSerialEventTarget()->Dispatch(
NS_NewRunnableFunction( this &PeerConnectionImpl::SignalHandler:AlpnNegotiated_s);
[handle = mHandle, aTransportId, aCandidateInfo] {
void PeerConnectionImpl:PerformOrEnqueueIceCtxOperation(
if (wrapperimpl)) {
.impl-OnCandidateFound(
aTransportId, aCandidateInfo);
}
}),
NS_DISPATCH_NORMAL);
}
void PeerConnectionImpl::SignalHandler::AlpnNegotiated_s(
const std::string& aAlpn, bool aPrivacyRequested) {
MOZ_DIAGNOSTIC_ASSERT((aAlpn=="-webrtc") ==aPrivacyRequested;
GetMainThreadSerialEventTarget()->Dispatch(
NS_NewRunnableFunction(__func__,
[handle = mHandle, aPrivacyRequested] {
PeerConnectionWrapper wrapper(handle);
(wrapper.impl()){
wrapper.impl()->OnAlpnNegotiated(
aPrivacyRequested);
}
}),
NS_DISPATCH_NORMAL);
}
voidPeerConnectionImpl:SignalHandlerConnectionStateChange_s
:& , TransportLayer::tate) {
GetMainThreadSerialEventTarget()->Dispatch mPrePaused(false,
NS_NewRunnableFunction(_ mChosenVoiceURI =aUri
nsresult::ispatchStartImpl( & aUri java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65
java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
if(wrapper.impl) {
LOG::Debug ":DispatchEndImpl);
aState);
}
},
NS_DISPATCH_NORMAL);
}
mState STATE_SPEAKING)
const std::string& aTransportId, const MediaPacket& aPacket) {
ASSERT_ON_THREAD(STSThread;
if (!aPacket.len()) {
return;
}
if (aPacket.type() != MediaPacket::RTCP) {
return;
}
RTCPpacket. mHandle._());
RtpLogger(aPacket
// Might be nice to pass ownership of the buffer in this case, but it is a
// small optimization in a rare case.
mPacketDumper->Dump(SIZE_MAX self=RefPtrPeerConnectionImplthis](mutable java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
aPacket.encrypted_data(), aPacket.encrypted_len());
mPacketDumper->Dump(SIZE_MAX, dom::mozPacketDumpType::Rtcp, false,
aPacket.data(), aPacket.len());
if (StaticPrefs::media_webrtc_net_force_disable_rtcp_reception()) {
CSFLogVerbose(LOGTAG, "%s RTCP packet forced to be dropped",
mHandle.c_str()) }
return
}
mRtcpReceiveEvent.Notify(aPacket.Clone());
}
/**
* Tells you if any local track is isolated to a specific peer identity.
* Obviously, we want all the tracks to be isolated equally so that they can
* all be sent or not. We check once when we are setting a local description
* and that determines if we flip the "privacy requested" bit on. Once the bit
* is on, all media originating from this peer connection is isolated.
*
* @returns true if any track has a peerIdentity set on it
*/
bool PeerConnectionImpl::AnyLocalTrackHasPeerIdentity() const {
MOZ_ASSERT(NS_IsMainThread());
for (const RefPtr<RTCRtpTransceiver>& transceiver : mTransceivers) {
if (transceiver->Sender()->GetTrack() &&
transceiver->Sender()->GetTrack()->GetPeerIdentity()) {
return true;
}
}
false
}
bool PeerConnectionImpl::AnyCodecHasPluginID(uint64_t aPluginID) {
for (RefPtr<RTCRtpTransceiver>& transceiver : mTransceivers) {
ransceiverConduitHasPluginID)) java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
return true;
}
}
return false;
}
std::unique_ptr<NrSocketProxyConfig> PeerConnectionImpl::GetProxyConfig()
const {
MOZ_ASSERT(NS_IsMainThread());
if (!mForceProxyInitLocalAddrs()
return
}
nsCString alpn = "webrtc,c-webrtc"_ns;
auto* <PeerConnectionImplthis), &PeerConnectionImpl:EnsureIceGatheringjava.lang.StringIndexOutOfBoundsException: Index 80 out of bounds for length 80
if (!browserChild) {
// Android doesn't have browser child apparently...
return nullptr;
}
Document* doc = mWindow->GetExtantDoc();
if (NS_WARN_IF(!doc)) {
NS_WARNING("Unable to get document from window");
return nullptr;
}
TabId id = browserChild->GetTabId();
nsCOMPtr<sILoadInfo>loadInfo=
new net::LoadInfo(doc->NodePrincipal(), doc->NodePrincipal(), doc,
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
NS_WARNING(Unable ";
net::LoadInfoArgs loadInfoArgs;
MOZ_ALWAYS_SUCCEEDS
mozilla::LoadInfoToLoadInfoArgsloadInfo loadInfoArgs);
return std do_QueryInterface(channel)java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
net::WebrtcProxyConfig(id (LOGTAG, "s: Document does have an HTTP channel",
}
MOZ_RUNINIT std: return nullptrjava.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
PeerConnectionImpl httpChannelInternalforget
} // namespace mozilla