diff options
Diffstat (limited to 'media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h')
-rw-r--r-- | media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h | 894 |
1 files changed, 894 insertions, 0 deletions
diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h new file mode 100644 index 000000000..c29d08180 --- /dev/null +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h @@ -0,0 +1,894 @@ +/* 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/. */ + +#ifndef _PEER_CONNECTION_IMPL_H_ +#define _PEER_CONNECTION_IMPL_H_ + +#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" + +#if !defined(MOZILLA_EXTERNAL_LINKAGE) +#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" +#endif + +namespace test { +#ifdef USE_FAKE_PCOBSERVER +class AFakePCObserver; +#endif +} + +#ifdef USE_FAKE_MEDIA_STREAMS +class Fake_DOMMediaStream; +class Fake_MediaStreamTrack; +#endif + +class nsGlobalWindow; +class nsDOMDataChannel; + +namespace mozilla { +class DataChannel; +class DtlsIdentity; +class NrIceCtx; +class NrIceMediaStream; +class NrIceStunServer; +class NrIceTurnServer; +class MediaPipeline; + +#ifdef USE_FAKE_MEDIA_STREAMS +typedef Fake_DOMMediaStream DOMMediaStream; +#else +class DOMMediaStream; +#endif + +namespace dom { +class RTCCertificate; +struct RTCConfiguration; +class RTCDTMFSender; +struct RTCIceServer; +struct RTCOfferOptions; +struct RTCRtpParameters; +class RTCRtpSender; +#ifdef USE_FAKE_MEDIA_STREAMS +typedef Fake_MediaStreamTrack MediaStreamTrack; +#else +class MediaStreamTrack; +#endif + +#ifdef USE_FAKE_PCOBSERVER +typedef test::AFakePCObserver PeerConnectionObserver; +typedef const char *PCObserverString; +#else +class PeerConnectionObserver; +typedef NS_ConvertUTF8toUTF16 PCObserverString; +#endif +} +} + +#if defined(__cplusplus) && __cplusplus >= 201103L +typedef struct Timecard Timecard; +#else +#include "timecard.h" +#endif + +// 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; +#if !defined(MOZILLA_EXTERNAL_LINKAGE) +using mozilla::PeerIdentity; +#endif + +class PeerConnectionWrapper; +class PeerConnectionMedia; +class RemoteSourceStreamInfo; + +// Uuid Generator +class PCUuidGenerator : public mozilla::JsepUuidGenerator { + public: + virtual bool Generate(std::string* idp) override; + + private: + nsCOMPtr<nsIUUIDGenerator> mGenerator; +}; + +class PeerConnectionConfiguration +{ +public: + 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; + } + addStunServer(*server); + return true; + } + bool addTurnServer(const std::string& addr, uint16_t port, + const std::string& username, + const std::string& pwd, + const char* transport) + { + // TODO(ekr@rtfm.com): 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, + transport)); + if (!server) { + return false; + } + addTurnServer(*server); + 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; } + +#ifndef MOZILLA_EXTERNAL_LINKAGE + nsresult Init(const RTCConfiguration& aSrc); + nsresult AddIceServer(const RTCIceServer& aServer); +#endif + +private: + std::vector<NrIceStunServer> mStunServers; + std::vector<NrIceTurnServer> mTurnServers; + JsepBundlePolicy mBundlePolicy; + NrIceCtx::Policy mIceTransportPolicy; +}; + +#if !defined(MOZILLA_EXTERNAL_LINKAGE) +// Not an inner class so we can forward declare. +class RTCStatsQuery { + public: + explicit RTCStatsQuery(bool internalStats); + ~RTCStatsQuery(); + + nsAutoPtr<mozilla::dom::RTCStatsReportInternal> report; + std::string error; + // A timestamp to help with telemetry. + mozilla::TimeStamp iceStartTime; + // Just for convenience, maybe integrate into the report later + bool failed; + + private: + friend class PeerConnectionImpl; + std::string pcName; + bool internalStats; + nsTArray<RefPtr<mozilla::MediaPipeline>> pipelines; + RefPtr<NrIceCtx> iceCtx; + bool grabAllLevels; + DOMHighResTimeStamp now; +}; +#endif // MOZILLA_INTERNAL_API + +// 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, +#if !defined(MOZILLA_EXTERNAL_LINKAGE) + public mozilla::DataChannelConnection::DataConnectionListener, + public dom::PrincipalChangeObserver<dom::MediaStreamTrack>, +#endif + public sigslot::has_slots<> +{ + struct Internal; // Avoid exposing c includes to bindings + +public: + 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 + }; + + NS_DECL_THREADSAFE_ISUPPORTS + +#if !defined(MOZILLA_EXTERNAL_LINKAGE) + bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector); +#endif + + 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) +#if !defined(MOZILLA_EXTERNAL_LINKAGE) + // PeerConnectionImpl only inherits from mozilla::DataChannelConnection + // inside libxul. + override +#endif + ; + + // Get the media object + const RefPtr<PeerConnectionMedia>& media() const { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); + 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() { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); + return mThread; + } + + // Get the STS thread + nsIEventTarget* GetSTSThread() { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); + return mSTSThread; + } + + nsPIDOMWindowInner* GetWindow() const { + PC_AUTO_ENTER_API_CALL_NO_CHECK(); + 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); + +#ifndef MOZILLA_EXTERNAL_LINKAGE + // Initialize PeerConnection from an RTCConfiguration object (JS entrypoint) + void Initialize(PeerConnectionObserver& aObserver, + nsGlobalWindow& aWindow, + const RTCConfiguration& aConfiguration, + nsISupports* aThread, + ErrorResult &rv); +#endif + +#if !defined(MOZILLA_EXTERNAL_LINKAGE) + void SetCertificate(mozilla::dom::RTCCertificate& aCertificate); + const RefPtr<mozilla::dom::RTCCertificate>& Certificate() const; +#endif + // 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()); + } + + NS_IMETHODIMP_TO_ERRORRESULT(GetStats, ErrorResult &rv, + 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(); + } + + NS_IMETHODIMP_TO_ERRORRESULT(AddTrack, ErrorResult &rv, + 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); + } + + nsresult + AddTrack(mozilla::dom::MediaStreamTrack& aTrack, DOMMediaStream& aStream); + + NS_IMETHODIMP_TO_ERRORRESULT(InsertDTMF, ErrorResult &rv, + dom::RTCRtpSender& sender, + const nsAString& tones, + uint32_t duration, uint32_t interToneGap) { + rv = InsertDTMF(sender, tones, duration, interToneGap); + } + + NS_IMETHODIMP_TO_ERRORRESULT(GetDTMFToneBuffer, ErrorResult &rv, + dom::RTCRtpSender& sender, + nsAString& outToneBuffer) { + rv = GetDTMFToneBuffer(sender, outToneBuffer); + } + + NS_IMETHODIMP_TO_ERRORRESULT(ReplaceTrack, ErrorResult &rv, + mozilla::dom::MediaStreamTrack& aThisTrack, + mozilla::dom::MediaStreamTrack& aWithTrack) + { + rv = ReplaceTrack(aThisTrack, aWithTrack); + } + +#if !defined(MOZILLA_EXTERNAL_LINKAGE) + 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); + } +#endif + + nsresult + SetParameters(dom::MediaStreamTrack& aTrack, + const std::vector<JsepTrack::JsConstraints>& aConstraints); + + nsresult + 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 !defined(MOZILLA_EXTERNAL_LINKAGE) + if (mPeerIdentity) { + peerIdentity = mPeerIdentity->ToString(); + return NS_OK; + } +#endif + + peerIdentity.SetIsVoid(true); + return NS_OK; + } + +#if !defined(MOZILLA_EXTERNAL_LINKAGE) + 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; + } +#endif + + // 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; + GetFingerprint(&tmp); + fingerprint.AssignASCII(tmp); + delete[] tmp; + } + + NS_IMETHODIMP GetLocalDescription(char** aSDP); + + void GetLocalDescription(nsAString& aSDP) + { + char *tmp; + GetLocalDescription(&tmp); + aSDP.AssignASCII(tmp); + delete[] tmp; + } + + NS_IMETHODIMP GetRemoteDescription(char** aSDP); + + void GetRemoteDescription(nsAString& aSDP) + { + char *tmp; + GetRemoteDescription(&tmp); + aSDP.AssignASCII(tmp); + delete[] tmp; + } + + NS_IMETHODIMP SignalingState(mozilla::dom::PCImplSignalingState* aState); + + mozilla::dom::PCImplSignalingState SignalingState() + { + mozilla::dom::PCImplSignalingState state; + SignalingState(&state); + return state; + } + + NS_IMETHODIMP IceConnectionState( + mozilla::dom::PCImplIceConnectionState* aState); + + mozilla::dom::PCImplIceConnectionState IceConnectionState() + { + mozilla::dom::PCImplIceConnectionState state; + IceConnectionState(&state); + return state; + } + + NS_IMETHODIMP IceGatheringState( + mozilla::dom::PCImplIceGatheringState* aState); + + mozilla::dom::PCImplIceGatheringState IceGatheringState() + { + mozilla::dom::PCImplIceGatheringState state; + IceGatheringState(&state); + return state; + } + + NS_IMETHODIMP Close(); + + void Close(ErrorResult &rv) + { + rv = Close(); + } + + bool PluginCrash(uint32_t aPluginID, + const nsAString& aPluginName); + + void RecordEndOfCallTelemetry() const; + + nsresult InitializeDataChannel(); + + NS_IMETHODIMP_TO_ERRORRESULT_RETREF(nsDOMDataChannel, + 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; + +#if !defined(MOZILLA_EXTERNAL_LINKAGE) + // 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; + +#endif + + static std::string GetStreamId(const DOMMediaStream& aStream); + static std::string GetTrackId(const dom::MediaStreamTrack& track); + + void OnMediaError(const std::string& aError); + +private: + 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 { +#if !defined(MOZILLA_EXTERNAL_LINKAGE) + // 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(ekr@rtfm.com): Fix the unit tests so they don't do that. + bool on; + NS_ENSURE_SUCCESS(mThread->IsOnCurrentThread(&on), false); + NS_ENSURE_TRUE(on, false); +#endif + return true; + } + +#if !defined(MOZILLA_EXTERNAL_LINKAGE) + nsresult GetTimeSinceEpoch(DOMHighResTimeStamp *result); +#endif + + // 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(); + +#if !defined(MOZILLA_EXTERNAL_LINKAGE) + 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); +#endif + + // 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 RLogConnector 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 +#if !defined(MOZILLA_EXTERNAL_LINKAGE) + // 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; +#else + RefPtr<DtlsIdentity> mIdentity; +#endif + // 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; + + // The target to run stuff on + nsCOMPtr<nsIEventTarget> mSTSThread; + +#if !defined(MOZILLA_EXTERNAL_LINKAGE) + // DataConnection that's used to get all the DataChannels + RefPtr<mozilla::DataChannelConnection> mDataConnection; +#endif + + 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 + +#if !defined(MOZILLA_EXTERNAL_LINKAGE) + // Start time of ICE, used for telemetry + mozilla::TimeStamp mIceStartTime; + // Start time of call used for Telemetry + mozilla::TimeStamp mStartTime; +#endif + + // 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]; + + // DTMF + class DTMFState : public nsITimerCallback { + virtual ~DTMFState(); + public: + DTMFState(); + + NS_DECL_NSITIMERCALLBACK + NS_DECL_THREADSAFE_ISUPPORTS + + PeerConnectionImpl* mPeerConnectionImpl; + nsCOMPtr<nsITimer> mSendTimer; + nsString mTrackId; + nsString mTones; + size_t mLevel; + uint32_t mDuration; + uint32_t mInterToneGap; + }; + + nsTArray<RefPtr<DTMFState>> mDTMFStates; + +public: + //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 +{ + public: + explicit PeerConnectionWrapper(const std::string& handle); + + PeerConnectionImpl *impl() { return impl_; } + + private: + RefPtr<PeerConnectionImpl> impl_; +}; + +} // end mozilla namespace + +#undef NS_IMETHODIMP_TO_ERRORRESULT +#undef NS_IMETHODIMP_TO_ERRORRESULT_RETREF +#endif // _PEER_CONNECTION_IMPL_H_ |