author Sebastian Hengst <>
Wed, 05 Oct 2016 17:03:06 +0200
changeset 359463 84cb9e48869cfa8126e44df7f5053e2d81e4f796
parent 359461 6242662fb3243870ad1d11ab9d92f9493daf0b0d
child 359611 492a39e1ca7c299ee74356c8d5937bec78f3e552
permissions -rw-r--r--
Backed out changeset 903fa45a9d6c (bug 1291715) for build bustage. r=backout

/* 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 */


#include <deque>
#include <string>
#include <vector>
#include <map>
#include <cmath>

#include "prlock.h"
#include "mozilla/RefPtr.h"
#include "nsWeakPtr.h"
#include "nsAutoPtr.h"
#include "nsIWeakReferenceUtils.h" // for the definition of nsWeakPtr
#include "IPeerConnection.h"
#include "sigslot.h"
#include "nricectx.h"
#include "nricemediastream.h"
#include "nsComponentManagerUtils.h"
#include "nsPIDOMWindow.h"
#include "nsIUUIDGenerator.h"
#include "nsIThread.h"

#include "signaling/src/jsep/JsepSession.h"
#include "signaling/src/jsep/JsepSessionImpl.h"
#include "signaling/src/sdp/SdpMediaSection.h"

#include "mozilla/ErrorResult.h"
#include "mozilla/dom/PeerConnectionImplEnumsBinding.h"
#include "PrincipalChangeObserver.h"
#include "StreamTracks.h"

#include "mozilla/TimeStamp.h"
#include "mozilla/net/DataChannel.h"
#include "VideoUtils.h"
#include "VideoSegment.h"
#include "mozilla/dom/RTCStatsReportBinding.h"
#include "nsIPrincipal.h"
#include "mozilla/PeerIdentity.h"

namespace test {
class AFakePCObserver;

class Fake_DOMMediaStream;
class Fake_MediaStreamTrack;

class nsGlobalWindow;
class nsDOMDataChannel;

namespace mozilla {
class DataChannel;
class DtlsIdentity;
class NrIceCtx;
class NrIceMediaStream;
class NrIceStunServer;
class NrIceTurnServer;
class MediaPipeline;

typedef Fake_DOMMediaStream DOMMediaStream;
class DOMMediaStream;

namespace dom {
class RTCCertificate;
struct RTCConfiguration;
struct RTCIceServer;
struct RTCOfferOptions;
struct RTCRtpParameters;
typedef Fake_MediaStreamTrack MediaStreamTrack;
class MediaStreamTrack;

typedef test::AFakePCObserver PeerConnectionObserver;
typedef const char *PCObserverString;
class PeerConnectionObserver;
typedef NS_ConvertUTF8toUTF16 PCObserverString;

#if defined(__cplusplus) && __cplusplus >= 201103L
typedef struct Timecard Timecard;
#include "timecard.h"

// To preserve blame, convert nsresult to ErrorResult with wrappers. These macros
// help declare wrappers w/function being wrapped when there are no differences.

#define NS_IMETHODIMP_TO_ERRORRESULT(func, rv, ...) \
NS_IMETHODIMP func(__VA_ARGS__);                    \
void func (__VA_ARGS__, rv)

#define NS_IMETHODIMP_TO_ERRORRESULT_RETREF(resulttype, func, rv, ...) \
NS_IMETHODIMP func(__VA_ARGS__, resulttype **result);                  \
already_AddRefed<resulttype> func (__VA_ARGS__, rv)

struct MediaStreamTable;

namespace mozilla {

using mozilla::dom::PeerConnectionObserver;
using mozilla::dom::RTCConfiguration;
using mozilla::dom::RTCIceServer;
using mozilla::dom::RTCOfferOptions;
using mozilla::DOMMediaStream;
using mozilla::NrIceCtx;
using mozilla::NrIceMediaStream;
using mozilla::DtlsIdentity;
using mozilla::ErrorResult;
using mozilla::NrIceStunServer;
using mozilla::NrIceTurnServer;
using mozilla::PeerIdentity;

class PeerConnectionWrapper;
class PeerConnectionMedia;
class RemoteSourceStreamInfo;

// Uuid Generator
class PCUuidGenerator : public mozilla::JsepUuidGenerator {
  virtual bool Generate(std::string* idp) override;

  nsCOMPtr<nsIUUIDGenerator> mGenerator;

class PeerConnectionConfiguration
  : mBundlePolicy(kBundleBalanced),
    mIceTransportPolicy(NrIceCtx::ICE_POLICY_ALL) {}

  bool addStunServer(const std::string& addr, uint16_t port,
                     const char* transport)
    UniquePtr<NrIceStunServer> server(NrIceStunServer::Create(addr, port, transport));
    if (!server) {
      return false;
    return true;
  bool addTurnServer(const std::string& addr, uint16_t port,
                     const std::string& username,
                     const std::string& pwd,
                     const char* transport)
    // TODO( Need support for SASLprep for
    // username and password. Bug # ???
    std::vector<unsigned char> password(pwd.begin(), pwd.end());

    UniquePtr<NrIceTurnServer> server(NrIceTurnServer::Create(addr, port, username, password,
    if (!server) {
      return false;
    return true;
  void addStunServer(const NrIceStunServer& server) { mStunServers.push_back (server); }
  void addTurnServer(const NrIceTurnServer& server) { mTurnServers.push_back (server); }
  const std::vector<NrIceStunServer>& getStunServers() const { return mStunServers; }
  const std::vector<NrIceTurnServer>& getTurnServers() const { return mTurnServers; }
  void setBundlePolicy(JsepBundlePolicy policy) { mBundlePolicy = policy;}
  JsepBundlePolicy getBundlePolicy() const { return mBundlePolicy; }
  void setIceTransportPolicy(NrIceCtx::Policy policy) { mIceTransportPolicy = policy;}
  NrIceCtx::Policy getIceTransportPolicy() const { return mIceTransportPolicy; }

  nsresult Init(const RTCConfiguration& aSrc);
  nsresult AddIceServer(const RTCIceServer& aServer);

  std::vector<NrIceStunServer> mStunServers;
  std::vector<NrIceTurnServer> mTurnServers;
  JsepBundlePolicy mBundlePolicy;
  NrIceCtx::Policy mIceTransportPolicy;

// Not an inner class so we can forward declare.
class RTCStatsQuery {
    explicit RTCStatsQuery(bool internalStats);

    nsAutoPtr<mozilla::dom::RTCStatsReportInternal> report;
    std::string error;
    // A timestamp to help with telemetry.
    mozilla::TimeStamp iceStartTime;
    bool isHello;
    // Just for convenience, maybe integrate into the report later
    bool failed;

    friend class PeerConnectionImpl;
    std::string pcName;
    bool internalStats;
    nsTArray<RefPtr<mozilla::MediaPipeline>> pipelines;
    RefPtr<NrIceCtx> iceCtx;
    bool grabAllLevels;
    DOMHighResTimeStamp now;

// Enter an API call and check that the state is OK,
// the PC isn't closed, etc.
#define PC_AUTO_ENTER_API_CALL(assert_ice_ready) \
    do { \
      /* do/while prevents res from conflicting with locals */    \
      nsresult res = CheckApiState(assert_ice_ready);             \
      if (NS_FAILED(res)) return res; \
    } while(0)
#define PC_AUTO_ENTER_API_CALL_VOID_RETURN(assert_ice_ready) \
    do { \
      /* do/while prevents res from conflicting with locals */    \
      nsresult res = CheckApiState(assert_ice_ready);             \
      if (NS_FAILED(res)) return; \
    } while(0)
#define PC_AUTO_ENTER_API_CALL_NO_CHECK() CheckThread()

class PeerConnectionImpl final : public nsISupports,
                                 public mozilla::DataChannelConnection::DataConnectionListener,
                                 public dom::PrincipalChangeObserver<dom::MediaStreamTrack>,
                                 public sigslot::has_slots<>
  struct Internal; // Avoid exposing c includes to bindings

  explicit PeerConnectionImpl(const mozilla::dom::GlobalObject* aGlobal = nullptr);

  enum Error {
    kNoError                          = 0,
    kInvalidCandidate                 = 2,
    kInvalidMediastreamTrack          = 3,
    kInvalidState                     = 4,
    kInvalidSessionDescription        = 5,
    kIncompatibleSessionDescription   = 6,
    kIncompatibleMediaStreamTrack     = 8,
    kInternalError                    = 9


  bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector);

  static already_AddRefed<PeerConnectionImpl>
      Constructor(const mozilla::dom::GlobalObject& aGlobal, ErrorResult& rv);
  static PeerConnectionImpl* CreatePeerConnection();
  already_AddRefed<DOMMediaStream> MakeMediaStream();

  nsresult CreateRemoteSourceStreamInfo(RefPtr<RemoteSourceStreamInfo>* aInfo,
                                        const std::string& aId);

  // DataConnection observers
  void NotifyDataChannel(already_AddRefed<mozilla::DataChannel> aChannel)
    // PeerConnectionImpl only inherits from mozilla::DataChannelConnection
    // inside libxul.

  // Get the media object
  const RefPtr<PeerConnectionMedia>& media() const {
    return mMedia;

  // Configure the ability to use localhost.
  void SetAllowIceLoopback(bool val) { mAllowIceLoopback = val; }
  bool GetAllowIceLoopback() const { return mAllowIceLoopback; }

  // Configure the ability to use IPV6 link-local addresses.
  void SetAllowIceLinkLocal(bool val) { mAllowIceLinkLocal = val; }
  bool GetAllowIceLinkLocal() const { return mAllowIceLinkLocal; }

  // Handle system to allow weak references to be passed through C code
  virtual const std::string& GetHandle();

  // Name suitable for exposing to content
  virtual const std::string& GetName();

  // ICE events
  void IceConnectionStateChange(NrIceCtx* ctx,
                                NrIceCtx::ConnectionState state);
  void IceGatheringStateChange(NrIceCtx* ctx,
                               NrIceCtx::GatheringState state);
  void UpdateDefaultCandidate(const std::string& defaultAddr,
                              uint16_t defaultPort,
                              const std::string& defaultRtcpAddr,
                              uint16_t defaultRtcpPort,
                              uint16_t level);
  void EndOfLocalCandidates(uint16_t level);
  void IceStreamReady(NrIceMediaStream *aStream);

  static void ListenThread(void *aData);
  static void ConnectThread(void *aData);

  // Get the main thread
  nsCOMPtr<nsIThread> GetMainThread() {
    return mThread;

  // Get the STS thread
  nsIEventTarget* GetSTSThread() {
    return mSTSThread;

  nsPIDOMWindowInner* GetWindow() const {
    return mWindow;

  // Initialize PeerConnection from a PeerConnectionConfiguration object
  // (used directly by unit-tests, and indirectly by the JS entry point)
  // This is necessary because RTCConfiguration can't be used by unit-tests
  nsresult Initialize(PeerConnectionObserver& aObserver,
                      nsGlobalWindow* aWindow,
                      const PeerConnectionConfiguration& aConfiguration,
                      nsISupports* aThread);

  // Initialize PeerConnection from an RTCConfiguration object (JS entrypoint)
  void Initialize(PeerConnectionObserver& aObserver,
                  nsGlobalWindow& aWindow,
                  const RTCConfiguration& aConfiguration,
                  nsISupports* aThread,
                  ErrorResult &rv);

  void SetCertificate(mozilla::dom::RTCCertificate& aCertificate);
  const RefPtr<mozilla::dom::RTCCertificate>& Certificate() const;
  // This is a hack to support external linkage.
  RefPtr<DtlsIdentity> Identity() const;

  NS_IMETHODIMP_TO_ERRORRESULT(CreateOffer, ErrorResult &rv,
                               const RTCOfferOptions& aOptions)
    rv = CreateOffer(aOptions);

  NS_IMETHODIMP CreateAnswer();
  void CreateAnswer(ErrorResult &rv)
    rv = CreateAnswer();

  NS_IMETHODIMP CreateOffer(
      const mozilla::JsepOfferOptions& aConstraints);

  NS_IMETHODIMP SetLocalDescription (int32_t aAction, const char* aSDP);

  void SetLocalDescription (int32_t aAction, const nsAString& aSDP, ErrorResult &rv)
    rv = SetLocalDescription(aAction, NS_ConvertUTF16toUTF8(aSDP).get());

  nsresult CreateNewRemoteTracks(RefPtr<PeerConnectionObserver>& aPco);

  void RemoveOldRemoteTracks(RefPtr<PeerConnectionObserver>& aPco);

  NS_IMETHODIMP SetRemoteDescription (int32_t aAction, const char* aSDP);

  void SetRemoteDescription (int32_t aAction, const nsAString& aSDP, ErrorResult &rv)
    rv = SetRemoteDescription(aAction, NS_ConvertUTF16toUTF8(aSDP).get());

                               mozilla::dom::MediaStreamTrack *aSelector)
    rv = GetStats(aSelector);

  NS_IMETHODIMP AddIceCandidate(const char* aCandidate, const char* aMid,
                                unsigned short aLevel);

  void AddIceCandidate(const nsAString& aCandidate, const nsAString& aMid,
                       unsigned short aLevel, ErrorResult &rv)
    rv = AddIceCandidate(NS_ConvertUTF16toUTF8(aCandidate).get(),
                         NS_ConvertUTF16toUTF8(aMid).get(), aLevel);

  NS_IMETHODIMP CloseStreams();

  void CloseStreams(ErrorResult &rv)
    rv = CloseStreams();

      mozilla::dom::MediaStreamTrack& aTrack,
      const mozilla::dom::Sequence<mozilla::OwningNonNull<DOMMediaStream>>& aStreams)
    rv = AddTrack(aTrack, aStreams);

  NS_IMETHODIMP_TO_ERRORRESULT(RemoveTrack, ErrorResult &rv,
                               mozilla::dom::MediaStreamTrack& aTrack)
    rv = RemoveTrack(aTrack);

  AddTrack(mozilla::dom::MediaStreamTrack& aTrack, DOMMediaStream& aStream);

  NS_IMETHODIMP_TO_ERRORRESULT(ReplaceTrack, ErrorResult &rv,
                               mozilla::dom::MediaStreamTrack& aThisTrack,
                               mozilla::dom::MediaStreamTrack& aWithTrack)
    rv = ReplaceTrack(aThisTrack, aWithTrack);

  NS_IMETHODIMP_TO_ERRORRESULT(SetParameters, ErrorResult &rv,
                               dom::MediaStreamTrack& aTrack,
                               const dom::RTCRtpParameters& aParameters)
    rv = SetParameters(aTrack, aParameters);

  NS_IMETHODIMP_TO_ERRORRESULT(GetParameters, ErrorResult &rv,
                               dom::MediaStreamTrack& aTrack,
                               dom::RTCRtpParameters& aOutParameters)
    rv = GetParameters(aTrack, aOutParameters);

  SetParameters(dom::MediaStreamTrack& aTrack,
                const std::vector<JsepTrack::JsConstraints>& aConstraints);

  GetParameters(dom::MediaStreamTrack& aTrack,
                std::vector<JsepTrack::JsConstraints>* aOutConstraints);

  NS_IMETHODIMP_TO_ERRORRESULT(SelectSsrc, ErrorResult &rv,
                               dom::MediaStreamTrack& aRecvTrack,
                               unsigned short aSsrcIndex)
    rv = SelectSsrc(aRecvTrack, aSsrcIndex);

  nsresult GetPeerIdentity(nsAString& peerIdentity)
    if (mPeerIdentity) {
      peerIdentity = mPeerIdentity->ToString();
      return NS_OK;

    return NS_OK;

  const PeerIdentity* GetPeerIdentity() const { return mPeerIdentity; }
  nsresult SetPeerIdentity(const nsAString& peerIdentity);

  const std::string& GetIdAsAscii() const
    return mName;

  nsresult GetId(nsAString& id)
    id = NS_ConvertASCIItoUTF16(mName.c_str());
    return NS_OK;

  nsresult SetId(const nsAString& id)
    mName = NS_ConvertUTF16toUTF8(id).get();
    return NS_OK;

  bool IsLoop() const { return mIsLoop; }

  // this method checks to see if we've made a promise to protect media.
  bool PrivacyRequested() const { return mPrivacyRequested; }

  NS_IMETHODIMP GetFingerprint(char** fingerprint);
  void GetFingerprint(nsAString& fingerprint)
    char *tmp;
    delete[] tmp;

  NS_IMETHODIMP GetLocalDescription(char** aSDP);

  void GetLocalDescription(nsAString& aSDP)
    char *tmp;
    delete[] tmp;

  NS_IMETHODIMP GetRemoteDescription(char** aSDP);

  void GetRemoteDescription(nsAString& aSDP)
    char *tmp;
    delete[] tmp;

  NS_IMETHODIMP SignalingState(mozilla::dom::PCImplSignalingState* aState);

  mozilla::dom::PCImplSignalingState SignalingState()
    mozilla::dom::PCImplSignalingState state;
    return state;

  NS_IMETHODIMP IceConnectionState(
      mozilla::dom::PCImplIceConnectionState* aState);

  mozilla::dom::PCImplIceConnectionState IceConnectionState()
    mozilla::dom::PCImplIceConnectionState state;
    return state;

  NS_IMETHODIMP IceGatheringState(
      mozilla::dom::PCImplIceGatheringState* aState);

  mozilla::dom::PCImplIceGatheringState IceGatheringState()
    mozilla::dom::PCImplIceGatheringState state;
    return state;


  void Close(ErrorResult &rv)
    rv = Close();

  bool PluginCrash(uint32_t aPluginID,
                   const nsAString& aPluginName);

  void RecordEndOfCallTelemetry() const;

  nsresult InitializeDataChannel();

                                      CreateDataChannel, ErrorResult &rv,
                                      const nsAString& aLabel,
                                      const nsAString& aProtocol,
                                      uint16_t aType,
                                      bool outOfOrderAllowed,
                                      uint16_t aMaxTime,
                                      uint16_t aMaxNum,
                                      bool aExternalNegotiated,
                                      uint16_t aStream);

  NS_IMETHODIMP_TO_ERRORRESULT(GetLocalStreams, ErrorResult &rv,
                               nsTArray<RefPtr<DOMMediaStream > >& result)
    rv = GetLocalStreams(result);

  NS_IMETHODIMP_TO_ERRORRESULT(GetRemoteStreams, ErrorResult &rv,
                               nsTArray<RefPtr<DOMMediaStream > >& result)
    rv = GetRemoteStreams(result);

  // Called whenever something is unrecognized by the parser
  // May be called more than once and does not necessarily mean
  // that parsing was stopped, only that something was unrecognized.
  void OnSdpParseError(const char* errorMessage);

  // Called when OnLocal/RemoteDescriptionSuccess/Error
  // is called to start the list over.
  void ClearSdpParseErrorMessages();

  // Called to retreive the list of parsing errors.
  const std::vector<std::string> &GetSdpParseErrors();

  // Sets the RTC Signaling State
  void SetSignalingState_m(mozilla::dom::PCImplSignalingState aSignalingState,
                           bool rollback = false);

  // Updates the RTC signaling state based on the JsepSession state
  void UpdateSignalingState(bool rollback = false);

  bool IsClosed() const;
  // called when DTLS connects; we only need this once
  nsresult SetDtlsConnected(bool aPrivacyRequested);

  bool HasMedia() const;

  // initialize telemetry for when calls start
  void startCallTelem();

  nsresult BuildStatsQuery_m(
      mozilla::dom::MediaStreamTrack *aSelector,
      RTCStatsQuery *query);

  static nsresult ExecuteStatsQuery_s(RTCStatsQuery *query);

  // for monitoring changes in track ownership
  // PeerConnectionMedia can't do it because it doesn't know about principals
  virtual void PrincipalChanged(dom::MediaStreamTrack* aTrack) override;


  static std::string GetStreamId(const DOMMediaStream& aStream);
  static std::string GetTrackId(const dom::MediaStreamTrack& track);

  void OnMediaError(const std::string& aError);

  virtual ~PeerConnectionImpl();
  PeerConnectionImpl(const PeerConnectionImpl&rhs);
  PeerConnectionImpl& operator=(PeerConnectionImpl);
  nsresult CalculateFingerprint(const std::string& algorithm,
                                std::vector<uint8_t>* fingerprint) const;
  nsresult ConfigureJsepSessionCodecs();

  NS_IMETHODIMP EnsureDataConnection(uint16_t aNumstreams);

  nsresult CloseInt();
  nsresult CheckApiState(bool assert_ice_ready) const;
  void CheckThread() const {
    MOZ_ASSERT(CheckThreadInt(), "Wrong thread");
  bool CheckThreadInt() const {
    // Thread assertions are disabled in the C++ unit tests because those
    // make API calls off the main thread.
    // This affects the standalone version of WebRTC since it is also used
    // for an alternate build of the unit tests.
    // TODO( Fix the unit tests so they don't do that.
    bool on;
    NS_ENSURE_SUCCESS(mThread->IsOnCurrentThread(&on), false);
    NS_ENSURE_TRUE(on, false);
    return true;

  nsresult GetTimeSinceEpoch(DOMHighResTimeStamp *result);

  // Shut down media - called on main thread only
  void ShutdownMedia();

  void CandidateReady(const std::string& candidate, uint16_t level);
  void SendLocalIceCandidateToContent(uint16_t level,
                                      const std::string& mid,
                                      const std::string& candidate);

  nsresult GetDatachannelParameters(
      const mozilla::JsepApplicationCodecDescription** codec,
      uint16_t* level) const;

  static void DeferredAddTrackToJsepSession(const std::string& pcHandle,
                                            SdpMediaSection::MediaType type,
                                            const std::string& streamId,
                                            const std::string& trackId);

  nsresult AddTrackToJsepSession(SdpMediaSection::MediaType type,
                                 const std::string& streamId,
                                 const std::string& trackId);

  nsresult SetupIceRestart();
  nsresult RollbackIceRestart();
  void FinalizeIceRestart();

  static void GetStatsForPCObserver_s(
      const std::string& pcHandle,
      nsAutoPtr<RTCStatsQuery> query);

  // Sends an RTCStatsReport to JS. Must run on main thread.
  static void DeliverStatsReportToPCObserver_m(
      const std::string& pcHandle,
      nsresult result,
      nsAutoPtr<RTCStatsQuery> query);

  // When ICE completes, we record a bunch of statistics that outlive the
  // PeerConnection. This is just telemetry right now, but this can also
  // include things like dumping the RLogRingbuffer somewhere, saving away
  // an RTCStatsReport somewhere so it can be inspected after the call is over,
  // or other things.
  void RecordLongtermICEStatistics();

  void OnNegotiationNeeded();
  static void MaybeFireNegotiationNeeded_static(const std::string& pcHandle);
  void MaybeFireNegotiationNeeded();

  // Timecard used to measure processing time. This should be the first class
  // attribute so that we accurately measure the time required to instantiate
  // any other attributes of this class.
  Timecard *mTimeCard;

  mozilla::dom::PCImplSignalingState mSignalingState;

  // ICE State
  mozilla::dom::PCImplIceConnectionState mIceConnectionState;
  mozilla::dom::PCImplIceGatheringState mIceGatheringState;

  // DTLS
  // this is true if we have been connected ever, see SetDtlsConnected
  bool mDtlsConnected;

  nsCOMPtr<nsIThread> mThread;
  // TODO: Remove if we ever properly wire PeerConnection for cycle-collection.
  nsWeakPtr mPCObserver;

  nsCOMPtr<nsPIDOMWindowInner> mWindow;

  // The SDP sent in from JS - here for debugging.
  std::string mLocalRequestedSDP;
  std::string mRemoteRequestedSDP;

  // DTLS fingerprint
  std::string mFingerprint;
  std::string mRemoteFingerprint;

  // identity-related fields
  // The entity on the other end of the peer-to-peer connection;
  // void if they are not yet identified, and no identity setting has been set
  RefPtr<PeerIdentity> mPeerIdentity;
  // The certificate we are using.
  RefPtr<mozilla::dom::RTCCertificate> mCertificate;
  RefPtr<DtlsIdentity> mIdentity;
  // Whether an app should be prevented from accessing media produced by the PC
  // If this is true, then media will not be sent until mPeerIdentity matches
  // local streams PeerIdentity; and remote streams are protected from content
  // This can be false if mPeerIdentity is set, in the case where identity is
  // provided, but the media is not protected from the app on either side
  bool mPrivacyRequested;

  // A handle to refer to this PC with
  std::string mHandle;

  // A name for this PC that we are willing to expose to content.
  std::string mName;
  bool mIsLoop; // For telemetry; doesn't have to be 100% right

  // The target to run stuff on
  nsCOMPtr<nsIEventTarget> mSTSThread;

  // DataConnection that's used to get all the DataChannels
  RefPtr<mozilla::DataChannelConnection> mDataConnection;

  bool mAllowIceLoopback;
  bool mAllowIceLinkLocal;
  RefPtr<PeerConnectionMedia> mMedia;

  // The JSEP negotiation session.
  mozilla::UniquePtr<PCUuidGenerator> mUuidGen;
  mozilla::UniquePtr<mozilla::JsepSession> mJsepSession;
  std::string mPreviousIceUfrag; // used during rollback of ice restart
  std::string mPreviousIcePwd; // used during rollback of ice restart

  // Start time of ICE, used for telemetry
  mozilla::TimeStamp mIceStartTime;
  // Start time of call used for Telemetry
  mozilla::TimeStamp mStartTime;

  // Temporary: used to prevent multiple audio streams or multiple video streams
  // in a single PC. This is tied up in the IETF discussion around proper
  // representation of multiple streams in SDP, and strongly related to
  // Bug 840728.
  int mNumAudioStreams;
  int mNumVideoStreams;
  bool mHaveConfiguredCodecs;

  bool mHaveDataStream;

  unsigned int mAddCandidateErrorCount;

  bool mTrickle;

  bool mNegotiationNeeded;

  bool mPrivateWindow;

  // storage for Telemetry data
  uint16_t mMaxReceiving[SdpMediaSection::kMediaTypes];
  uint16_t mMaxSending[SdpMediaSection::kMediaTypes];

  //these are temporary until the DataChannel Listen/Connect API is removed
  unsigned short listenPort;
  unsigned short connectPort;
  char *connectStr; // XXX ownership/free

// This is what is returned when you acquire on a handle
class PeerConnectionWrapper
  explicit PeerConnectionWrapper(const std::string& handle);

  PeerConnectionImpl *impl() { return impl_; }

  RefPtr<PeerConnectionImpl> impl_;

}  // end mozilla namespace