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