summaryrefslogtreecommitdiffstats
path: root/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
diff options
context:
space:
mode:
Diffstat (limited to 'media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h')
-rw-r--r--media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h586
1 files changed, 586 insertions, 0 deletions
diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
new file mode 100644
index 000000000..c0001a5e5
--- /dev/null
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
@@ -0,0 +1,586 @@
+/* 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_MEDIA_H_
+#define _PEER_CONNECTION_MEDIA_H_
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "nspr.h"
+#include "prlock.h"
+
+#include "mozilla/RefPtr.h"
+#include "mozilla/UniquePtr.h"
+#include "nsComponentManagerUtils.h"
+#include "nsIProtocolProxyCallback.h"
+
+#include "signaling/src/jsep/JsepSession.h"
+#include "AudioSegment.h"
+
+#if !defined(MOZILLA_EXTERNAL_LINKAGE)
+#include "Layers.h"
+#include "VideoUtils.h"
+#include "ImageLayers.h"
+#include "VideoSegment.h"
+#include "MediaStreamTrack.h"
+#endif
+
+class nsIPrincipal;
+
+namespace mozilla {
+class DataChannel;
+class PeerIdentity;
+class MediaPipelineFactory;
+namespace dom {
+struct RTCInboundRTPStreamStats;
+struct RTCOutboundRTPStreamStats;
+}
+}
+
+#include "nricectxhandler.h"
+#include "nriceresolver.h"
+#include "nricemediastream.h"
+#include "MediaPipeline.h"
+
+namespace mozilla {
+
+class PeerConnectionImpl;
+class PeerConnectionMedia;
+class PCUuidGenerator;
+
+class SourceStreamInfo {
+public:
+ SourceStreamInfo(DOMMediaStream* aMediaStream,
+ PeerConnectionMedia *aParent,
+ const std::string& aId)
+ : mMediaStream(aMediaStream),
+ mParent(aParent),
+ mId(aId) {
+ MOZ_ASSERT(mMediaStream);
+ }
+
+ SourceStreamInfo(already_AddRefed<DOMMediaStream>& aMediaStream,
+ PeerConnectionMedia *aParent,
+ const std::string& aId)
+ : mMediaStream(aMediaStream),
+ mParent(aParent),
+ mId(aId) {
+ MOZ_ASSERT(mMediaStream);
+ }
+
+ virtual ~SourceStreamInfo() {}
+
+ DOMMediaStream* GetMediaStream() const {
+ return mMediaStream;
+ }
+
+ nsresult StorePipeline(const std::string& trackId,
+ const RefPtr<MediaPipeline>& aPipeline);
+
+ virtual void AddTrack(const std::string& trackId,
+ const RefPtr<dom::MediaStreamTrack>& aTrack)
+ {
+ mTracks.insert(std::make_pair(trackId, aTrack));
+ }
+ virtual void RemoveTrack(const std::string& trackId);
+ bool HasTrack(const std::string& trackId) const
+ {
+ return !!mTracks.count(trackId);
+ }
+ size_t GetTrackCount() const { return mTracks.size(); }
+
+ // This method exists for stats and the unittests.
+ // It allows visibility into the pipelines and flows.
+ const std::map<std::string, RefPtr<MediaPipeline>>&
+ GetPipelines() const { return mPipelines; }
+ RefPtr<MediaPipeline> GetPipelineByTrackId_m(const std::string& trackId);
+ // This is needed so PeerConnectionImpl can unregister itself as
+ // PrincipalChangeObserver from each track.
+ const std::map<std::string, RefPtr<dom::MediaStreamTrack>>&
+ GetMediaStreamTracks() const { return mTracks; }
+ dom::MediaStreamTrack* GetTrackById(const std::string& trackId) const
+ {
+ auto it = mTracks.find(trackId);
+ if (it == mTracks.end()) {
+ return nullptr;
+ }
+
+ return it->second;
+ }
+ const std::string& GetId() const { return mId; }
+
+ void DetachTransport_s();
+ virtual void DetachMedia_m();
+ bool AnyCodecHasPluginID(uint64_t aPluginID);
+protected:
+ void EndTrack(MediaStream* stream, dom::MediaStreamTrack* track);
+ RefPtr<DOMMediaStream> mMediaStream;
+ PeerConnectionMedia *mParent;
+ const std::string mId;
+ // These get set up before we generate our local description, the pipelines
+ // and conduits are set up once offer/answer completes.
+ std::map<std::string, RefPtr<dom::MediaStreamTrack>> mTracks;
+ std::map<std::string, RefPtr<MediaPipeline>> mPipelines;
+};
+
+// TODO(ekr@rtfm.com): Refactor {Local,Remote}SourceStreamInfo
+// bug 837539.
+class LocalSourceStreamInfo : public SourceStreamInfo {
+ ~LocalSourceStreamInfo() {
+ mMediaStream = nullptr;
+ }
+public:
+ LocalSourceStreamInfo(DOMMediaStream *aMediaStream,
+ PeerConnectionMedia *aParent,
+ const std::string& aId)
+ : SourceStreamInfo(aMediaStream, aParent, aId) {}
+
+ nsresult TakePipelineFrom(RefPtr<LocalSourceStreamInfo>& info,
+ const std::string& oldTrackId,
+ dom::MediaStreamTrack& aNewTrack,
+ const std::string& newTrackId);
+
+#if !defined(MOZILLA_EXTERNAL_LINKAGE)
+ void UpdateSinkIdentity_m(dom::MediaStreamTrack* aTrack,
+ nsIPrincipal* aPrincipal,
+ const PeerIdentity* aSinkIdentity);
+#endif
+
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(LocalSourceStreamInfo)
+
+private:
+ already_AddRefed<MediaPipeline> ForgetPipelineByTrackId_m(
+ const std::string& trackId);
+};
+
+#if !defined(MOZILLA_EXTERNAL_LINKAGE)
+class RemoteTrackSource : public dom::MediaStreamTrackSource
+{
+public:
+ explicit RemoteTrackSource(nsIPrincipal* aPrincipal, const nsString& aLabel)
+ : dom::MediaStreamTrackSource(aPrincipal, aLabel) {}
+
+ dom::MediaSourceEnum GetMediaSource() const override
+ {
+ return dom::MediaSourceEnum::Other;
+ }
+
+ already_AddRefed<PledgeVoid>
+ ApplyConstraints(nsPIDOMWindowInner* aWindow,
+ const dom::MediaTrackConstraints& aConstraints) override;
+
+ void Stop() override
+ {
+ // XXX (Bug 1314270): Implement rejection logic if necessary when we have
+ // clarity in the spec.
+ }
+
+ void SetPrincipal(nsIPrincipal* aPrincipal)
+ {
+ mPrincipal = aPrincipal;
+ PrincipalChanged();
+ }
+
+protected:
+ virtual ~RemoteTrackSource() {}
+};
+#endif
+
+class RemoteSourceStreamInfo : public SourceStreamInfo {
+ ~RemoteSourceStreamInfo() {}
+ public:
+ RemoteSourceStreamInfo(already_AddRefed<DOMMediaStream> aMediaStream,
+ PeerConnectionMedia *aParent,
+ const std::string& aId)
+ : SourceStreamInfo(aMediaStream, aParent, aId),
+ mReceiving(false)
+ {
+ }
+
+ void DetachMedia_m() override;
+ void RemoveTrack(const std::string& trackId) override;
+ void SyncPipeline(RefPtr<MediaPipelineReceive> aPipeline);
+
+#if !defined(MOZILLA_EXTERNAL_LINKAGE)
+ void UpdatePrincipal_m(nsIPrincipal* aPrincipal);
+#endif
+
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteSourceStreamInfo)
+
+ void AddTrack(const std::string& trackId,
+ const RefPtr<dom::MediaStreamTrack>& aTrack) override
+ {
+ SourceStreamInfo::AddTrack(trackId, aTrack);
+ }
+
+ TrackID GetNumericTrackId(const std::string& trackId) const
+ {
+ dom::MediaStreamTrack* track = GetTrackById(trackId);
+ if (!track) {
+ return TRACK_INVALID;
+ }
+ return track->mTrackID;
+ }
+
+ void StartReceiving();
+
+ private:
+ // True iff SetPullEnabled(true) has been called on the DOMMediaStream. This
+ // happens when offer/answer concludes.
+ bool mReceiving;
+};
+
+class PeerConnectionMedia : public sigslot::has_slots<> {
+ ~PeerConnectionMedia()
+ {
+ MOZ_RELEASE_ASSERT(!mMainThread);
+ }
+
+ public:
+ explicit PeerConnectionMedia(PeerConnectionImpl *parent);
+
+ enum IceRestartState { ICE_RESTART_NONE,
+ ICE_RESTART_PROVISIONAL,
+ ICE_RESTART_COMMITTED
+ };
+
+ PeerConnectionImpl* GetPC() { return mParent; }
+ nsresult Init(const std::vector<NrIceStunServer>& stun_servers,
+ const std::vector<NrIceTurnServer>& turn_servers,
+ NrIceCtx::Policy policy);
+ // WARNING: This destroys the object!
+ void SelfDestruct();
+
+ RefPtr<NrIceCtxHandler> ice_ctx_hdlr() const { return mIceCtxHdlr; }
+ RefPtr<NrIceCtx> ice_ctx() const { return mIceCtxHdlr->ctx(); }
+
+ RefPtr<NrIceMediaStream> ice_media_stream(size_t i) const {
+ return mIceCtxHdlr->ctx()->GetStream(i);
+ }
+
+ size_t num_ice_media_streams() const {
+ return mIceCtxHdlr->ctx()->GetStreamCount();
+ }
+
+ // Ensure ICE transports exist that we might need when offer/answer concludes
+ void EnsureTransports(const JsepSession& aSession);
+
+ // Activate or remove ICE transports at the conclusion of offer/answer,
+ // or when rollback occurs.
+ void ActivateOrRemoveTransports(const JsepSession& aSession);
+
+ // Start ICE checks.
+ void StartIceChecks(const JsepSession& session);
+
+ bool IsIceRestarting() const;
+ IceRestartState GetIceRestartState() const;
+
+ // Begin ICE restart
+ void BeginIceRestart(const std::string& ufrag,
+ const std::string& pwd);
+ // Commit ICE Restart - offer/answer complete, no rollback possible
+ void CommitIceRestart();
+ // Finalize ICE restart
+ void FinalizeIceRestart();
+ // Abort ICE restart
+ void RollbackIceRestart();
+
+ // Process a trickle ICE candidate.
+ void AddIceCandidate(const std::string& candidate, const std::string& mid,
+ uint32_t aMLine);
+
+ // Handle complete media pipelines.
+ nsresult UpdateMediaPipelines(const JsepSession& session);
+
+ // Add a track (main thread only)
+ nsresult AddTrack(DOMMediaStream& aMediaStream,
+ const std::string& streamId,
+ dom::MediaStreamTrack& aTrack,
+ const std::string& trackId);
+
+ nsresult RemoveLocalTrack(const std::string& streamId,
+ const std::string& trackId);
+ nsresult RemoveRemoteTrack(const std::string& streamId,
+ const std::string& trackId);
+
+ // Get a specific local stream
+ uint32_t LocalStreamsLength()
+ {
+ return mLocalSourceStreams.Length();
+ }
+ LocalSourceStreamInfo* GetLocalStreamByIndex(int index);
+ LocalSourceStreamInfo* GetLocalStreamById(const std::string& id);
+ LocalSourceStreamInfo* GetLocalStreamByTrackId(const std::string& id);
+
+ // Get a specific remote stream
+ uint32_t RemoteStreamsLength()
+ {
+ return mRemoteSourceStreams.Length();
+ }
+
+ RemoteSourceStreamInfo* GetRemoteStreamByIndex(size_t index);
+ RemoteSourceStreamInfo* GetRemoteStreamById(const std::string& id);
+ RemoteSourceStreamInfo* GetRemoteStreamByTrackId(const std::string& id);
+
+ // Add a remote stream.
+ nsresult AddRemoteStream(RefPtr<RemoteSourceStreamInfo> aInfo);
+
+ nsresult ReplaceTrack(const std::string& aOldStreamId,
+ const std::string& aOldTrackId,
+ dom::MediaStreamTrack& aNewTrack,
+ const std::string& aNewStreamId,
+ const std::string& aNewTrackId);
+
+#if !defined(MOZILLA_EXTERNAL_LINKAGE)
+ // In cases where the peer isn't yet identified, we disable the pipeline (not
+ // the stream, that would potentially affect others), so that it sends
+ // black/silence. Once the peer is identified, re-enable those streams.
+ // aTrack will be set if this update came from a principal change on aTrack.
+ void UpdateSinkIdentity_m(dom::MediaStreamTrack* aTrack,
+ nsIPrincipal* aPrincipal,
+ const PeerIdentity* aSinkIdentity);
+ // this determines if any track is peerIdentity constrained
+ bool AnyLocalTrackHasPeerIdentity() const;
+ // When we finally learn who is on the other end, we need to change the ownership
+ // on streams
+ void UpdateRemoteStreamPrincipals_m(nsIPrincipal* aPrincipal);
+#endif
+
+ bool AnyCodecHasPluginID(uint64_t aPluginID);
+
+ const nsCOMPtr<nsIThread>& GetMainThread() const { return mMainThread; }
+ const nsCOMPtr<nsIEventTarget>& GetSTSThread() const { return mSTSThread; }
+
+ static size_t GetTransportFlowIndex(int aStreamIndex, bool aRtcp)
+ {
+ return aStreamIndex * 2 + (aRtcp ? 1 : 0);
+ }
+
+ // Get a transport flow either RTP/RTCP for a particular stream
+ // A stream can be of audio/video/datachannel/budled(?) types
+ RefPtr<TransportFlow> GetTransportFlow(int aStreamIndex, bool aIsRtcp) {
+ int index_inner = GetTransportFlowIndex(aStreamIndex, aIsRtcp);
+
+ if (mTransportFlows.find(index_inner) == mTransportFlows.end())
+ return nullptr;
+
+ return mTransportFlows[index_inner];
+ }
+
+ // Add a transport flow
+ void AddTransportFlow(int aIndex, bool aRtcp,
+ const RefPtr<TransportFlow> &aFlow);
+ void RemoveTransportFlow(int aIndex, bool aRtcp);
+ void ConnectDtlsListener_s(const RefPtr<TransportFlow>& aFlow);
+ void DtlsConnected_s(TransportLayer* aFlow,
+ TransportLayer::State state);
+ static void DtlsConnected_m(const std::string& aParentHandle,
+ bool aPrivacyRequested);
+
+ RefPtr<AudioSessionConduit> GetAudioConduit(size_t level) {
+ auto it = mConduits.find(level);
+ if (it == mConduits.end()) {
+ return nullptr;
+ }
+
+ if (it->second.first) {
+ MOZ_ASSERT(false, "In GetAudioConduit, we found a video conduit!");
+ return nullptr;
+ }
+
+ return RefPtr<AudioSessionConduit>(
+ static_cast<AudioSessionConduit*>(it->second.second.get()));
+ }
+
+ RefPtr<VideoSessionConduit> GetVideoConduit(size_t level) {
+ auto it = mConduits.find(level);
+ if (it == mConduits.end()) {
+ return nullptr;
+ }
+
+ if (!it->second.first) {
+ MOZ_ASSERT(false, "In GetVideoConduit, we found an audio conduit!");
+ return nullptr;
+ }
+
+ return RefPtr<VideoSessionConduit>(
+ static_cast<VideoSessionConduit*>(it->second.second.get()));
+ }
+
+ // Add a conduit
+ void AddAudioConduit(size_t level, const RefPtr<AudioSessionConduit> &aConduit) {
+ mConduits[level] = std::make_pair(false, aConduit);
+ }
+
+ void AddVideoConduit(size_t level, const RefPtr<VideoSessionConduit> &aConduit) {
+ mConduits[level] = std::make_pair(true, aConduit);
+ }
+
+ // ICE state signals
+ sigslot::signal2<NrIceCtx*, NrIceCtx::GatheringState>
+ SignalIceGatheringStateChange;
+ sigslot::signal2<NrIceCtx*, NrIceCtx::ConnectionState>
+ SignalIceConnectionStateChange;
+ // This passes a candidate:... attribute and level
+ sigslot::signal2<const std::string&, uint16_t> SignalCandidate;
+ // This passes address, port, level of the default candidate.
+ sigslot::signal5<const std::string&, uint16_t,
+ const std::string&, uint16_t, uint16_t>
+ SignalUpdateDefaultCandidate;
+ sigslot::signal1<uint16_t>
+ SignalEndOfLocalCandidates;
+
+ private:
+ nsresult InitProxy();
+ class ProtocolProxyQueryHandler : public nsIProtocolProxyCallback {
+ public:
+ explicit ProtocolProxyQueryHandler(PeerConnectionMedia *pcm) :
+ pcm_(pcm) {}
+
+ NS_IMETHOD OnProxyAvailable(nsICancelable *request,
+ nsIChannel *aChannel,
+ nsIProxyInfo *proxyinfo,
+ nsresult result) override;
+ NS_DECL_ISUPPORTS
+
+ private:
+ void SetProxyOnPcm(nsIProxyInfo& proxyinfo);
+ RefPtr<PeerConnectionMedia> pcm_;
+ virtual ~ProtocolProxyQueryHandler() {}
+ };
+
+ // Shutdown media transport. Must be called on STS thread.
+ void ShutdownMediaTransport_s();
+
+ // Final destruction of the media stream. Must be called on the main
+ // thread.
+ void SelfDestruct_m();
+
+ // Manage ICE transports.
+ void EnsureTransport_s(size_t aLevel, size_t aComponentCount);
+ void ActivateOrRemoveTransport_s(
+ size_t aMLine,
+ size_t aComponentCount,
+ const std::string& aUfrag,
+ const std::string& aPassword,
+ const std::vector<std::string>& aCandidateList);
+ void RemoveTransportsAtOrAfter_s(size_t aMLine);
+
+ void GatherIfReady();
+ void FlushIceCtxOperationQueueIfReady();
+ void PerformOrEnqueueIceCtxOperation(nsIRunnable* runnable);
+ void EnsureIceGathering_s(bool aDefaultRouteOnly, bool aProxyOnly);
+ void StartIceChecks_s(bool aIsControlling,
+ bool aIsIceLite,
+ const std::vector<std::string>& aIceOptionsList);
+
+ void BeginIceRestart_s(RefPtr<NrIceCtx> new_ctx);
+ void FinalizeIceRestart_s();
+ void RollbackIceRestart_s();
+ bool GetPrefDefaultAddressOnly() const;
+ bool GetPrefProxyOnly() const;
+
+ void ConnectSignals(NrIceCtx *aCtx, NrIceCtx *aOldCtx=nullptr);
+
+ // Process a trickle ICE candidate.
+ void AddIceCandidate_s(const std::string& aCandidate, const std::string& aMid,
+ uint32_t aMLine);
+
+
+ // ICE events
+ void IceGatheringStateChange_s(NrIceCtx* ctx,
+ NrIceCtx::GatheringState state);
+ void IceConnectionStateChange_s(NrIceCtx* ctx,
+ NrIceCtx::ConnectionState state);
+ void IceStreamReady_s(NrIceMediaStream *aStream);
+ void OnCandidateFound_s(NrIceMediaStream *aStream,
+ const std::string& aCandidate);
+ void EndOfLocalCandidates(const std::string& aDefaultAddr,
+ uint16_t aDefaultPort,
+ const std::string& aDefaultRtcpAddr,
+ uint16_t aDefaultRtcpPort,
+ uint16_t aMLine);
+ void GetDefaultCandidates(const NrIceMediaStream& aStream,
+ NrIceCandidate* aCandidate,
+ NrIceCandidate* aRtcpCandidate);
+
+ void IceGatheringStateChange_m(NrIceCtx* ctx,
+ NrIceCtx::GatheringState state);
+ void IceConnectionStateChange_m(NrIceCtx* ctx,
+ NrIceCtx::ConnectionState state);
+ void OnCandidateFound_m(const std::string& aCandidateLine,
+ const std::string& aDefaultAddr,
+ uint16_t aDefaultPort,
+ const std::string& aDefaultRtcpAddr,
+ uint16_t aDefaultRtcpPort,
+ uint16_t aMLine);
+ void EndOfLocalCandidates_m(const std::string& aDefaultAddr,
+ uint16_t aDefaultPort,
+ const std::string& aDefaultRtcpAddr,
+ uint16_t aDefaultRtcpPort,
+ uint16_t aMLine);
+ bool IsIceCtxReady() const {
+ return mProxyResolveCompleted;
+ }
+
+ // The parent PC
+ PeerConnectionImpl *mParent;
+ // and a loose handle on it for event driven stuff
+ std::string mParentHandle;
+ std::string mParentName;
+
+ // A list of streams returned from GetUserMedia
+ // This is only accessed on the main thread (with one special exception)
+ nsTArray<RefPtr<LocalSourceStreamInfo> > mLocalSourceStreams;
+
+ // A list of streams provided by the other side
+ // This is only accessed on the main thread (with one special exception)
+ nsTArray<RefPtr<RemoteSourceStreamInfo> > mRemoteSourceStreams;
+
+ std::map<size_t, std::pair<bool, RefPtr<MediaSessionConduit>>> mConduits;
+
+ // ICE objects
+ RefPtr<NrIceCtxHandler> mIceCtxHdlr;
+
+ // DNS
+ RefPtr<NrIceResolver> mDNSResolver;
+
+ // Transport flows: even is RTP, odd is RTCP
+ std::map<int, RefPtr<TransportFlow> > mTransportFlows;
+
+ // UUID Generator
+ UniquePtr<PCUuidGenerator> mUuidGen;
+
+ // The main thread.
+ nsCOMPtr<nsIThread> mMainThread;
+
+ // The STS thread.
+ nsCOMPtr<nsIEventTarget> mSTSThread;
+
+ // Used whenever we need to dispatch a runnable to STS to tweak something
+ // on our ICE ctx, but are not ready to do so at the moment (eg; we are
+ // waiting to get a callback with our http proxy config before we start
+ // gathering or start checking)
+ std::vector<nsCOMPtr<nsIRunnable>> mQueuedIceCtxOperations;
+
+ // Used to cancel any ongoing proxy request.
+ nsCOMPtr<nsICancelable> mProxyRequest;
+
+ // Used to track the state of the request.
+ bool mProxyResolveCompleted;
+
+ // Used to store the result of the request.
+ UniquePtr<NrIceProxyServer> mProxyServer;
+
+ // Used to track the state of ice restart
+ IceRestartState mIceRestartState;
+
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PeerConnectionMedia)
+};
+
+} // namespace mozilla
+
+#endif