tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MediaTransportHandler.cpp (60371B)


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