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 #include "MediaTransportHandler.h"
6 #include "MediaTransportHandlerIPC.h"
7 #include "transport/nricemediastream.h"
8 #include "transport/nriceresolver.h"
9 #include "transport/transportflow.h"
10 #include "transport/transportlayerice.h"
11 #include "transport/transportlayerdtls.h"
12 #include "transport/transportlayersrtp.h"
13 
14 // Config stuff
15 #include "mozilla/dom/RTCConfigurationBinding.h"
16 #include "mozilla/Preferences.h"
17 
18 // Parsing STUN/TURN URIs
19 #include "nsIURI.h"
20 #include "nsNetUtil.h"
21 #include "nsURLHelper.h"
22 #include "nsIURLParser.h"
23 
24 // Logging stuff
25 #include "common/browser_logging/CSFLog.h"
26 
27 // For fetching ICE logging
28 #include "transport/rlogconnector.h"
29 
30 // DTLS
31 #include "sdp/SdpAttribute.h"
32 
33 #include "transport/runnable_utils.h"
34 
35 #include "mozilla/Algorithm.h"
36 #include "mozilla/Telemetry.h"
37 
38 #include "mozilla/dom/RTCStatsReportBinding.h"
39 
40 #include "nss.h"                // For NSS_NoDB_Init
41 #include "mozilla/PublicSSL.h"  // For psm::InitializeCipherSuite
42 
43 #include "nsISocketTransportService.h"
44 #include "nsDNSService2.h"
45 #include "nsNetUtil.h"  // NS_CheckPortSafety
46 
47 #include <string>
48 #include <vector>
49 #include <map>
50 
51 namespace mozilla {
52 
53 static const char* mthLogTag = "MediaTransportHandler";
54 #ifdef LOGTAG
55 #  undef LOGTAG
56 #endif
57 #define LOGTAG mthLogTag
58 
59 class MediaTransportHandlerSTS : public MediaTransportHandler,
60                                  public sigslot::has_slots<> {
61  public:
62   explicit MediaTransportHandlerSTS(nsISerialEventTarget* aCallbackThread);
63 
64   RefPtr<IceLogPromise> GetIceLog(const nsCString& aPattern) override;
65   void ClearIceLog() override;
66   void EnterPrivateMode() override;
67   void ExitPrivateMode() override;
68 
69   nsresult CreateIceCtx(const std::string& aName,
70                         const nsTArray<dom::RTCIceServer>& aIceServers,
71                         dom::RTCIceTransportPolicy aIcePolicy) override;
72 
73   // We will probably be able to move the proxy lookup stuff into
74   // this class once we move mtransport to its own process.
75   void SetProxyConfig(NrSocketProxyConfig&& aProxyConfig) override;
76 
77   void EnsureProvisionalTransport(const std::string& aTransportId,
78                                   const std::string& aUfrag,
79                                   const std::string& aPwd,
80                                   size_t aComponentCount) override;
81 
82   void SetTargetForDefaultLocalAddressLookup(const std::string& aTargetIp,
83                                              uint16_t aTargetPort) override;
84 
85   // We set default-route-only as late as possible because it depends on what
86   // capture permissions have been granted on the window, which could easily
87   // change between Init (ie; when the PC is created) and StartIceGathering
88   // (ie; when we set the local description).
89   void StartIceGathering(bool aDefaultRouteOnly, bool aObfuscateHostAddresses,
90                          // This will go away once mtransport moves to its
91                          // own process, because we won't need to get this
92                          // via IPC anymore
93                          const nsTArray<NrIceStunAddr>& aStunAddrs) override;
94 
95   void ActivateTransport(
96       const std::string& aTransportId, const std::string& aLocalUfrag,
97       const std::string& aLocalPwd, size_t aComponentCount,
98       const std::string& aUfrag, const std::string& aPassword,
99       const nsTArray<uint8_t>& aKeyDer, const nsTArray<uint8_t>& aCertDer,
100       SSLKEAType aAuthType, bool aDtlsClient, const DtlsDigestList& aDigests,
101       bool aPrivacyRequested) override;
102 
103   void RemoveTransportsExcept(
104       const std::set<std::string>& aTransportIds) override;
105 
106   void StartIceChecks(bool aIsControlling,
107                       const std::vector<std::string>& aIceOptions) override;
108 
109   void AddIceCandidate(const std::string& aTransportId,
110                        const std::string& aCandidate, const std::string& aUfrag,
111                        const std::string& aObfuscatedAddress) override;
112 
113   void UpdateNetworkState(bool aOnline) override;
114 
115   void SendPacket(const std::string& aTransportId,
116                   MediaPacket&& aPacket) override;
117 
118   RefPtr<dom::RTCStatsPromise> GetIceStats(const std::string& aTransportId,
119                                            DOMHighResTimeStamp aNow) override;
120 
121   void Shutdown();
122 
123  private:
124   void Destroy() override;
125   void Destroy_s();
126   void DestroyFinal();
127   void Shutdown_s();
128   RefPtr<TransportFlow> CreateTransportFlow(const std::string& aTransportId,
129                                             bool aIsRtcp,
130                                             RefPtr<DtlsIdentity> aDtlsIdentity,
131                                             bool aDtlsClient,
132                                             const DtlsDigestList& aDigests,
133                                             bool aPrivacyRequested);
134 
135   struct Transport {
136     RefPtr<TransportFlow> mFlow;
137     RefPtr<TransportFlow> mRtcpFlow;
138   };
139 
140   using MediaTransportHandler::OnAlpnNegotiated;
141   using MediaTransportHandler::OnCandidate;
142   using MediaTransportHandler::OnConnectionStateChange;
143   using MediaTransportHandler::OnEncryptedSending;
144   using MediaTransportHandler::OnGatheringStateChange;
145   using MediaTransportHandler::OnPacketReceived;
146   using MediaTransportHandler::OnRtcpStateChange;
147   using MediaTransportHandler::OnStateChange;
148 
149   void OnGatheringStateChange(NrIceCtx* aIceCtx,
150                               NrIceCtx::GatheringState aState);
151   void OnConnectionStateChange(NrIceCtx* aIceCtx,
152                                NrIceCtx::ConnectionState aState);
153   void OnCandidateFound(NrIceMediaStream* aStream,
154                         const std::string& aCandidate,
155                         const std::string& aUfrag, const std::string& aMDNSAddr,
156                         const std::string& aActualAddr);
157   void OnStateChange(TransportLayer* aLayer, TransportLayer::State);
158   void OnRtcpStateChange(TransportLayer* aLayer, TransportLayer::State);
159   void PacketReceived(TransportLayer* aLayer, MediaPacket& aPacket);
160   void EncryptedPacketSending(TransportLayer* aLayer, MediaPacket& aPacket);
161   RefPtr<TransportFlow> GetTransportFlow(const std::string& aTransportId,
162                                          bool aIsRtcp) const;
163   void GetIceStats(const NrIceMediaStream& aStream, DOMHighResTimeStamp aNow,
164                    dom::RTCStatsCollection* aStats) const;
165 
166   virtual ~MediaTransportHandlerSTS() = default;
167   nsCOMPtr<nsISerialEventTarget> mStsThread;
168   RefPtr<NrIceCtx> mIceCtx;
169   RefPtr<NrIceResolver> mDNSResolver;
170   std::map<std::string, Transport> mTransports;
171   bool mObfuscateHostAddresses = false;
172   uint32_t mMinDtlsVersion = 0;
173   uint32_t mMaxDtlsVersion = 0;
174 
175   std::set<std::string> mSignaledAddresses;
176 
177   // Init can only be done on main, but we want this to be usable on any thread
178   typedef MozPromise<bool, std::string, false> InitPromise;
179   RefPtr<InitPromise> mInitPromise;
180 };
181 
182 /* static */
Create(nsISerialEventTarget * aCallbackThread)183 already_AddRefed<MediaTransportHandler> MediaTransportHandler::Create(
184     nsISerialEventTarget* aCallbackThread) {
185   RefPtr<MediaTransportHandler> result;
186   if (XRE_IsContentProcess() &&
187       Preferences::GetBool("media.peerconnection.mtransport_process") &&
188       Preferences::GetBool("network.process.enabled")) {
189     result = new MediaTransportHandlerIPC(aCallbackThread);
190   } else {
191     result = new MediaTransportHandlerSTS(aCallbackThread);
192   }
193   return result.forget();
194 }
195 
196 class STSShutdownHandler : public nsISTSShutdownObserver {
197  public:
198   NS_DECL_ISUPPORTS
199 
200   // Lazy singleton
Instance()201   static RefPtr<STSShutdownHandler>& Instance() {
202     MOZ_ASSERT(NS_IsMainThread());
203     static RefPtr<STSShutdownHandler> sHandler(new STSShutdownHandler);
204     return sHandler;
205   }
206 
Shutdown()207   void Shutdown() {
208     MOZ_ASSERT(NS_IsMainThread());
209     for (const auto& handler : mHandlers) {
210       handler->Shutdown();
211     }
212     mHandlers.clear();
213   }
214 
STSShutdownHandler()215   STSShutdownHandler() {
216     CSFLogDebug(LOGTAG, "%s", __func__);
217     nsresult res;
218     nsCOMPtr<nsISocketTransportService> sts =
219         do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &res);
220     MOZ_RELEASE_ASSERT(NS_SUCCEEDED(res));
221     MOZ_RELEASE_ASSERT(sts);
222     sts->AddShutdownObserver(this);
223   }
224 
Observe()225   NS_IMETHOD Observe() override {
226     CSFLogDebug(LOGTAG, "%s", __func__);
227     Shutdown();
228     nsresult res;
229     nsCOMPtr<nsISocketTransportService> sts =
230         do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &res);
231     MOZ_RELEASE_ASSERT(NS_SUCCEEDED(res));
232     MOZ_RELEASE_ASSERT(sts);
233     sts->RemoveShutdownObserver(this);
234     Instance() = nullptr;
235     return NS_OK;
236   }
237 
Register(MediaTransportHandlerSTS * aHandler)238   void Register(MediaTransportHandlerSTS* aHandler) {
239     MOZ_ASSERT(NS_IsMainThread());
240     mHandlers.insert(aHandler);
241   }
242 
Deregister(MediaTransportHandlerSTS * aHandler)243   void Deregister(MediaTransportHandlerSTS* aHandler) {
244     MOZ_ASSERT(NS_IsMainThread());
245     mHandlers.erase(aHandler);
246   }
247 
248  private:
~STSShutdownHandler()249   virtual ~STSShutdownHandler() {}
250 
251   // Raw ptrs, registered on init, deregistered on destruction, all on main
252   std::set<MediaTransportHandlerSTS*> mHandlers;
253 };
254 
255 NS_IMPL_ISUPPORTS(STSShutdownHandler, nsISTSShutdownObserver);
256 
MediaTransportHandlerSTS(nsISerialEventTarget * aCallbackThread)257 MediaTransportHandlerSTS::MediaTransportHandlerSTS(
258     nsISerialEventTarget* aCallbackThread)
259     : MediaTransportHandler(aCallbackThread) {
260   nsresult rv;
261   mStsThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
262   if (!mStsThread) {
263     MOZ_CRASH();
264   }
265 
266   RLogConnector::CreateInstance();
267 
268   CSFLogDebug(LOGTAG, "%s done %p", __func__, this);
269 
270   // We do not set up mDNSService here, because we are not running on main (we
271   // use PBackground), and the DNS service asserts.
272 }
273 
toNrIcePolicy(dom::RTCIceTransportPolicy aPolicy)274 static NrIceCtx::Policy toNrIcePolicy(dom::RTCIceTransportPolicy aPolicy) {
275   switch (aPolicy) {
276     case dom::RTCIceTransportPolicy::Relay:
277       return NrIceCtx::ICE_POLICY_RELAY;
278     case dom::RTCIceTransportPolicy::All:
279       if (Preferences::GetBool("media.peerconnection.ice.no_host", false)) {
280         return NrIceCtx::ICE_POLICY_NO_HOST;
281       } else {
282         return NrIceCtx::ICE_POLICY_ALL;
283       }
284     default:
285       MOZ_CRASH();
286   }
287   return NrIceCtx::ICE_POLICY_ALL;
288 }
289 
290 // list of known acceptable ports for webrtc
291 int16_t gGoodWebrtcPortList[] = {
292     53,    // Some deplyoments use DNS port to punch through overzealous NATs
293     3478,  // stun or turn
294     5349,  // stuns or turns
295     0,     // Sentinel value: This MUST be zero
296 };
297 
addNrIceServer(const nsString & aIceUrl,const dom::RTCIceServer & aIceServer,std::vector<NrIceStunServer> * aStunServersOut,std::vector<NrIceTurnServer> * aTurnServersOut)298 static nsresult addNrIceServer(const nsString& aIceUrl,
299                                const dom::RTCIceServer& aIceServer,
300                                std::vector<NrIceStunServer>* aStunServersOut,
301                                std::vector<NrIceTurnServer>* aTurnServersOut) {
302   // Without STUN/TURN handlers, NS_NewURI returns nsSimpleURI rather than
303   // nsStandardURL. To parse STUN/TURN URI's to spec
304   // http://tools.ietf.org/html/draft-nandakumar-rtcweb-stun-uri-02#section-3
305   // http://tools.ietf.org/html/draft-petithuguenin-behave-turn-uri-03#section-3
306   // we parse out the query-string, and use ParseAuthority() on the rest
307   RefPtr<nsIURI> url;
308   nsresult rv = NS_NewURI(getter_AddRefs(url), aIceUrl);
309   NS_ENSURE_SUCCESS(rv, rv);
310   bool isStun = url->SchemeIs("stun");
311   bool isStuns = url->SchemeIs("stuns");
312   bool isTurn = url->SchemeIs("turn");
313   bool isTurns = url->SchemeIs("turns");
314   if (!(isStun || isStuns || isTurn || isTurns)) {
315     return NS_ERROR_FAILURE;
316   }
317   if (isStuns) {
318     return NS_OK;  // TODO: Support STUNS (Bug 1056934)
319   }
320 
321   nsAutoCString spec;
322   rv = url->GetSpec(spec);
323   NS_ENSURE_SUCCESS(rv, rv);
324 
325   // TODO(jib@mozilla.com): Revisit once nsURI supports STUN/TURN (Bug 833509)
326   int32_t port;
327   nsAutoCString host;
328   nsAutoCString transport;
329   {
330     uint32_t hostPos;
331     int32_t hostLen;
332     nsAutoCString path;
333     rv = url->GetPathQueryRef(path);
334     NS_ENSURE_SUCCESS(rv, rv);
335 
336     // Tolerate query-string + parse 'transport=[udp|tcp]' by hand.
337     int32_t questionmark = path.FindChar('?');
338     if (questionmark >= 0) {
339       const nsCString match = "transport="_ns;
340 
341       for (int32_t i = questionmark, endPos; i >= 0; i = endPos) {
342         endPos = path.FindCharInSet("&", i + 1);
343         const nsDependentCSubstring fieldvaluepair =
344             Substring(path, i + 1, endPos);
345         if (StringBeginsWith(fieldvaluepair, match)) {
346           transport = Substring(fieldvaluepair, match.Length());
347           ToLowerCase(transport);
348         }
349       }
350       path.SetLength(questionmark);
351     }
352 
353     rv = net_GetAuthURLParser()->ParseAuthority(
354         path.get(), path.Length(), nullptr, nullptr, nullptr, nullptr, &hostPos,
355         &hostLen, &port);
356     NS_ENSURE_SUCCESS(rv, rv);
357     if (!hostLen) {
358       return NS_ERROR_FAILURE;
359     }
360     if (hostPos > 1) /* The username was removed */
361       return NS_ERROR_FAILURE;
362     path.Mid(host, hostPos, hostLen);
363     // Strip off brackets around IPv6 literals
364     host.Trim("[]");
365   }
366   if (port == -1) port = (isStuns || isTurns) ? 5349 : 3478;
367 
368   // First check the known good ports for webrtc
369   bool goodPort = false;
370   for (int i = 0; !goodPort && gGoodWebrtcPortList[i]; i++) {
371     if (port == gGoodWebrtcPortList[i]) {
372       goodPort = true;
373     }
374   }
375 
376   // if not in the list of known good ports for webrtc, check
377   // the generic block list using NS_CheckPortSafety.
378   if (!goodPort) {
379     rv = NS_CheckPortSafety(port, nullptr);
380     NS_ENSURE_SUCCESS(rv, rv);
381   }
382 
383   if (isStuns || isTurns) {
384     // Should we barf if transport is set to udp or something?
385     transport = kNrIceTransportTls;
386   }
387 
388   if (transport.IsEmpty()) {
389     transport = kNrIceTransportUdp;
390   }
391 
392   if (isTurn || isTurns) {
393     std::string pwd(
394         NS_ConvertUTF16toUTF8(aIceServer.mCredential.Value()).get());
395     std::string username(
396         NS_ConvertUTF16toUTF8(aIceServer.mUsername.Value()).get());
397 
398     std::vector<unsigned char> password(pwd.begin(), pwd.end());
399 
400     UniquePtr<NrIceTurnServer> server(NrIceTurnServer::Create(
401         host.get(), port, username, password, transport.get()));
402     if (!server) {
403       return NS_ERROR_FAILURE;
404     }
405     if (server->HasFqdn()) {
406       // Add an IPv4 entry, then an IPv6 entry
407       aTurnServersOut->push_back(*server);
408       server->SetUseIPv6IfFqdn();
409     }
410     aTurnServersOut->emplace_back(std::move(*server));
411   } else {
412     UniquePtr<NrIceStunServer> server(
413         NrIceStunServer::Create(host.get(), port, transport.get()));
414     if (!server) {
415       return NS_ERROR_FAILURE;
416     }
417     if (server->HasFqdn()) {
418       // Add an IPv4 entry, then an IPv6 entry
419       aStunServersOut->push_back(*server);
420       server->SetUseIPv6IfFqdn();
421     }
422     aStunServersOut->emplace_back(std::move(*server));
423   }
424   return NS_OK;
425 }
426 
427 /* static */
ConvertIceServers(const nsTArray<dom::RTCIceServer> & aIceServers,std::vector<NrIceStunServer> * aStunServers,std::vector<NrIceTurnServer> * aTurnServers)428 nsresult MediaTransportHandler::ConvertIceServers(
429     const nsTArray<dom::RTCIceServer>& aIceServers,
430     std::vector<NrIceStunServer>* aStunServers,
431     std::vector<NrIceTurnServer>* aTurnServers) {
432   for (const auto& iceServer : aIceServers) {
433     NS_ENSURE_STATE(iceServer.mUrls.WasPassed());
434     NS_ENSURE_STATE(iceServer.mUrls.Value().IsStringSequence());
435     for (const auto& iceUrl : iceServer.mUrls.Value().GetAsStringSequence()) {
436       nsresult rv =
437           addNrIceServer(iceUrl, iceServer, aStunServers, aTurnServers);
438       if (NS_FAILED(rv)) {
439         CSFLogError(LOGTAG, "%s: invalid STUN/TURN server: %s", __FUNCTION__,
440                     NS_ConvertUTF16toUTF8(iceUrl).get());
441         return rv;
442       }
443     }
444   }
445 
446   return NS_OK;
447 }
448 
GetGlobalConfig()449 static NrIceCtx::GlobalConfig GetGlobalConfig() {
450   NrIceCtx::GlobalConfig config;
451   config.mAllowLinkLocal =
452       Preferences::GetBool("media.peerconnection.ice.link_local", false);
453   config.mAllowLoopback =
454       Preferences::GetBool("media.peerconnection.ice.loopback", false);
455   config.mTcpEnabled =
456       Preferences::GetBool("media.peerconnection.ice.tcp", false);
457   config.mStunClientMaxTransmits = Preferences::GetInt(
458       "media.peerconnection.ice.stun_client_maximum_transmits",
459       config.mStunClientMaxTransmits);
460   config.mTrickleIceGracePeriod =
461       Preferences::GetInt("media.peerconnection.ice.trickle_grace_period",
462                           config.mTrickleIceGracePeriod);
463   config.mIceTcpSoSockCount = Preferences::GetInt(
464       "media.peerconnection.ice.tcp_so_sock_count", config.mIceTcpSoSockCount);
465   config.mIceTcpListenBacklog =
466       Preferences::GetInt("media.peerconnection.ice.tcp_listen_backlog",
467                           config.mIceTcpListenBacklog);
468   (void)Preferences::GetCString("media.peerconnection.ice.force_interface",
469                                 config.mForceNetInterface);
470   return config;
471 }
472 
GetNatConfig()473 static Maybe<NrIceCtx::NatSimulatorConfig> GetNatConfig() {
474   bool block_tcp = Preferences::GetBool(
475       "media.peerconnection.nat_simulator.block_tcp", false);
476   bool block_udp = Preferences::GetBool(
477       "media.peerconnection.nat_simulator.block_udp", false);
478   int error_code_for_drop = Preferences::GetInt(
479       "media.peerconnection.nat_simulator.error_code_for_drop", 0);
480   nsAutoCString mapping_type;
481   (void)Preferences::GetCString(
482       "media.peerconnection.nat_simulator.mapping_type", mapping_type);
483   nsAutoCString filtering_type;
484   (void)Preferences::GetCString(
485       "media.peerconnection.nat_simulator.filtering_type", filtering_type);
486   nsAutoCString redirect_address;
487   (void)Preferences::GetCString(
488       "media.peerconnection.nat_simulator.redirect_address", redirect_address);
489   nsAutoCString redirect_targets;
490   (void)Preferences::GetCString(
491       "media.peerconnection.nat_simulator.redirect_targets", redirect_targets);
492 
493   if (block_udp || block_tcp || !mapping_type.IsEmpty() ||
494       !filtering_type.IsEmpty() || !redirect_address.IsEmpty()) {
495     CSFLogDebug(LOGTAG, "NAT filtering type: %s", filtering_type.get());
496     CSFLogDebug(LOGTAG, "NAT mapping type: %s", mapping_type.get());
497     NrIceCtx::NatSimulatorConfig natConfig;
498     natConfig.mBlockUdp = block_udp;
499     natConfig.mBlockTcp = block_tcp;
500     natConfig.mErrorCodeForDrop = error_code_for_drop;
501     natConfig.mFilteringType = filtering_type;
502     natConfig.mMappingType = mapping_type;
503     if (redirect_address.Length()) {
504       CSFLogDebug(LOGTAG, "Redirect address: %s", redirect_address.get());
505       CSFLogDebug(LOGTAG, "Redirect targets: %s", redirect_targets.get());
506       natConfig.mRedirectAddress = redirect_address;
507       std::stringstream str(redirect_targets.Data());
508       std::string target;
509       while (getline(str, target, ',')) {
510         CSFLogDebug(LOGTAG, "Adding target: %s", target.c_str());
511         natConfig.mRedirectTargets.AppendElement(target);
512       }
513     }
514     return Some(natConfig);
515   }
516   return Nothing();
517 }
518 
CreateIceCtx(const std::string & aName,const nsTArray<dom::RTCIceServer> & aIceServers,dom::RTCIceTransportPolicy aIcePolicy)519 nsresult MediaTransportHandlerSTS::CreateIceCtx(
520     const std::string& aName, const nsTArray<dom::RTCIceServer>& aIceServers,
521     dom::RTCIceTransportPolicy aIcePolicy) {
522   // We rely on getting an error when this happens, so do it up front.
523   std::vector<NrIceStunServer> stunServers;
524   std::vector<NrIceTurnServer> turnServers;
525   nsresult rv = ConvertIceServers(aIceServers, &stunServers, &turnServers);
526   if (NS_FAILED(rv)) {
527     return rv;
528   }
529 
530   mInitPromise = InvokeAsync(
531       GetMainThreadSerialEventTarget(), __func__,
532       [=, self = RefPtr<MediaTransportHandlerSTS>(this)]() {
533         CSFLogDebug(LOGTAG, "%s starting", __func__);
534         if (!NSS_IsInitialized()) {
535           if (NSS_NoDB_Init(nullptr) != SECSuccess) {
536             MOZ_CRASH();
537             return InitPromise::CreateAndReject("NSS_NoDB_Init failed",
538                                                 __func__);
539           }
540 
541           if (NS_FAILED(mozilla::psm::InitializeCipherSuite())) {
542             MOZ_CRASH();
543             return InitPromise::CreateAndReject("InitializeCipherSuite failed",
544                                                 __func__);
545           }
546 
547           mozilla::psm::DisableMD5();
548         }
549 
550         static bool globalInitDone = false;
551         if (!globalInitDone) {
552           // Ensure the DNS service is initted for the first time on main
553           DebugOnly<RefPtr<nsIDNSService>> dnsService =
554               RefPtr<nsIDNSService>(nsDNSService::GetXPCOMSingleton());
555           MOZ_ASSERT(dnsService.value);
556           mStsThread->Dispatch(
557               WrapRunnableNM(&NrIceCtx::InitializeGlobals, GetGlobalConfig()),
558               NS_DISPATCH_NORMAL);
559           globalInitDone = true;
560         }
561 
562         // Give us a way to globally turn off TURN support
563         bool turnDisabled =
564             Preferences::GetBool("media.peerconnection.turn.disable", false);
565         // We are reading these here, because when we setup the DTLS transport
566         // we are on the wrong thread to read prefs
567         mMinDtlsVersion =
568             Preferences::GetUint("media.peerconnection.dtls.version.min");
569         mMaxDtlsVersion =
570             Preferences::GetUint("media.peerconnection.dtls.version.max");
571 
572         NrIceCtx::Config config;
573         config.mPolicy = toNrIcePolicy(aIcePolicy);
574         config.mNatSimulatorConfig = GetNatConfig();
575 
576         MOZ_RELEASE_ASSERT(STSShutdownHandler::Instance());
577         STSShutdownHandler::Instance()->Register(this);
578 
579         return InvokeAsync(
580             mStsThread, __func__,
581             [=, self = RefPtr<MediaTransportHandlerSTS>(this)]() {
582               mIceCtx = NrIceCtx::Create(aName, config);
583               if (!mIceCtx) {
584                 return InitPromise::CreateAndReject("NrIceCtx::Create failed",
585                                                     __func__);
586               }
587 
588               mIceCtx->SignalGatheringStateChange.connect(
589                   this, &MediaTransportHandlerSTS::OnGatheringStateChange);
590               mIceCtx->SignalConnectionStateChange.connect(
591                   this, &MediaTransportHandlerSTS::OnConnectionStateChange);
592 
593               nsresult rv;
594 
595               if (NS_FAILED(rv = mIceCtx->SetStunServers(stunServers))) {
596                 CSFLogError(LOGTAG, "%s: Failed to set stun servers",
597                             __FUNCTION__);
598                 return InitPromise::CreateAndReject(
599                     "Failed to set stun servers", __func__);
600               }
601               if (!turnDisabled) {
602                 if (NS_FAILED(rv = mIceCtx->SetTurnServers(turnServers))) {
603                   CSFLogError(LOGTAG, "%s: Failed to set turn servers",
604                               __FUNCTION__);
605                   return InitPromise::CreateAndReject(
606                       "Failed to set turn servers", __func__);
607                 }
608               } else if (!turnServers.empty()) {
609                 CSFLogError(LOGTAG, "%s: Setting turn servers disabled",
610                             __FUNCTION__);
611               }
612 
613               mDNSResolver = new NrIceResolver;
614               if (NS_FAILED(rv = mDNSResolver->Init())) {
615                 CSFLogError(LOGTAG, "%s: Failed to initialize dns resolver",
616                             __FUNCTION__);
617                 return InitPromise::CreateAndReject(
618                     "Failed to initialize dns resolver", __func__);
619               }
620               if (NS_FAILED(rv = mIceCtx->SetResolver(
621                                 mDNSResolver->AllocateResolver()))) {
622                 CSFLogError(LOGTAG, "%s: Failed to get dns resolver",
623                             __FUNCTION__);
624                 return InitPromise::CreateAndReject(
625                     "Failed to get dns resolver", __func__);
626               }
627 
628               CSFLogDebug(LOGTAG, "%s done", __func__);
629               return InitPromise::CreateAndResolve(true, __func__);
630             });
631       });
632   return NS_OK;
633 }
634 
Shutdown()635 void MediaTransportHandlerSTS::Shutdown() {
636   CSFLogDebug(LOGTAG, "%s", __func__);
637   MOZ_ASSERT(NS_IsMainThread());
638   mStsThread->Dispatch(NewNonOwningRunnableMethod(
639       __func__, this, &MediaTransportHandlerSTS::Shutdown_s));
640 }
641 
Shutdown_s()642 void MediaTransportHandlerSTS::Shutdown_s() {
643   CSFLogDebug(LOGTAG, "%s", __func__);
644   disconnect_all();
645   // Clear the transports before destroying the ice ctx so that
646   // the close_notify alerts have a chance to be sent as the
647   // TransportFlow destructors execute.
648   mTransports.clear();
649   if (mIceCtx) {
650     NrIceStats stats = mIceCtx->Destroy();
651     CSFLogDebug(LOGTAG,
652                 "Ice Telemetry: stun (retransmits: %d)"
653                 "   turn (401s: %d   403s: %d   438s: %d)",
654                 stats.stun_retransmits, stats.turn_401s, stats.turn_403s,
655                 stats.turn_438s);
656   }
657   mIceCtx = nullptr;
658   mDNSResolver = nullptr;
659 }
660 
Destroy()661 void MediaTransportHandlerSTS::Destroy() {
662   CSFLogDebug(LOGTAG, "%s %p", __func__, this);
663   // Our "destruction tour" starts on main, because we need to deregister.
664   if (!NS_IsMainThread()) {
665     GetMainThreadEventTarget()->Dispatch(NewNonOwningRunnableMethod(
666         __func__, this, &MediaTransportHandlerSTS::Destroy));
667     return;
668   }
669 
670   MOZ_ASSERT(NS_IsMainThread());
671   if (STSShutdownHandler::Instance()) {
672     STSShutdownHandler::Instance()->Deregister(this);
673     Shutdown();
674   }
675 
676   // mIceCtx still has a reference to us via sigslot! We must dispach to STS,
677   // and clean up there. However, by the time _that_ happens, we may have
678   // dispatched a signal callback to mCallbackThread, so we have to dispatch
679   // the final destruction to mCallbackThread.
680   nsresult rv = mStsThread->Dispatch(NewNonOwningRunnableMethod(
681       __func__, this, &MediaTransportHandlerSTS::Destroy_s));
682   if (NS_WARN_IF(NS_FAILED(rv))) {
683     CSFLogError(LOGTAG,
684                 "Unable to dispatch to STS: why has the XPCOM shutdown handler "
685                 "not been invoked?");
686     delete this;
687   }
688 }
689 
Destroy_s()690 void MediaTransportHandlerSTS::Destroy_s() {
691   if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
692     nsresult rv = mCallbackThread->Dispatch(NewNonOwningRunnableMethod(
693         __func__, this, &MediaTransportHandlerSTS::DestroyFinal));
694     if (NS_SUCCEEDED(rv)) {
695       return;
696     }
697   }
698 
699   DestroyFinal();
700 }
701 
DestroyFinal()702 void MediaTransportHandlerSTS::DestroyFinal() { delete this; }
703 
SetProxyConfig(NrSocketProxyConfig && aProxyConfig)704 void MediaTransportHandlerSTS::SetProxyConfig(
705     NrSocketProxyConfig&& aProxyConfig) {
706   mInitPromise->Then(
707       mStsThread, __func__,
708       [this, self = RefPtr<MediaTransportHandlerSTS>(this),
709        aProxyConfig = std::move(aProxyConfig)]() mutable {
710         if (!mIceCtx) {
711           return;  // Probably due to XPCOM shutdown
712         }
713 
714         mIceCtx->SetProxyConfig(std::move(aProxyConfig));
715       },
716       [](const std::string& aError) {});
717 }
718 
EnsureProvisionalTransport(const std::string & aTransportId,const std::string & aUfrag,const std::string & aPwd,size_t aComponentCount)719 void MediaTransportHandlerSTS::EnsureProvisionalTransport(
720     const std::string& aTransportId, const std::string& aUfrag,
721     const std::string& aPwd, size_t aComponentCount) {
722   mInitPromise->Then(
723       mStsThread, __func__,
724       [=, self = RefPtr<MediaTransportHandlerSTS>(this)]() {
725         if (!mIceCtx) {
726           return;  // Probably due to XPCOM shutdown
727         }
728 
729         RefPtr<NrIceMediaStream> stream(mIceCtx->GetStream(aTransportId));
730         if (!stream) {
731           CSFLogDebug(LOGTAG, "%s: Creating ICE media stream=%s components=%u",
732                       mIceCtx->name().c_str(), aTransportId.c_str(),
733                       static_cast<unsigned>(aComponentCount));
734 
735           std::ostringstream os;
736           os << mIceCtx->name() << " transport-id=" << aTransportId;
737           stream =
738               mIceCtx->CreateStream(aTransportId, os.str(), aComponentCount);
739 
740           if (!stream) {
741             CSFLogError(LOGTAG, "Failed to create ICE stream.");
742             return;
743           }
744 
745           stream->SignalCandidate.connect(
746               this, &MediaTransportHandlerSTS::OnCandidateFound);
747         }
748 
749         // Begins an ICE restart if this stream has a different ufrag/pwd
750         stream->SetIceCredentials(aUfrag, aPwd);
751 
752         // Make sure there's an entry in mTransports
753         mTransports[aTransportId];
754       },
755       [](const std::string& aError) {});
756 }
757 
ActivateTransport(const std::string & aTransportId,const std::string & aLocalUfrag,const std::string & aLocalPwd,size_t aComponentCount,const std::string & aUfrag,const std::string & aPassword,const nsTArray<uint8_t> & aKeyDer,const nsTArray<uint8_t> & aCertDer,SSLKEAType aAuthType,bool aDtlsClient,const DtlsDigestList & aDigests,bool aPrivacyRequested)758 void MediaTransportHandlerSTS::ActivateTransport(
759     const std::string& aTransportId, const std::string& aLocalUfrag,
760     const std::string& aLocalPwd, size_t aComponentCount,
761     const std::string& aUfrag, const std::string& aPassword,
762     const nsTArray<uint8_t>& aKeyDer, const nsTArray<uint8_t>& aCertDer,
763     SSLKEAType aAuthType, bool aDtlsClient, const DtlsDigestList& aDigests,
764     bool aPrivacyRequested) {
765   mInitPromise->Then(
766       mStsThread, __func__,
767       [=, keyDer = aKeyDer.Clone(), certDer = aCertDer.Clone(),
768        self = RefPtr<MediaTransportHandlerSTS>(this)]() {
769         if (!mIceCtx) {
770           return;  // Probably due to XPCOM shutdown
771         }
772 
773         MOZ_ASSERT(aComponentCount);
774         RefPtr<DtlsIdentity> dtlsIdentity(
775             DtlsIdentity::Deserialize(keyDer, certDer, aAuthType));
776         if (!dtlsIdentity) {
777           MOZ_ASSERT(false);
778           return;
779         }
780 
781         RefPtr<NrIceMediaStream> stream(mIceCtx->GetStream(aTransportId));
782         if (!stream) {
783           MOZ_ASSERT(false);
784           return;
785         }
786 
787         CSFLogDebug(LOGTAG, "%s: Activating ICE media stream=%s components=%u",
788                     mIceCtx->name().c_str(), aTransportId.c_str(),
789                     static_cast<unsigned>(aComponentCount));
790 
791         std::vector<std::string> attrs;
792         attrs.reserve(2 /* ufrag + pwd */);
793         attrs.push_back("ice-ufrag:" + aUfrag);
794         attrs.push_back("ice-pwd:" + aPassword);
795 
796         // If we started an ICE restart in EnsureProvisionalTransport, this is
797         // where we decide whether to commit or rollback.
798         nsresult rv = stream->ConnectToPeer(aLocalUfrag, aLocalPwd, attrs);
799         if (NS_FAILED(rv)) {
800           CSFLogError(LOGTAG, "Couldn't parse ICE attributes, rv=%u",
801                       static_cast<unsigned>(rv));
802           MOZ_ASSERT(false);
803           return;
804         }
805 
806         Transport transport = mTransports[aTransportId];
807         if (!transport.mFlow) {
808           transport.mFlow =
809               CreateTransportFlow(aTransportId, false, dtlsIdentity,
810                                   aDtlsClient, aDigests, aPrivacyRequested);
811           if (!transport.mFlow) {
812             return;
813           }
814           TransportLayer* dtls =
815               transport.mFlow->GetLayer(TransportLayerDtls::ID());
816           dtls->SignalStateChange.connect(
817               this, &MediaTransportHandlerSTS::OnStateChange);
818           if (aComponentCount < 2) {
819             dtls->SignalStateChange.connect(
820                 this, &MediaTransportHandlerSTS::OnRtcpStateChange);
821           }
822         }
823 
824         if (aComponentCount == 2) {
825           if (!transport.mRtcpFlow) {
826             transport.mRtcpFlow =
827                 CreateTransportFlow(aTransportId, true, dtlsIdentity,
828                                     aDtlsClient, aDigests, aPrivacyRequested);
829             if (!transport.mRtcpFlow) {
830               return;
831             }
832             TransportLayer* dtls =
833                 transport.mRtcpFlow->GetLayer(TransportLayerDtls::ID());
834             dtls->SignalStateChange.connect(
835                 this, &MediaTransportHandlerSTS::OnRtcpStateChange);
836           }
837         } else {
838           transport.mRtcpFlow = nullptr;
839           // components are 1-indexed
840           stream->DisableComponent(2);
841         }
842 
843         mTransports[aTransportId] = transport;
844       },
845       [](const std::string& aError) {});
846 }
847 
SetTargetForDefaultLocalAddressLookup(const std::string & aTargetIp,uint16_t aTargetPort)848 void MediaTransportHandlerSTS::SetTargetForDefaultLocalAddressLookup(
849     const std::string& aTargetIp, uint16_t aTargetPort) {
850   mInitPromise->Then(
851       mStsThread, __func__,
852       [=, self = RefPtr<MediaTransportHandlerSTS>(this)]() {
853         if (!mIceCtx) {
854           return;  // Probably due to XPCOM shutdown
855         }
856 
857         mIceCtx->SetTargetForDefaultLocalAddressLookup(aTargetIp, aTargetPort);
858       },
859       [](const std::string& aError) {});
860 }
861 
StartIceGathering(bool aDefaultRouteOnly,bool aObfuscateHostAddresses,const nsTArray<NrIceStunAddr> & aStunAddrs)862 void MediaTransportHandlerSTS::StartIceGathering(
863     bool aDefaultRouteOnly, bool aObfuscateHostAddresses,
864     const nsTArray<NrIceStunAddr>& aStunAddrs) {
865   mInitPromise->Then(
866       mStsThread, __func__,
867       [=, stunAddrs = aStunAddrs.Clone(),
868        self = RefPtr<MediaTransportHandlerSTS>(this)]() {
869         if (!mIceCtx) {
870           return;  // Probably due to XPCOM shutdown
871         }
872 
873         mObfuscateHostAddresses = aObfuscateHostAddresses;
874 
875         // Belt and suspenders - in e10s mode, the call below to SetStunAddrs
876         // needs to have the proper flags set on ice ctx.  For non-e10s,
877         // setting those flags happens in StartGathering.  We could probably
878         // just set them here, and only do it here.
879         mIceCtx->SetCtxFlags(aDefaultRouteOnly);
880 
881         if (stunAddrs.Length()) {
882           mIceCtx->SetStunAddrs(stunAddrs);
883         }
884 
885         // Start gathering, but only if there are streams
886         if (!mIceCtx->GetStreams().empty()) {
887           mIceCtx->StartGathering(aDefaultRouteOnly, aObfuscateHostAddresses);
888         }
889       },
890       [](const std::string& aError) {});
891 }
892 
StartIceChecks(bool aIsControlling,const std::vector<std::string> & aIceOptions)893 void MediaTransportHandlerSTS::StartIceChecks(
894     bool aIsControlling, const std::vector<std::string>& aIceOptions) {
895   mInitPromise->Then(
896       mStsThread, __func__,
897       [=, self = RefPtr<MediaTransportHandlerSTS>(this)]() {
898         if (!mIceCtx) {
899           return;  // Probably due to XPCOM shutdown
900         }
901 
902         nsresult rv = mIceCtx->ParseGlobalAttributes(aIceOptions);
903         if (NS_FAILED(rv)) {
904           CSFLogError(LOGTAG, "%s: couldn't parse global parameters",
905                       __FUNCTION__);
906           return;
907         }
908 
909         rv = mIceCtx->SetControlling(aIsControlling ? NrIceCtx::ICE_CONTROLLING
910                                                     : NrIceCtx::ICE_CONTROLLED);
911         if (NS_FAILED(rv)) {
912           CSFLogError(LOGTAG, "%s: couldn't set controlling to %d",
913                       __FUNCTION__, aIsControlling);
914           return;
915         }
916 
917         rv = mIceCtx->StartChecks();
918         if (NS_FAILED(rv)) {
919           CSFLogError(LOGTAG, "%s: couldn't start checks", __FUNCTION__);
920           return;
921         }
922       },
923       [](const std::string& aError) {});
924 }
925 
TokenizeCandidate(const std::string & aCandidate,std::vector<std::string> & aTokens)926 void TokenizeCandidate(const std::string& aCandidate,
927                        std::vector<std::string>& aTokens) {
928   aTokens.clear();
929 
930   std::istringstream iss(aCandidate);
931   std::string token;
932   while (std::getline(iss, token, ' ')) {
933     aTokens.push_back(token);
934   }
935 }
936 
AddIceCandidate(const std::string & aTransportId,const std::string & aCandidate,const std::string & aUfrag,const std::string & aObfuscatedAddress)937 void MediaTransportHandlerSTS::AddIceCandidate(
938     const std::string& aTransportId, const std::string& aCandidate,
939     const std::string& aUfrag, const std::string& aObfuscatedAddress) {
940   mInitPromise->Then(
941       mStsThread, __func__,
942       [=, self = RefPtr<MediaTransportHandlerSTS>(this)]() {
943         if (!mIceCtx) {
944           return;  // Probably due to XPCOM shutdown
945         }
946 
947         std::vector<std::string> tokens;
948         TokenizeCandidate(aCandidate, tokens);
949 
950         RefPtr<NrIceMediaStream> stream(mIceCtx->GetStream(aTransportId));
951         if (!stream) {
952           CSFLogError(LOGTAG,
953                       "No ICE stream for candidate with transport id %s: %s",
954                       aTransportId.c_str(), aCandidate.c_str());
955           return;
956         }
957 
958         nsresult rv = stream->ParseTrickleCandidate(aCandidate, aUfrag,
959                                                     aObfuscatedAddress);
960         if (NS_SUCCEEDED(rv)) {
961           // If the address is not obfuscated, we want to track it as
962           // explicitly signaled so that we know it is fine to reveal
963           // the address later on.
964           if (mObfuscateHostAddresses && tokens.size() > 4 &&
965               aObfuscatedAddress.empty()) {
966             mSignaledAddresses.insert(tokens[4]);
967           }
968         } else {
969           CSFLogError(LOGTAG,
970                       "Couldn't process ICE candidate with transport id %s: "
971                       "%s",
972                       aTransportId.c_str(), aCandidate.c_str());
973         }
974       },
975       [](const std::string& aError) {});
976 }
977 
UpdateNetworkState(bool aOnline)978 void MediaTransportHandlerSTS::UpdateNetworkState(bool aOnline) {
979   mInitPromise->Then(
980       mStsThread, __func__,
981       [=, self = RefPtr<MediaTransportHandlerSTS>(this)]() {
982         if (!mIceCtx) {
983           return;  // Probably due to XPCOM shutdown
984         }
985 
986         mIceCtx->UpdateNetworkState(aOnline);
987       },
988       [](const std::string& aError) {});
989 }
990 
RemoveTransportsExcept(const std::set<std::string> & aTransportIds)991 void MediaTransportHandlerSTS::RemoveTransportsExcept(
992     const std::set<std::string>& aTransportIds) {
993   mInitPromise->Then(
994       mStsThread, __func__,
995       [=, self = RefPtr<MediaTransportHandlerSTS>(this)]() {
996         if (!mIceCtx) {
997           return;  // Probably due to XPCOM shutdown
998         }
999 
1000         for (auto it = mTransports.begin(); it != mTransports.end();) {
1001           const std::string transportId(it->first);
1002           if (!aTransportIds.count(transportId)) {
1003             if (it->second.mFlow) {
1004               OnStateChange(transportId, TransportLayer::TS_NONE);
1005               OnRtcpStateChange(transportId, TransportLayer::TS_NONE);
1006             }
1007             // Erase the transport before destroying the ice stream so that
1008             // the close_notify alerts have a chance to be sent as the
1009             // TransportFlow destructors execute.
1010             it = mTransports.erase(it);
1011             // We're already on the STS thread, but the TransportFlow
1012             // destructor executed when mTransports.erase(it) is called
1013             // above dispatches the call to DestroyFinal to the STS thread. If
1014             // we don't also dispatch the call to destroy the NrIceMediaStream
1015             // to the STS thread, it will tear down the NrIceMediaStream
1016             // before the TransportFlow is destroyed.  Without a valid
1017             // NrIceMediaStream the close_notify alert cannot be sent.
1018             mStsThread->Dispatch(NS_NewRunnableFunction(
1019                 __func__, [iceCtx = RefPtr<NrIceCtx>(mIceCtx), transportId] {
1020                   iceCtx->DestroyStream(transportId);
1021                 }));
1022           } else {
1023             MOZ_ASSERT(it->second.mFlow);
1024             ++it;
1025           }
1026         }
1027       },
1028       [](const std::string& aError) {});
1029 }
1030 
SendPacket(const std::string & aTransportId,MediaPacket && aPacket)1031 void MediaTransportHandlerSTS::SendPacket(const std::string& aTransportId,
1032                                           MediaPacket&& aPacket) {
1033   mInitPromise->Then(
1034       mStsThread, __func__,
1035       [this, self = RefPtr<MediaTransportHandlerSTS>(this), aTransportId,
1036        aPacket = std::move(aPacket)]() mutable {
1037         if (!mIceCtx) {
1038           return;  // Probably due to XPCOM shutdown
1039         }
1040 
1041         MOZ_ASSERT(aPacket.type() != MediaPacket::UNCLASSIFIED);
1042         RefPtr<TransportFlow> flow =
1043             GetTransportFlow(aTransportId, aPacket.type() == MediaPacket::RTCP);
1044 
1045         if (!flow) {
1046           CSFLogError(LOGTAG,
1047                       "%s: No such transport flow (%s) for outgoing packet",
1048                       mIceCtx->name().c_str(), aTransportId.c_str());
1049           return;
1050         }
1051 
1052         TransportLayer* layer = nullptr;
1053         switch (aPacket.type()) {
1054           case MediaPacket::SCTP:
1055             layer = flow->GetLayer(TransportLayerDtls::ID());
1056             break;
1057           case MediaPacket::RTP:
1058           case MediaPacket::RTCP:
1059             layer = flow->GetLayer(TransportLayerSrtp::ID());
1060             break;
1061           default:
1062             // Maybe it would be useful to allow the injection of other packet
1063             // types for testing?
1064             MOZ_ASSERT(false);
1065             return;
1066         }
1067 
1068         MOZ_ASSERT(layer);
1069 
1070         if (layer->SendPacket(aPacket) < 0) {
1071           CSFLogError(LOGTAG, "%s: Transport flow (%s) failed to send packet",
1072                       mIceCtx->name().c_str(), aTransportId.c_str());
1073         }
1074       },
1075       [](const std::string& aError) {});
1076 }
1077 
GetState(const std::string & aTransportId,bool aRtcp) const1078 TransportLayer::State MediaTransportHandler::GetState(
1079     const std::string& aTransportId, bool aRtcp) const {
1080   // TODO Bug 1520692: we should allow Datachannel to connect without
1081   // DTLS SRTP keys
1082   if (mCallbackThread) {
1083     MOZ_ASSERT(mCallbackThread->IsOnCurrentThread());
1084   }
1085 
1086   const std::map<std::string, TransportLayer::State>* cache = nullptr;
1087   if (aRtcp) {
1088     cache = &mRtcpStateCache;
1089   } else {
1090     cache = &mStateCache;
1091   }
1092 
1093   auto it = cache->find(aTransportId);
1094   if (it != cache->end()) {
1095     return it->second;
1096   }
1097   return TransportLayer::TS_NONE;
1098 }
1099 
OnCandidate(const std::string & aTransportId,const CandidateInfo & aCandidateInfo)1100 void MediaTransportHandler::OnCandidate(const std::string& aTransportId,
1101                                         const CandidateInfo& aCandidateInfo) {
1102   if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
1103     mCallbackThread->Dispatch(
1104         // This is being called from sigslot, which does not hold a strong ref.
1105         WrapRunnable(this, &MediaTransportHandler::OnCandidate, aTransportId,
1106                      aCandidateInfo),
1107         NS_DISPATCH_NORMAL);
1108     return;
1109   }
1110 
1111   SignalCandidate(aTransportId, aCandidateInfo);
1112 }
1113 
OnAlpnNegotiated(const std::string & aAlpn)1114 void MediaTransportHandler::OnAlpnNegotiated(const std::string& aAlpn) {
1115   if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
1116     mCallbackThread->Dispatch(
1117         // This is being called from sigslot, which does not hold a strong ref.
1118         WrapRunnable(this, &MediaTransportHandler::OnAlpnNegotiated, aAlpn),
1119         NS_DISPATCH_NORMAL);
1120     return;
1121   }
1122 
1123   const bool privacyRequested = aAlpn == "c-webrtc";
1124   SignalAlpnNegotiated(aAlpn, privacyRequested);
1125 }
1126 
OnGatheringStateChange(dom::RTCIceGatheringState aState)1127 void MediaTransportHandler::OnGatheringStateChange(
1128     dom::RTCIceGatheringState aState) {
1129   if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
1130     mCallbackThread->Dispatch(
1131         // This is being called from sigslot, which does not hold a strong ref.
1132         WrapRunnable(this, &MediaTransportHandler::OnGatheringStateChange,
1133                      aState),
1134         NS_DISPATCH_NORMAL);
1135     return;
1136   }
1137 
1138   SignalGatheringStateChange(aState);
1139 }
1140 
OnConnectionStateChange(dom::RTCIceConnectionState aState)1141 void MediaTransportHandler::OnConnectionStateChange(
1142     dom::RTCIceConnectionState aState) {
1143   if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
1144     mCallbackThread->Dispatch(
1145         // This is being called from sigslot, which does not hold a strong ref.
1146         WrapRunnable(this, &MediaTransportHandler::OnConnectionStateChange,
1147                      aState),
1148         NS_DISPATCH_NORMAL);
1149     return;
1150   }
1151 
1152   SignalConnectionStateChange(aState);
1153 }
1154 
OnPacketReceived(const std::string & aTransportId,const MediaPacket & aPacket)1155 void MediaTransportHandler::OnPacketReceived(const std::string& aTransportId,
1156                                              const MediaPacket& aPacket) {
1157   if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
1158     mCallbackThread->Dispatch(
1159         // This is being called from sigslot, which does not hold a strong ref.
1160         WrapRunnable(this, &MediaTransportHandler::OnPacketReceived,
1161                      aTransportId, const_cast<MediaPacket&>(aPacket)),
1162         NS_DISPATCH_NORMAL);
1163     return;
1164   }
1165 
1166   SignalPacketReceived(aTransportId, aPacket);
1167 }
1168 
OnEncryptedSending(const std::string & aTransportId,const MediaPacket & aPacket)1169 void MediaTransportHandler::OnEncryptedSending(const std::string& aTransportId,
1170                                                const MediaPacket& aPacket) {
1171   if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
1172     mCallbackThread->Dispatch(
1173         // This is being called from sigslot, which does not hold a strong ref.
1174         WrapRunnable(this, &MediaTransportHandler::OnEncryptedSending,
1175                      aTransportId, const_cast<MediaPacket&>(aPacket)),
1176         NS_DISPATCH_NORMAL);
1177     return;
1178   }
1179 
1180   SignalEncryptedSending(aTransportId, aPacket);
1181 }
1182 
OnStateChange(const std::string & aTransportId,TransportLayer::State aState)1183 void MediaTransportHandler::OnStateChange(const std::string& aTransportId,
1184                                           TransportLayer::State aState) {
1185   if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
1186     mCallbackThread->Dispatch(
1187         // This is being called from sigslot, which does not hold a strong ref.
1188         WrapRunnable(this, &MediaTransportHandler::OnStateChange, aTransportId,
1189                      aState),
1190         NS_DISPATCH_NORMAL);
1191     return;
1192   }
1193 
1194   if (aState == TransportLayer::TS_NONE) {
1195     mStateCache.erase(aTransportId);
1196   } else {
1197     mStateCache[aTransportId] = aState;
1198   }
1199   SignalStateChange(aTransportId, aState);
1200 }
1201 
OnRtcpStateChange(const std::string & aTransportId,TransportLayer::State aState)1202 void MediaTransportHandler::OnRtcpStateChange(const std::string& aTransportId,
1203                                               TransportLayer::State aState) {
1204   if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
1205     mCallbackThread->Dispatch(
1206         // This is being called from sigslot, which does not hold a strong ref.
1207         WrapRunnable(this, &MediaTransportHandler::OnRtcpStateChange,
1208                      aTransportId, aState),
1209         NS_DISPATCH_NORMAL);
1210     return;
1211   }
1212 
1213   if (aState == TransportLayer::TS_NONE) {
1214     mRtcpStateCache.erase(aTransportId);
1215   } else {
1216     mRtcpStateCache[aTransportId] = aState;
1217   }
1218   SignalRtcpStateChange(aTransportId, aState);
1219 }
1220 
GetIceStats(const std::string & aTransportId,DOMHighResTimeStamp aNow)1221 RefPtr<dom::RTCStatsPromise> MediaTransportHandlerSTS::GetIceStats(
1222     const std::string& aTransportId, DOMHighResTimeStamp aNow) {
1223   return mInitPromise->Then(
1224       mStsThread, __func__,
1225       [=, self = RefPtr<MediaTransportHandlerSTS>(this)]() {
1226         UniquePtr<dom::RTCStatsCollection> stats(new dom::RTCStatsCollection);
1227         if (mIceCtx) {
1228           for (const auto& stream : mIceCtx->GetStreams()) {
1229             if (aTransportId.empty() || aTransportId == stream->GetId()) {
1230               GetIceStats(*stream, aNow, stats.get());
1231             }
1232           }
1233         }
1234         return dom::RTCStatsPromise::CreateAndResolve(std::move(stats),
1235                                                       __func__);
1236       });
1237 }
1238 
1239 RefPtr<MediaTransportHandler::IceLogPromise>
GetIceLog(const nsCString & aPattern)1240 MediaTransportHandlerSTS::GetIceLog(const nsCString& aPattern) {
1241   return InvokeAsync(
1242       mStsThread, __func__, [=, self = RefPtr<MediaTransportHandlerSTS>(this)] {
1243         dom::Sequence<nsString> converted;
1244         RLogConnector* logs = RLogConnector::GetInstance();
1245         std::deque<std::string> result;
1246         // Might not exist yet.
1247         if (logs) {
1248           logs->Filter(aPattern.get(), 0, &result);
1249         }
1250         /// XXX(Bug 1631386) Check if we should reject the promise instead of
1251         /// crashing in an OOM situation.
1252         if (!converted.SetCapacity(result.size(), fallible)) {
1253           mozalloc_handle_oom(sizeof(nsString) * result.size());
1254         }
1255         for (auto& line : result) {
1256           // Cannot fail, SetCapacity was called before.
1257           (void)converted.AppendElement(NS_ConvertUTF8toUTF16(line.c_str()),
1258                                         fallible);
1259         }
1260         return IceLogPromise::CreateAndResolve(std::move(converted), __func__);
1261       });
1262 }
1263 
ClearIceLog()1264 void MediaTransportHandlerSTS::ClearIceLog() {
1265   if (!mStsThread->IsOnCurrentThread()) {
1266     mStsThread->Dispatch(WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
1267                                       &MediaTransportHandlerSTS::ClearIceLog),
1268                          NS_DISPATCH_NORMAL);
1269     return;
1270   }
1271 
1272   RLogConnector* logs = RLogConnector::GetInstance();
1273   if (logs) {
1274     logs->Clear();
1275   }
1276 }
1277 
EnterPrivateMode()1278 void MediaTransportHandlerSTS::EnterPrivateMode() {
1279   if (!mStsThread->IsOnCurrentThread()) {
1280     mStsThread->Dispatch(
1281         WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
1282                      &MediaTransportHandlerSTS::EnterPrivateMode),
1283         NS_DISPATCH_NORMAL);
1284     return;
1285   }
1286 
1287   RLogConnector::GetInstance()->EnterPrivateMode();
1288 }
1289 
ExitPrivateMode()1290 void MediaTransportHandlerSTS::ExitPrivateMode() {
1291   if (!mStsThread->IsOnCurrentThread()) {
1292     mStsThread->Dispatch(
1293         WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
1294                      &MediaTransportHandlerSTS::ExitPrivateMode),
1295         NS_DISPATCH_NORMAL);
1296     return;
1297   }
1298 
1299   auto* log = RLogConnector::GetInstance();
1300   MOZ_ASSERT(log);
1301   if (log) {
1302     log->ExitPrivateMode();
1303   }
1304 }
1305 
ToRTCIceCandidateStats(const std::vector<NrIceCandidate> & candidates,dom::RTCStatsType candidateType,const nsString & transportId,DOMHighResTimeStamp now,dom::RTCStatsCollection * stats,bool obfuscateHostAddresses,const std::set<std::string> & signaledAddresses)1306 static void ToRTCIceCandidateStats(
1307     const std::vector<NrIceCandidate>& candidates,
1308     dom::RTCStatsType candidateType, const nsString& transportId,
1309     DOMHighResTimeStamp now, dom::RTCStatsCollection* stats,
1310     bool obfuscateHostAddresses,
1311     const std::set<std::string>& signaledAddresses) {
1312   MOZ_ASSERT(stats);
1313   for (const auto& candidate : candidates) {
1314     dom::RTCIceCandidateStats cand;
1315     cand.mType.Construct(candidateType);
1316     NS_ConvertASCIItoUTF16 codeword(candidate.codeword.c_str());
1317     cand.mTransportId.Construct(transportId);
1318     cand.mId.Construct(codeword);
1319     cand.mTimestamp.Construct(now);
1320     cand.mCandidateType.Construct(dom::RTCIceCandidateType(candidate.type));
1321     cand.mPriority.Construct(candidate.priority);
1322     // https://tools.ietf.org/html/draft-ietf-rtcweb-mdns-ice-candidates-03#section-3.3.1
1323     // This obfuscates the address with the mDNS address if one exists
1324     if (!candidate.mdns_addr.empty()) {
1325       cand.mAddress.Construct(
1326           NS_ConvertASCIItoUTF16(candidate.mdns_addr.c_str()));
1327     } else if (obfuscateHostAddresses &&
1328                candidate.type == NrIceCandidate::ICE_PEER_REFLEXIVE &&
1329                signaledAddresses.find(candidate.cand_addr.host) ==
1330                    signaledAddresses.end()) {
1331       cand.mAddress.Construct(NS_ConvertASCIItoUTF16("(redacted)"));
1332     } else {
1333       cand.mAddress.Construct(
1334           NS_ConvertASCIItoUTF16(candidate.cand_addr.host.c_str()));
1335     }
1336     cand.mPort.Construct(candidate.cand_addr.port);
1337     cand.mProtocol.Construct(
1338         NS_ConvertASCIItoUTF16(candidate.cand_addr.transport.c_str()));
1339     if (candidateType == dom::RTCStatsType::Local_candidate &&
1340         dom::RTCIceCandidateType(candidate.type) ==
1341             dom::RTCIceCandidateType::Relay) {
1342       cand.mRelayProtocol.Construct(
1343           NS_ConvertASCIItoUTF16(candidate.local_addr.transport.c_str()));
1344     }
1345     cand.mProxied.Construct(NS_ConvertASCIItoUTF16(
1346         candidate.is_proxied ? "proxied" : "non-proxied"));
1347     if (!stats->mIceCandidateStats.AppendElement(cand, fallible)) {
1348       // XXX(Bug 1632090) Instead of extending the array 1-by-1 (which might
1349       // involve multiple reallocations) and potentially crashing here,
1350       // SetCapacity could be called outside the loop once.
1351       mozalloc_handle_oom(0);
1352     }
1353     if (candidate.trickled) {
1354       if (!stats->mTrickledIceCandidateStats.AppendElement(cand, fallible)) {
1355         mozalloc_handle_oom(0);
1356       }
1357     }
1358   }
1359 }
1360 
GetIceStats(const NrIceMediaStream & aStream,DOMHighResTimeStamp aNow,dom::RTCStatsCollection * aStats) const1361 void MediaTransportHandlerSTS::GetIceStats(
1362     const NrIceMediaStream& aStream, DOMHighResTimeStamp aNow,
1363     dom::RTCStatsCollection* aStats) const {
1364   MOZ_ASSERT(mStsThread->IsOnCurrentThread());
1365 
1366   NS_ConvertASCIItoUTF16 transportId(aStream.GetId().c_str());
1367 
1368   std::vector<NrIceCandidatePair> candPairs;
1369   nsresult res = aStream.GetCandidatePairs(&candPairs);
1370   if (NS_FAILED(res)) {
1371     CSFLogError(LOGTAG,
1372                 "%s: Error getting candidate pairs for transport id \"%s\"",
1373                 __FUNCTION__, aStream.GetId().c_str());
1374     return;
1375   }
1376 
1377   for (auto& candPair : candPairs) {
1378     NS_ConvertASCIItoUTF16 codeword(candPair.codeword.c_str());
1379     NS_ConvertASCIItoUTF16 localCodeword(candPair.local.codeword.c_str());
1380     NS_ConvertASCIItoUTF16 remoteCodeword(candPair.remote.codeword.c_str());
1381     // Only expose candidate-pair statistics to chrome, until we've thought
1382     // through the implications of exposing it to content.
1383 
1384     dom::RTCIceCandidatePairStats s;
1385     s.mId.Construct(codeword);
1386     s.mTransportId.Construct(transportId);
1387     s.mTimestamp.Construct(aNow);
1388     s.mType.Construct(dom::RTCStatsType::Candidate_pair);
1389     s.mLocalCandidateId.Construct(localCodeword);
1390     s.mRemoteCandidateId.Construct(remoteCodeword);
1391     s.mNominated.Construct(candPair.nominated);
1392     s.mWritable.Construct(candPair.writable);
1393     s.mReadable.Construct(candPair.readable);
1394     s.mPriority.Construct(candPair.priority);
1395     s.mSelected.Construct(candPair.selected);
1396     s.mBytesSent.Construct(candPair.bytes_sent);
1397     s.mBytesReceived.Construct(candPair.bytes_recvd);
1398     s.mLastPacketSentTimestamp.Construct(candPair.ms_since_last_send);
1399     s.mLastPacketReceivedTimestamp.Construct(candPair.ms_since_last_recv);
1400     s.mState.Construct(dom::RTCStatsIceCandidatePairState(candPair.state));
1401     s.mComponentId.Construct(candPair.component_id);
1402     if (!aStats->mIceCandidatePairStats.AppendElement(s, fallible)) {
1403       // XXX(Bug 1632090) Instead of extending the array 1-by-1 (which might
1404       // involve multiple reallocations) and potentially crashing here,
1405       // SetCapacity could be called outside the loop once.
1406       mozalloc_handle_oom(0);
1407     }
1408   }
1409 
1410   std::vector<NrIceCandidate> candidates;
1411   if (NS_SUCCEEDED(aStream.GetLocalCandidates(&candidates))) {
1412     ToRTCIceCandidateStats(candidates, dom::RTCStatsType::Local_candidate,
1413                            transportId, aNow, aStats, mObfuscateHostAddresses,
1414                            mSignaledAddresses);
1415     // add the local candidates unparsed string to a sequence
1416     for (const auto& candidate : candidates) {
1417       if (!aStats->mRawLocalCandidates.AppendElement(
1418               NS_ConvertASCIItoUTF16(candidate.label.c_str()), fallible)) {
1419         // XXX(Bug 1632090) Instead of extending the array 1-by-1 (which might
1420         // involve multiple reallocations) and potentially crashing here,
1421         // SetCapacity could be called outside the loop once.
1422         mozalloc_handle_oom(0);
1423       }
1424     }
1425   }
1426   candidates.clear();
1427 
1428   if (NS_SUCCEEDED(aStream.GetRemoteCandidates(&candidates))) {
1429     ToRTCIceCandidateStats(candidates, dom::RTCStatsType::Remote_candidate,
1430                            transportId, aNow, aStats, mObfuscateHostAddresses,
1431                            mSignaledAddresses);
1432     // add the remote candidates unparsed string to a sequence
1433     for (const auto& candidate : candidates) {
1434       if (!aStats->mRawRemoteCandidates.AppendElement(
1435               NS_ConvertASCIItoUTF16(candidate.label.c_str()), fallible)) {
1436         // XXX(Bug 1632090) Instead of extending the array 1-by-1 (which might
1437         // involve multiple reallocations) and potentially crashing here,
1438         // SetCapacity could be called outside the loop once.
1439         mozalloc_handle_oom(0);
1440       }
1441     }
1442   }
1443 }
1444 
GetTransportFlow(const std::string & aTransportId,bool aIsRtcp) const1445 RefPtr<TransportFlow> MediaTransportHandlerSTS::GetTransportFlow(
1446     const std::string& aTransportId, bool aIsRtcp) const {
1447   auto it = mTransports.find(aTransportId);
1448   if (it == mTransports.end()) {
1449     return nullptr;
1450   }
1451 
1452   if (aIsRtcp) {
1453     return it->second.mRtcpFlow ? it->second.mRtcpFlow : it->second.mFlow;
1454     ;
1455   }
1456 
1457   return it->second.mFlow;
1458 }
1459 
CreateTransportFlow(const std::string & aTransportId,bool aIsRtcp,RefPtr<DtlsIdentity> aDtlsIdentity,bool aDtlsClient,const DtlsDigestList & aDigests,bool aPrivacyRequested)1460 RefPtr<TransportFlow> MediaTransportHandlerSTS::CreateTransportFlow(
1461     const std::string& aTransportId, bool aIsRtcp,
1462     RefPtr<DtlsIdentity> aDtlsIdentity, bool aDtlsClient,
1463     const DtlsDigestList& aDigests, bool aPrivacyRequested) {
1464   nsresult rv;
1465   RefPtr<TransportFlow> flow = new TransportFlow(aTransportId);
1466 
1467   // The media streams are made on STS so we need to defer setup.
1468   auto ice = MakeUnique<TransportLayerIce>();
1469   auto dtls = MakeUnique<TransportLayerDtls>();
1470   auto srtp = MakeUnique<TransportLayerSrtp>(*dtls);
1471   dtls->SetRole(aDtlsClient ? TransportLayerDtls::CLIENT
1472                             : TransportLayerDtls::SERVER);
1473 
1474   dtls->SetIdentity(aDtlsIdentity);
1475 
1476   dtls->SetMinMaxVersion(
1477       static_cast<TransportLayerDtls::Version>(mMinDtlsVersion),
1478       static_cast<TransportLayerDtls::Version>(mMaxDtlsVersion));
1479 
1480   for (const auto& digest : aDigests) {
1481     rv = dtls->SetVerificationDigest(digest);
1482     if (NS_FAILED(rv)) {
1483       CSFLogError(LOGTAG, "Could not set fingerprint");
1484       return nullptr;
1485     }
1486   }
1487 
1488   std::vector<uint16_t> srtpCiphers =
1489       TransportLayerDtls::GetDefaultSrtpCiphers();
1490 
1491   rv = dtls->SetSrtpCiphers(srtpCiphers);
1492   if (NS_FAILED(rv)) {
1493     CSFLogError(LOGTAG, "Couldn't set SRTP ciphers");
1494     return nullptr;
1495   }
1496 
1497   // Always permits negotiation of the confidential mode.
1498   // Only allow non-confidential (which is an allowed default),
1499   // if we aren't confidential.
1500   std::set<std::string> alpn = {"c-webrtc"};
1501   std::string alpnDefault;
1502   if (!aPrivacyRequested) {
1503     alpnDefault = "webrtc";
1504     alpn.insert(alpnDefault);
1505   }
1506   rv = dtls->SetAlpn(alpn, alpnDefault);
1507   if (NS_FAILED(rv)) {
1508     CSFLogError(LOGTAG, "Couldn't set ALPN");
1509     return nullptr;
1510   }
1511 
1512   ice->SetParameters(mIceCtx->GetStream(aTransportId), aIsRtcp ? 2 : 1);
1513   NS_ENSURE_SUCCESS(ice->Init(), nullptr);
1514   NS_ENSURE_SUCCESS(dtls->Init(), nullptr);
1515   NS_ENSURE_SUCCESS(srtp->Init(), nullptr);
1516   dtls->Chain(ice.get());
1517   srtp->Chain(ice.get());
1518 
1519   dtls->SignalPacketReceived.connect(this,
1520                                      &MediaTransportHandlerSTS::PacketReceived);
1521   srtp->SignalPacketReceived.connect(this,
1522                                      &MediaTransportHandlerSTS::PacketReceived);
1523   ice->SignalPacketSending.connect(
1524       this, &MediaTransportHandlerSTS::EncryptedPacketSending);
1525   flow->PushLayer(ice.release());
1526   flow->PushLayer(dtls.release());
1527   flow->PushLayer(srtp.release());
1528   return flow;
1529 }
1530 
toDomIceGatheringState(NrIceCtx::GatheringState aState)1531 static mozilla::dom::RTCIceGatheringState toDomIceGatheringState(
1532     NrIceCtx::GatheringState aState) {
1533   switch (aState) {
1534     case NrIceCtx::ICE_CTX_GATHER_INIT:
1535       return dom::RTCIceGatheringState::New;
1536     case NrIceCtx::ICE_CTX_GATHER_STARTED:
1537       return dom::RTCIceGatheringState::Gathering;
1538     case NrIceCtx::ICE_CTX_GATHER_COMPLETE:
1539       return dom::RTCIceGatheringState::Complete;
1540   }
1541   MOZ_CRASH();
1542 }
1543 
OnGatheringStateChange(NrIceCtx * aIceCtx,NrIceCtx::GatheringState aState)1544 void MediaTransportHandlerSTS::OnGatheringStateChange(
1545     NrIceCtx* aIceCtx, NrIceCtx::GatheringState aState) {
1546   OnGatheringStateChange(toDomIceGatheringState(aState));
1547 }
1548 
toDomIceConnectionState(NrIceCtx::ConnectionState aState)1549 static mozilla::dom::RTCIceConnectionState toDomIceConnectionState(
1550     NrIceCtx::ConnectionState aState) {
1551   switch (aState) {
1552     case NrIceCtx::ICE_CTX_INIT:
1553       return dom::RTCIceConnectionState::New;
1554     case NrIceCtx::ICE_CTX_CHECKING:
1555       return dom::RTCIceConnectionState::Checking;
1556     case NrIceCtx::ICE_CTX_CONNECTED:
1557       return dom::RTCIceConnectionState::Connected;
1558     case NrIceCtx::ICE_CTX_COMPLETED:
1559       return dom::RTCIceConnectionState::Completed;
1560     case NrIceCtx::ICE_CTX_FAILED:
1561       return dom::RTCIceConnectionState::Failed;
1562     case NrIceCtx::ICE_CTX_DISCONNECTED:
1563       return dom::RTCIceConnectionState::Disconnected;
1564     case NrIceCtx::ICE_CTX_CLOSED:
1565       return dom::RTCIceConnectionState::Closed;
1566   }
1567   MOZ_CRASH();
1568 }
1569 
OnConnectionStateChange(NrIceCtx * aIceCtx,NrIceCtx::ConnectionState aState)1570 void MediaTransportHandlerSTS::OnConnectionStateChange(
1571     NrIceCtx* aIceCtx, NrIceCtx::ConnectionState aState) {
1572   OnConnectionStateChange(toDomIceConnectionState(aState));
1573 }
1574 
1575 // The stuff below here will eventually go into the MediaTransportChild class
OnCandidateFound(NrIceMediaStream * aStream,const std::string & aCandidate,const std::string & aUfrag,const std::string & aMDNSAddr,const std::string & aActualAddr)1576 void MediaTransportHandlerSTS::OnCandidateFound(
1577     NrIceMediaStream* aStream, const std::string& aCandidate,
1578     const std::string& aUfrag, const std::string& aMDNSAddr,
1579     const std::string& aActualAddr) {
1580   CandidateInfo info;
1581   info.mCandidate = aCandidate;
1582   MOZ_ASSERT(!aUfrag.empty());
1583   info.mUfrag = aUfrag;
1584   NrIceCandidate defaultRtpCandidate;
1585   NrIceCandidate defaultRtcpCandidate;
1586   nsresult rv = aStream->GetDefaultCandidate(1, &defaultRtpCandidate);
1587   if (NS_SUCCEEDED(rv)) {
1588     if (!defaultRtpCandidate.mdns_addr.empty()) {
1589       info.mDefaultHostRtp = "0.0.0.0";
1590       info.mDefaultPortRtp = 9;
1591     } else {
1592       info.mDefaultHostRtp = defaultRtpCandidate.cand_addr.host;
1593       info.mDefaultPortRtp = defaultRtpCandidate.cand_addr.port;
1594     }
1595   } else {
1596     CSFLogError(LOGTAG,
1597                 "%s: GetDefaultCandidates failed for transport id %s, "
1598                 "res=%u",
1599                 __FUNCTION__, aStream->GetId().c_str(),
1600                 static_cast<unsigned>(rv));
1601   }
1602 
1603   // Optional; component won't exist if doing rtcp-mux
1604   if (NS_SUCCEEDED(aStream->GetDefaultCandidate(2, &defaultRtcpCandidate))) {
1605     if (!defaultRtcpCandidate.mdns_addr.empty()) {
1606       info.mDefaultHostRtcp = defaultRtcpCandidate.mdns_addr;
1607     } else {
1608       info.mDefaultHostRtcp = defaultRtcpCandidate.cand_addr.host;
1609     }
1610     info.mDefaultPortRtcp = defaultRtcpCandidate.cand_addr.port;
1611   }
1612 
1613   info.mMDNSAddress = aMDNSAddr;
1614   info.mActualAddress = aActualAddr;
1615 
1616   OnCandidate(aStream->GetId(), info);
1617 }
1618 
OnStateChange(TransportLayer * aLayer,TransportLayer::State aState)1619 void MediaTransportHandlerSTS::OnStateChange(TransportLayer* aLayer,
1620                                              TransportLayer::State aState) {
1621   if (aState == TransportLayer::TS_OPEN) {
1622     MOZ_ASSERT(aLayer->id() == TransportLayerDtls::ID());
1623     TransportLayerDtls* dtlsLayer = static_cast<TransportLayerDtls*>(aLayer);
1624     OnAlpnNegotiated(dtlsLayer->GetNegotiatedAlpn());
1625   }
1626 
1627   // DTLS state indicates the readiness of the transport as a whole, because
1628   // SRTP uses the keys from the DTLS handshake.
1629   MediaTransportHandler::OnStateChange(aLayer->flow_id(), aState);
1630 }
1631 
OnRtcpStateChange(TransportLayer * aLayer,TransportLayer::State aState)1632 void MediaTransportHandlerSTS::OnRtcpStateChange(TransportLayer* aLayer,
1633                                                  TransportLayer::State aState) {
1634   MediaTransportHandler::OnRtcpStateChange(aLayer->flow_id(), aState);
1635 }
1636 
PacketReceived(TransportLayer * aLayer,MediaPacket & aPacket)1637 void MediaTransportHandlerSTS::PacketReceived(TransportLayer* aLayer,
1638                                               MediaPacket& aPacket) {
1639   OnPacketReceived(aLayer->flow_id(), aPacket);
1640 }
1641 
EncryptedPacketSending(TransportLayer * aLayer,MediaPacket & aPacket)1642 void MediaTransportHandlerSTS::EncryptedPacketSending(TransportLayer* aLayer,
1643                                                       MediaPacket& aPacket) {
1644   OnEncryptedSending(aLayer->flow_id(), aPacket);
1645 }
1646 
1647 }  // namespace mozilla
1648