1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 #ifndef _PEER_CONNECTION_MEDIA_H_
6 #define _PEER_CONNECTION_MEDIA_H_
7 
8 #include <string>
9 #include <vector>
10 #include <map>
11 
12 #include "mozilla/RefPtr.h"
13 #include "mozilla/UniquePtr.h"
14 #include "mozilla/net/StunAddrsRequestChild.h"
15 #include "nsIProtocolProxyCallback.h"
16 
17 #include "TransceiverImpl.h"
18 
19 class nsIPrincipal;
20 
21 namespace mozilla {
22 class DataChannel;
23 class PeerIdentity;
24 namespace dom {
25 struct RTCInboundRTPStreamStats;
26 struct RTCOutboundRTPStreamStats;
27 class MediaStreamTrack;
28 }  // namespace dom
29 }  // namespace mozilla
30 
31 #include "nricectxhandler.h"
32 #include "nriceresolver.h"
33 #include "nricemediastream.h"
34 
35 namespace mozilla {
36 
37 class PeerConnectionImpl;
38 class PeerConnectionMedia;
39 class PCUuidGenerator;
40 class MediaPipeline;
41 class MediaPipelineFilter;
42 class JsepSession;
43 
44 // TODO(bug 1402997): If we move the TransceiverImpl stuff out of here, this
45 // will be a class that handles just the transport stuff, and we can rename it
46 // to something more explanatory (say, PeerConnectionTransportManager).
47 class PeerConnectionMedia : public sigslot::has_slots<> {
48   ~PeerConnectionMedia();
49 
50  public:
51   explicit PeerConnectionMedia(PeerConnectionImpl* parent);
52 
53   enum IceRestartState {
54     ICE_RESTART_NONE,
55     ICE_RESTART_PROVISIONAL,
56     ICE_RESTART_COMMITTED
57   };
58 
GetPC()59   PeerConnectionImpl* GetPC() { return mParent; }
60   nsresult Init(const std::vector<NrIceStunServer>& stun_servers,
61                 const std::vector<NrIceTurnServer>& turn_servers,
62                 NrIceCtx::Policy policy);
63   // WARNING: This destroys the object!
64   void SelfDestruct();
65 
ice_ctx_hdlr()66   RefPtr<NrIceCtxHandler> ice_ctx_hdlr() const { return mIceCtxHdlr; }
ice_ctx()67   RefPtr<NrIceCtx> ice_ctx() const { return mIceCtxHdlr->ctx(); }
68 
ice_media_stream(size_t i)69   RefPtr<NrIceMediaStream> ice_media_stream(size_t i) const {
70     return mIceCtxHdlr->ctx()->GetStream(i);
71   }
72 
num_ice_media_streams()73   size_t num_ice_media_streams() const {
74     return mIceCtxHdlr->ctx()->GetStreamCount();
75   }
76 
77   // Ensure ICE transports exist that we might need when offer/answer concludes
78   void EnsureTransports(const JsepSession& aSession);
79 
80   // Activate or remove ICE transports at the conclusion of offer/answer,
81   // or when rollback occurs.
82   nsresult ActivateOrRemoveTransports(const JsepSession& aSession,
83                                       const bool forceIceTcp);
84 
85   // Update the transports on the TransceiverImpls
86   nsresult UpdateTransceiverTransports(const JsepSession& aSession);
87 
88   // Start ICE checks.
89   void StartIceChecks(const JsepSession& session);
90 
91   bool IsIceRestarting() const;
92   IceRestartState GetIceRestartState() const;
93 
94   // Begin ICE restart
95   void BeginIceRestart(const std::string& ufrag, const std::string& pwd);
96   // Commit ICE Restart - offer/answer complete, no rollback possible
97   void CommitIceRestart();
98   // Finalize ICE restart
99   void FinalizeIceRestart();
100   // Abort ICE restart
101   void RollbackIceRestart();
102 
103   // Process a trickle ICE candidate.
104   void AddIceCandidate(const std::string& candidate, const std::string& mid,
105                        uint32_t aMLine);
106 
107   // Handle notifications of network online/offline events.
108   void UpdateNetworkState(bool online);
109 
110   // Handle complete media pipelines.
111   // This updates codec parameters, starts/stops send/receive, and other
112   // stuff that doesn't necessarily require negotiation. This can be called at
113   // any time, not just when an offer/answer exchange completes.
114   // TODO: Let's move this to PeerConnectionImpl
115   nsresult UpdateMediaPipelines();
116 
117   // TODO: Let's move the TransceiverImpl stuff to PeerConnectionImpl.
118   nsresult AddTransceiver(JsepTransceiver* aJsepTransceiver,
119                           dom::MediaStreamTrack& aReceiveTrack,
120                           dom::MediaStreamTrack* aSendTrack,
121                           RefPtr<TransceiverImpl>* aTransceiverImpl);
122 
123   void GetTransmitPipelinesMatching(
124       dom::MediaStreamTrack* aTrack,
125       nsTArray<RefPtr<MediaPipeline>>* aPipelines);
126 
127   void GetReceivePipelinesMatching(dom::MediaStreamTrack* aTrack,
128                                    nsTArray<RefPtr<MediaPipeline>>* aPipelines);
129 
130   nsresult AddRIDExtension(dom::MediaStreamTrack& aRecvTrack,
131                            unsigned short aExtensionId);
132 
133   nsresult AddRIDFilter(dom::MediaStreamTrack& aRecvTrack,
134                         const nsAString& aRid);
135 
136   // In cases where the peer isn't yet identified, we disable the pipeline (not
137   // the stream, that would potentially affect others), so that it sends
138   // black/silence.  Once the peer is identified, re-enable those streams.
139   // aTrack will be set if this update came from a principal change on aTrack.
140   // TODO: Move to PeerConnectionImpl
141   void UpdateSinkIdentity_m(const dom::MediaStreamTrack* aTrack,
142                             nsIPrincipal* aPrincipal,
143                             const PeerIdentity* aSinkIdentity);
144   // this determines if any track is peerIdentity constrained
145   bool AnyLocalTrackHasPeerIdentity() const;
146   // When we finally learn who is on the other end, we need to change the
147   // ownership on streams
148   void UpdateRemoteStreamPrincipals_m(nsIPrincipal* aPrincipal);
149 
150   bool AnyCodecHasPluginID(uint64_t aPluginID);
151 
GetMainThread()152   const nsCOMPtr<nsIThread>& GetMainThread() const { return mMainThread; }
GetSTSThread()153   const nsCOMPtr<nsIEventTarget>& GetSTSThread() const { return mSTSThread; }
154 
GetTransportFlowIndex(int aStreamIndex,bool aRtcp)155   static size_t GetTransportFlowIndex(int aStreamIndex, bool aRtcp) {
156     return aStreamIndex * 2 + (aRtcp ? 1 : 0);
157   }
158 
159   // Get a transport flow either RTP/RTCP for a particular stream
160   // A stream can be of audio/video/datachannel/budled(?) types
GetTransportFlow(int aStreamIndex,bool aIsRtcp)161   RefPtr<TransportFlow> GetTransportFlow(int aStreamIndex, bool aIsRtcp) {
162     int index_inner = GetTransportFlowIndex(aStreamIndex, aIsRtcp);
163 
164     if (mTransportFlows.find(index_inner) == mTransportFlows.end())
165       return nullptr;
166 
167     return mTransportFlows[index_inner];
168   }
169 
170   // Used by PCImpl in a couple of places. Might be good to move that code in
171   // here.
GetTransceivers()172   std::vector<RefPtr<TransceiverImpl>>& GetTransceivers() {
173     return mTransceivers;
174   }
175 
176   // Add a transport flow
177   void AddTransportFlow(int aIndex, bool aRtcp,
178                         const RefPtr<TransportFlow>& aFlow);
179   void RemoveTransportFlow(int aIndex, bool aRtcp);
180   void ConnectDtlsListener_s(const RefPtr<TransportFlow>& aFlow);
181   void DtlsConnected_s(TransportLayer* aFlow, TransportLayer::State state);
182   static void DtlsConnected_m(const std::string& aParentHandle,
183                               bool aPrivacyRequested);
184 
185   // ICE state signals
186   sigslot::signal2<NrIceCtx*, NrIceCtx::GatheringState>
187       SignalIceGatheringStateChange;
188   sigslot::signal2<NrIceCtx*, NrIceCtx::ConnectionState>
189       SignalIceConnectionStateChange;
190   // This passes a candidate:... attribute  and level
191   sigslot::signal2<const std::string&, uint16_t> SignalCandidate;
192   // This passes address, port, level of the default candidate.
193   sigslot::signal5<const std::string&, uint16_t, const std::string&, uint16_t,
194                    uint16_t>
195       SignalUpdateDefaultCandidate;
196   sigslot::signal1<uint16_t> SignalEndOfLocalCandidates;
197 
198   // TODO: Move to PeerConnectionImpl
199   RefPtr<WebRtcCallWrapper> mCall;
200 
201  private:
202   void InitLocalAddrs();  // for stun local address IPC request
203   nsresult InitProxy();
204   class ProtocolProxyQueryHandler : public nsIProtocolProxyCallback {
205    public:
ProtocolProxyQueryHandler(PeerConnectionMedia * pcm)206     explicit ProtocolProxyQueryHandler(PeerConnectionMedia* pcm) : pcm_(pcm) {}
207 
208     NS_IMETHOD OnProxyAvailable(nsICancelable* request, nsIChannel* aChannel,
209                                 nsIProxyInfo* proxyinfo,
210                                 nsresult result) override;
211     NS_DECL_ISUPPORTS
212 
213    private:
214     void SetProxyOnPcm(nsIProxyInfo& proxyinfo);
215     RefPtr<PeerConnectionMedia> pcm_;
~ProtocolProxyQueryHandler()216     virtual ~ProtocolProxyQueryHandler() {}
217   };
218 
219   class StunAddrsHandler : public net::StunAddrsListener {
220    public:
StunAddrsHandler(PeerConnectionMedia * pcm)221     explicit StunAddrsHandler(PeerConnectionMedia* pcm) : pcm_(pcm) {}
222     void OnStunAddrsAvailable(
223         const mozilla::net::NrIceStunAddrArray& addrs) override;
224 
225    private:
226     RefPtr<PeerConnectionMedia> pcm_;
~StunAddrsHandler()227     virtual ~StunAddrsHandler() {}
228   };
229 
230   // Shutdown media transport. Must be called on STS thread.
231   void ShutdownMediaTransport_s();
232 
233   // Final destruction of the media stream. Must be called on the main
234   // thread.
235   void SelfDestruct_m();
236 
237   // Manage ICE transports.
238   void EnsureTransport_s(size_t aLevel, size_t aComponentCount);
239   void ActivateOrRemoveTransport_s(
240       size_t aMLine, size_t aComponentCount, const std::string& aUfrag,
241       const std::string& aPassword,
242       const std::vector<std::string>& aCandidateList);
243   void RemoveTransportsAtOrAfter_s(size_t aMLine);
244   nsresult UpdateTransportFlows(const JsepTransceiver& transceiver);
245   nsresult UpdateTransportFlow(size_t aLevel, bool aIsRtcp,
246                                const JsepTransport& aTransport);
247 
248   void GatherIfReady();
249   void FlushIceCtxOperationQueueIfReady();
250   void PerformOrEnqueueIceCtxOperation(nsIRunnable* runnable);
251   void EnsureIceGathering_s(bool aDefaultRouteOnly, bool aProxyOnly);
252   void StartIceChecks_s(bool aIsControlling, bool aIsOfferer, bool aIsIceLite,
253                         const std::vector<std::string>& aIceOptionsList);
254 
255   void BeginIceRestart_s(RefPtr<NrIceCtx> new_ctx);
256   void FinalizeIceRestart_s();
257   void RollbackIceRestart_s();
258   bool GetPrefDefaultAddressOnly() const;
259   bool GetPrefProxyOnly() const;
260 
261   void ConnectSignals(NrIceCtx* aCtx, NrIceCtx* aOldCtx = nullptr);
262 
263   // Process a trickle ICE candidate.
264   void AddIceCandidate_s(const std::string& aCandidate, const std::string& aMid,
265                          uint32_t aMLine);
266 
267   void UpdateNetworkState_s(bool online);
268 
269   // ICE events
270   void IceGatheringStateChange_s(NrIceCtx* ctx, NrIceCtx::GatheringState state);
271   void IceConnectionStateChange_s(NrIceCtx* ctx,
272                                   NrIceCtx::ConnectionState state);
273   void IceStreamReady_s(NrIceMediaStream* aStream);
274   void OnCandidateFound_s(NrIceMediaStream* aStream,
275                           const std::string& aCandidate);
276   void EndOfLocalCandidates(const std::string& aDefaultAddr,
277                             uint16_t aDefaultPort,
278                             const std::string& aDefaultRtcpAddr,
279                             uint16_t aDefaultRtcpPort, uint16_t aMLine);
280   void GetDefaultCandidates(const NrIceMediaStream& aStream,
281                             NrIceCandidate* aCandidate,
282                             NrIceCandidate* aRtcpCandidate);
283 
284   void IceGatheringStateChange_m(NrIceCtx* ctx, NrIceCtx::GatheringState state);
285   void IceConnectionStateChange_m(NrIceCtx* ctx,
286                                   NrIceCtx::ConnectionState state);
287   void OnCandidateFound_m(const std::string& aCandidateLine,
288                           const std::string& aDefaultAddr,
289                           uint16_t aDefaultPort,
290                           const std::string& aDefaultRtcpAddr,
291                           uint16_t aDefaultRtcpPort, uint16_t aMLine);
292   void EndOfLocalCandidates_m(const std::string& aDefaultAddr,
293                               uint16_t aDefaultPort,
294                               const std::string& aDefaultRtcpAddr,
295                               uint16_t aDefaultRtcpPort, uint16_t aMLine);
IsIceCtxReady()296   bool IsIceCtxReady() const {
297     return mProxyResolveCompleted && mLocalAddrsCompleted;
298   }
299 
300   // The parent PC
301   PeerConnectionImpl* mParent;
302   // and a loose handle on it for event driven stuff
303   std::string mParentHandle;
304   std::string mParentName;
305 
306   std::vector<RefPtr<TransceiverImpl>> mTransceivers;
307 
308   // ICE objects
309   RefPtr<NrIceCtxHandler> mIceCtxHdlr;
310 
311   // DNS
312   RefPtr<NrIceResolver> mDNSResolver;
313 
314   // Transport flows: even is RTP, odd is RTCP
315   std::map<int, RefPtr<TransportFlow>> mTransportFlows;
316 
317   // UUID Generator
318   UniquePtr<PCUuidGenerator> mUuidGen;
319 
320   // The main thread.
321   nsCOMPtr<nsIThread> mMainThread;
322 
323   // The STS thread.
324   nsCOMPtr<nsIEventTarget> mSTSThread;
325 
326   // Used whenever we need to dispatch a runnable to STS to tweak something
327   // on our ICE ctx, but are not ready to do so at the moment (eg; we are
328   // waiting to get a callback with our http proxy config before we start
329   // gathering or start checking)
330   std::vector<nsCOMPtr<nsIRunnable>> mQueuedIceCtxOperations;
331 
332   // Used to cancel any ongoing proxy request.
333   nsCOMPtr<nsICancelable> mProxyRequest;
334 
335   // Used to track the state of the request.
336   bool mProxyResolveCompleted;
337 
338   // Used to store the result of the request.
339   UniquePtr<NrIceProxyServer> mProxyServer;
340 
341   // Used to track the state of ice restart
342   IceRestartState mIceRestartState;
343 
344   // Used to cancel incoming stun addrs response
345   RefPtr<net::StunAddrsRequestChild> mStunAddrsRequest;
346 
347   // Used to track the state of the stun addr IPC request
348   bool mLocalAddrsCompleted;
349 
350   // Used to store the result of the stun addr IPC request
351   nsTArray<NrIceStunAddr> mStunAddrs;
352 
353   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PeerConnectionMedia)
354 };
355 
356 }  // namespace mozilla
357 
358 #endif
359