Quellcodebibliothek Statistik Leitseite project   (Browser von der Mozilla Stiftung Version 136.0.1©) image not shown  

Quellcode-Bibliothek PeerConnectionImpl.cpp

  Sprache: C
 

/* 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, 0sizeof(mMaxReceiving));
  memset(mMaxSending, 0sizeof(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 length 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 stateifresultisSom
  // 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

Messung V0.5 in Prozent
C=91 H=91 G=90

¤ Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.0.169Bemerkung:  ¤

*Bot Zugriff






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.