tor-browser

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

ice_unittest.cpp (145248B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 // Original author: ekr@rtfm.com
      8 
      9 #include <algorithm>
     10 #include <deque>
     11 #include <iostream>
     12 #include <limits>
     13 #include <map>
     14 #include <string>
     15 #include <vector>
     16 
     17 #include "logging.h"
     18 #include "mozilla/DataMutex.h"
     19 #include "mozilla/Preferences.h"
     20 #include "nsThreadUtils.h"
     21 #include "nsXPCOM.h"
     22 #include "sigslot.h"
     23 #include "ssl.h"
     24 
     25 extern "C" {
     26 // clang-format off
     27 #include "r_types.h"
     28 #include "async_wait.h"
     29 #include "async_timer.h"
     30 #include "r_data.h"
     31 #include "util.h"
     32 #include "r_time.h"
     33 // clang-format on
     34 }
     35 
     36 #include "gtest_ringbuffer_dumper.h"
     37 #include "ice_ctx.h"
     38 #include "ice_media_stream.h"
     39 #include "ice_peer_ctx.h"
     40 #include "mozilla/net/DNS.h"
     41 #include "nr_socket_prsock.h"
     42 #include "nricectx.h"
     43 #include "nricemediastream.h"
     44 #include "nriceresolver.h"
     45 #include "nriceresolverfake.h"
     46 #include "nrinterfaceprioritizer.h"
     47 #include "nsISocketFilter.h"
     48 #include "rlogconnector.h"
     49 #include "runnable_utils.h"
     50 #include "stunserver.h"
     51 #include "test_nr_socket.h"
     52 
     53 #define GTEST_HAS_RTTI 0
     54 #include "gtest/gtest.h"
     55 #include "gtest_utils.h"
     56 
     57 using namespace mozilla;
     58 
     59 static unsigned int kDefaultTimeout = 7000;
     60 
     61 // TODO: It would be nice to have a test STUN/TURN server that can run with
     62 // gtest.
     63 MOZ_RUNINIT const std::string kDefaultStunServerHostname((char*)"");
     64 MOZ_RUNINIT const std::string kBogusStunServerHostname(
     65    (char*)"stun-server-nonexistent.invalid");
     66 const uint16_t kDefaultStunServerPort = 19305;
     67 MOZ_RUNINIT const std::string kBogusIceCandidate(
     68    (char*)"candidate:0 2 UDP 2113601790 192.168.178.20 50769 typ");
     69 
     70 MOZ_RUNINIT const std::string kUnreachableHostIceCandidate(
     71    (char*)"candidate:0 1 UDP 2113601790 192.168.178.20 50769 typ host");
     72 
     73 namespace {
     74 
     75 // DNS resolution helper code
     76 static std::string Resolve(const std::string& fqdn, int address_family) {
     77  struct addrinfo hints;
     78  memset(&hints, 0, sizeof(hints));
     79  hints.ai_family = address_family;
     80  hints.ai_protocol = IPPROTO_UDP;
     81  struct addrinfo* res;
     82  int err = getaddrinfo(fqdn.c_str(), nullptr, &hints, &res);
     83  if (err) {
     84    std::cerr << "Error in getaddrinfo: " << err << std::endl;
     85    return "";
     86  }
     87 
     88  char str_addr[64] = {0};
     89  switch (res->ai_family) {
     90    case AF_INET:
     91      inet_ntop(AF_INET,
     92                &reinterpret_cast<struct sockaddr_in*>(res->ai_addr)->sin_addr,
     93                str_addr, sizeof(str_addr));
     94      break;
     95    case AF_INET6:
     96      inet_ntop(
     97          AF_INET6,
     98          &reinterpret_cast<struct sockaddr_in6*>(res->ai_addr)->sin6_addr,
     99          str_addr, sizeof(str_addr));
    100      break;
    101    default:
    102      std::cerr << "Got unexpected address family in DNS lookup: "
    103                << res->ai_family << std::endl;
    104      freeaddrinfo(res);
    105      return "";
    106  }
    107 
    108  if (!strlen(str_addr)) {
    109    std::cerr << "inet_ntop failed" << std::endl;
    110  }
    111 
    112  freeaddrinfo(res);
    113  return str_addr;
    114 }
    115 
    116 class StunTest : public MtransportTest {
    117 public:
    118  StunTest() = default;
    119 
    120  void SetUp() override {
    121    MtransportTest::SetUp();
    122 
    123    stun_server_hostname_ = kDefaultStunServerHostname;
    124    // If only a STUN server FQDN was provided, look up its IP address for the
    125    // address-only tests.
    126    if (stun_server_address_.empty() && !stun_server_hostname_.empty()) {
    127      stun_server_address_ = Resolve(stun_server_hostname_, AF_INET);
    128      ASSERT_TRUE(!stun_server_address_.empty());
    129    }
    130 
    131    test_utils_->SyncDispatchToSTS(WrapRunnable(this, &StunTest::SetUp_s));
    132  }
    133 
    134  void SetUp_s() {
    135    // Make sure NrIceCtx is in a testable state.
    136    NrIceCtx::internal_DeinitializeGlobal();
    137    RLogConnector::CreateInstance();
    138 
    139    TestStunServer::GetInstance(AF_INET);
    140    TestStunServer::GetInstance(AF_INET6);
    141 
    142    TestStunTcpServer::GetInstance(AF_INET);
    143    TestStunTcpServer::GetInstance(AF_INET6);
    144  }
    145 
    146  void TearDown() override {
    147    test_utils_->SyncDispatchToSTS(WrapRunnable(this, &StunTest::TearDown_s));
    148    MtransportTest::TearDown();
    149  }
    150 
    151  void TearDown_s() {
    152    NrIceCtx::internal_DeinitializeGlobal();
    153    TestStunServer::ShutdownInstance();
    154    TestStunTcpServer::ShutdownInstance();
    155  }
    156 };
    157 
    158 enum TrickleMode { TRICKLE_NONE, TRICKLE_SIMULATE, TRICKLE_REAL };
    159 
    160 enum ConsentStatus { CONSENT_FRESH, CONSENT_STALE, CONSENT_EXPIRED };
    161 
    162 typedef std::string (*CandidateFilter)(const std::string& candidate);
    163 
    164 std::vector<std::string> split(const std::string& s, char delim) {
    165  std::vector<std::string> elems;
    166  std::stringstream ss(s);
    167  std::string item;
    168  while (std::getline(ss, item, delim)) {
    169    elems.push_back(item);
    170  }
    171  return elems;
    172 }
    173 
    174 static std::string IsSrflxCandidate(const std::string& candidate) {
    175  std::vector<std::string> tokens = split(candidate, ' ');
    176  if ((tokens.at(6) == "typ") && (tokens.at(7) == "srflx")) {
    177    return candidate;
    178  }
    179  return std::string();
    180 }
    181 
    182 static std::string IsRelayCandidate(const std::string& candidate) {
    183  if (candidate.find("typ relay") != std::string::npos) {
    184    return candidate;
    185  }
    186  return std::string();
    187 }
    188 
    189 static std::string IsTcpCandidate(const std::string& candidate) {
    190  if (candidate.find("TCP") != std::string::npos) {
    191    return candidate;
    192  }
    193  return std::string();
    194 }
    195 
    196 static std::string IsTcpSoCandidate(const std::string& candidate) {
    197  if (candidate.find("tcptype so") != std::string::npos) {
    198    return candidate;
    199  }
    200  return std::string();
    201 }
    202 
    203 static std::string IsLoopbackCandidate(const std::string& candidate) {
    204  if (candidate.find("127.0.0.") != std::string::npos) {
    205    return candidate;
    206  }
    207  return std::string();
    208 }
    209 
    210 static std::string IsIpv4Candidate(const std::string& candidate) {
    211  std::vector<std::string> tokens = split(candidate, ' ');
    212  if (tokens.at(4).find(':') == std::string::npos) {
    213    return candidate;
    214  }
    215  return std::string();
    216 }
    217 
    218 static std::string SabotageHostCandidateAndDropReflexive(
    219    const std::string& candidate) {
    220  if (candidate.find("typ srflx") != std::string::npos) {
    221    return std::string();
    222  }
    223 
    224  if (candidate.find("typ host") != std::string::npos) {
    225    return kUnreachableHostIceCandidate;
    226  }
    227 
    228  return candidate;
    229 }
    230 
    231 bool ContainsSucceededPair(const std::vector<NrIceCandidatePair>& pairs) {
    232  for (const auto& pair : pairs) {
    233    if (pair.state == NrIceCandidatePair::STATE_SUCCEEDED) {
    234      return true;
    235    }
    236  }
    237  return false;
    238 }
    239 
    240 // Note: Does not correspond to any notion of prioritization; this is just
    241 // so we can use stl containers/algorithms that need a comparator
    242 bool operator<(const NrIceCandidate& lhs, const NrIceCandidate& rhs) {
    243  if (lhs.cand_addr.host == rhs.cand_addr.host) {
    244    if (lhs.cand_addr.port == rhs.cand_addr.port) {
    245      if (lhs.cand_addr.transport == rhs.cand_addr.transport) {
    246        if (lhs.type == rhs.type) {
    247          return lhs.tcp_type < rhs.tcp_type;
    248        }
    249        return lhs.type < rhs.type;
    250      }
    251      return lhs.cand_addr.transport < rhs.cand_addr.transport;
    252    }
    253    return lhs.cand_addr.port < rhs.cand_addr.port;
    254  }
    255  return lhs.cand_addr.host < rhs.cand_addr.host;
    256 }
    257 
    258 bool operator==(const NrIceCandidate& lhs, const NrIceCandidate& rhs) {
    259  return !((lhs < rhs) || (rhs < lhs));
    260 }
    261 
    262 class IceCandidatePairCompare {
    263 public:
    264  bool operator()(const NrIceCandidatePair& lhs,
    265                  const NrIceCandidatePair& rhs) const {
    266    if (lhs.priority == rhs.priority) {
    267      if (lhs.local == rhs.local) {
    268        if (lhs.remote == rhs.remote) {
    269          return lhs.codeword < rhs.codeword;
    270        }
    271        return lhs.remote < rhs.remote;
    272      }
    273      return lhs.local < rhs.local;
    274    }
    275    return lhs.priority < rhs.priority;
    276  }
    277 };
    278 
    279 class IceTestPeer;
    280 
    281 class SchedulableTrickleCandidate {
    282 public:
    283  SchedulableTrickleCandidate(IceTestPeer* peer, size_t stream,
    284                              const std::string& candidate,
    285                              const std::string& ufrag,
    286                              MtransportTestUtils* utils)
    287      : peer_(peer),
    288        stream_(stream),
    289        candidate_(candidate),
    290        ufrag_(ufrag),
    291        timer_handle_(nullptr),
    292        test_utils_(utils) {}
    293 
    294  ~SchedulableTrickleCandidate() {
    295    if (timer_handle_) NR_async_timer_cancel(timer_handle_);
    296  }
    297 
    298  void Schedule(unsigned int ms) {
    299    std::cerr << "Scheduling " << Candidate() << " in " << ms << "ms"
    300              << std::endl;
    301    test_utils_->SyncDispatchToSTS(
    302        WrapRunnable(this, &SchedulableTrickleCandidate::Schedule_s, ms));
    303  }
    304 
    305  void Schedule_s(unsigned int ms) {
    306    MOZ_ASSERT(!timer_handle_);
    307    NR_ASYNC_TIMER_SET(ms, Trickle_cb, this, &timer_handle_);
    308  }
    309 
    310  static void Trickle_cb(NR_SOCKET s, int how, void* cb_arg) {
    311    static_cast<SchedulableTrickleCandidate*>(cb_arg)->Trickle();
    312  }
    313 
    314  void Trickle();
    315 
    316  std::string& Candidate() { return candidate_; }
    317 
    318  const std::string& Candidate() const { return candidate_; }
    319 
    320  bool IsHost() const {
    321    return candidate_.find("typ host") != std::string::npos;
    322  }
    323 
    324  bool IsReflexive() const {
    325    return candidate_.find("typ srflx") != std::string::npos;
    326  }
    327 
    328  bool IsRelay() const {
    329    return candidate_.find("typ relay") != std::string::npos;
    330  }
    331 
    332 private:
    333  IceTestPeer* peer_;
    334  size_t stream_;
    335  std::string candidate_;
    336  std::string ufrag_;
    337  void* timer_handle_;
    338  MtransportTestUtils* test_utils_;
    339 
    340  DISALLOW_COPY_ASSIGN(SchedulableTrickleCandidate);
    341 };
    342 
    343 class IceTestPeer : public sigslot::has_slots<> {
    344 public:
    345  IceTestPeer(const std::string& name, MtransportTestUtils* utils, bool offerer,
    346              const NrIceCtx::Config& config)
    347      : name_(name),
    348        ice_ctx_(NrIceCtx::Create(name)),
    349        offerer_(offerer),
    350        stream_counter_(0),
    351        shutting_down_(false),
    352        mConnectionStates("IceTestPeer::mConnectionStates"),
    353        mGatheringStates("IceTestPeer::mGatheringStates"),
    354        ready_ct_(0),
    355        ice_reached_checking_(false),
    356        received_(0),
    357        sent_(0),
    358        dns_resolver_(new NrIceResolver()),
    359        remote_(nullptr),
    360        candidate_filter_(nullptr),
    361        expected_local_type_(NrIceCandidate::ICE_HOST),
    362        expected_local_transport_(kNrIceTransportUdp),
    363        expected_remote_type_(NrIceCandidate::ICE_HOST),
    364        trickle_mode_(TRICKLE_NONE),
    365        simulate_ice_lite_(false),
    366        nat_(new TestNat),
    367        test_utils_(utils) {
    368    ice_ctx_->SignalConnectionStateChange.connect(
    369        this, &IceTestPeer::ConnectionStateChange);
    370 
    371    ice_ctx_->SetIceConfig(config);
    372 
    373    consent_timestamp_.tv_sec = 0;
    374    consent_timestamp_.tv_usec = 0;
    375    int r = ice_ctx_->SetNat(nat_);
    376    (void)r;
    377    MOZ_ASSERT(!r);
    378  }
    379 
    380  ~IceTestPeer() {
    381    test_utils_->SyncDispatchToSTS(WrapRunnable(this, &IceTestPeer::Shutdown));
    382 
    383    // Give the ICE destruction callback time to fire before
    384    // we destroy the resolver.
    385    PR_Sleep(1000);
    386  }
    387 
    388  std::string MakeTransportId(size_t index) const {
    389    char id[100];
    390    snprintf(id, sizeof(id), "%s:stream%d", name_.c_str(), (int)index);
    391    return id;
    392  }
    393 
    394  void SetIceCredentials_s(NrIceMediaStream& stream) {
    395    static size_t counter = 0;
    396    std::ostringstream prefix;
    397    prefix << name_ << "-" << counter++;
    398    std::string ufrag = prefix.str() + "-ufrag";
    399    std::string pwd = prefix.str() + "-pwd";
    400    if (mIceCredentials.count(stream.GetId())) {
    401      mOldIceCredentials[stream.GetId()] = mIceCredentials[stream.GetId()];
    402    }
    403    mIceCredentials[stream.GetId()] = std::make_pair(ufrag, pwd);
    404    stream.SetIceCredentials(ufrag, pwd);
    405  }
    406 
    407  void AddStream_s(int components) {
    408    std::string id = MakeTransportId(stream_counter_++);
    409 
    410    RefPtr<NrIceMediaStream> stream =
    411        ice_ctx_->CreateStream(id, id, components);
    412 
    413    ASSERT_TRUE(stream);
    414    SetIceCredentials_s(*stream);
    415 
    416    stream->SignalCandidate.connect(this, &IceTestPeer::CandidateInitialized);
    417    stream->SignalReady.connect(this, &IceTestPeer::StreamReady);
    418    stream->SignalFailed.connect(this, &IceTestPeer::StreamFailed);
    419    stream->SignalPacketReceived.connect(this, &IceTestPeer::PacketReceived);
    420    stream->SignalGatheringStateChange.connect(
    421        this, &IceTestPeer::GatheringStateChange);
    422    {
    423      auto lock = mConnectionStates.Lock();
    424      lock.ref()[id] = NrIceCtx::ICE_CTX_INIT;
    425    }
    426    {
    427      auto lock = mGatheringStates.Lock();
    428      lock.ref()[id] = NrIceMediaStream::ICE_STREAM_GATHER_INIT;
    429    }
    430  }
    431 
    432  void AddStream(int components) {
    433    test_utils_->SyncDispatchToSTS(
    434        WrapRunnable(this, &IceTestPeer::AddStream_s, components));
    435  }
    436 
    437  void RemoveStream_s(size_t index) {
    438    const std::string id = MakeTransportId(index);
    439    ice_ctx_->DestroyStream(id);
    440    {
    441      auto lock = mConnectionStates.Lock();
    442      lock->erase(id);
    443    }
    444    {
    445      auto lock = mGatheringStates.Lock();
    446      lock->erase(id);
    447    }
    448  }
    449 
    450  void RemoveStream(size_t index) {
    451    test_utils_->SyncDispatchToSTS(
    452        WrapRunnable(this, &IceTestPeer::RemoveStream_s, index));
    453  }
    454 
    455  RefPtr<NrIceMediaStream> GetStream_s(size_t index) {
    456    std::string id = MakeTransportId(index);
    457    return ice_ctx_->GetStream(id);
    458  }
    459 
    460  void SetStunServer(const std::string addr, uint16_t port,
    461                     const char* transport = kNrIceTransportUdp) {
    462    if (addr.empty()) {
    463      // Happens when MOZ_DISABLE_NONLOCAL_CONNECTIONS is set
    464      return;
    465    }
    466 
    467    std::vector<NrIceStunServer> stun_servers;
    468    UniquePtr<NrIceStunServer> server(
    469        NrIceStunServer::Create(addr, port, transport));
    470    stun_servers.push_back(*server);
    471    SetStunServers(stun_servers);
    472  }
    473 
    474  void SetStunServers(const std::vector<NrIceStunServer>& servers) {
    475    ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetStunServers(servers)));
    476  }
    477 
    478  void UseTestStunServer() {
    479    SetStunServer(TestStunServer::GetInstance(AF_INET)->addr(),
    480                  TestStunServer::GetInstance(AF_INET)->port());
    481  }
    482 
    483  void SetTurnServer(const std::string addr, uint16_t port,
    484                     const std::string username, const std::string password,
    485                     const char* transport) {
    486    std::vector<unsigned char> password_vec(password.begin(), password.end());
    487    SetTurnServer(addr, port, username, password_vec, transport);
    488  }
    489 
    490  void SetTurnServer(const std::string addr, uint16_t port,
    491                     const std::string username,
    492                     const std::vector<unsigned char> password,
    493                     const char* transport) {
    494    std::vector<NrIceTurnServer> turn_servers;
    495    UniquePtr<NrIceTurnServer> server(
    496        NrIceTurnServer::Create(addr, port, username, password, transport));
    497    turn_servers.push_back(*server);
    498    ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetTurnServers(turn_servers)));
    499  }
    500 
    501  void SetTurnServers(const std::vector<NrIceTurnServer> servers) {
    502    ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetTurnServers(servers)));
    503  }
    504 
    505  void SetFakeResolver(const std::string& ip, const std::string& fqdn) {
    506    ASSERT_TRUE(NS_SUCCEEDED(dns_resolver_->Init()));
    507    if (!ip.empty() && !fqdn.empty()) {
    508      PRNetAddr addr;
    509      PRStatus status = PR_StringToNetAddr(ip.c_str(), &addr);
    510      addr.inet.port = kDefaultStunServerPort;
    511      ASSERT_EQ(PR_SUCCESS, status);
    512      fake_resolver_.SetAddr(fqdn, addr);
    513    }
    514    ASSERT_TRUE(
    515        NS_SUCCEEDED(ice_ctx_->SetResolver(fake_resolver_.AllocateResolver())));
    516  }
    517 
    518  void SetDNSResolver() {
    519    ASSERT_TRUE(NS_SUCCEEDED(dns_resolver_->Init()));
    520    ASSERT_TRUE(
    521        NS_SUCCEEDED(ice_ctx_->SetResolver(dns_resolver_->AllocateResolver())));
    522  }
    523 
    524  void Gather(bool default_route_only = false,
    525              bool obfuscate_host_addresses = false) {
    526    nsresult res;
    527 
    528    test_utils_->SyncDispatchToSTS(
    529        WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::StartGathering,
    530                        default_route_only, obfuscate_host_addresses));
    531 
    532    ASSERT_TRUE(NS_SUCCEEDED(res));
    533  }
    534 
    535  void SetCtxFlags(bool default_route_only) {
    536    test_utils_->SyncDispatchToSTS(
    537        WrapRunnable(ice_ctx_, &NrIceCtx::SetCtxFlags, default_route_only));
    538  }
    539 
    540  nsTArray<NrIceStunAddr> GetStunAddrs() { return ice_ctx_->GetStunAddrs(); }
    541 
    542  void SetStunAddrs(const nsTArray<NrIceStunAddr>& addrs) {
    543    ice_ctx_->SetStunAddrs(addrs);
    544  }
    545 
    546  void UseNat() {
    547    test_utils_->SyncDispatchToSTS(WrapRunnable(this, &IceTestPeer::UseNat_s));
    548  }
    549 
    550  void UseNat_s() { nat_->enabled_ = true; }
    551 
    552  void SetTimerDivider(int div) { ice_ctx_->internal_SetTimerAccelarator(div); }
    553 
    554  void SetStunResponseDelay(uint32_t delay) {
    555    test_utils_->SyncDispatchToSTS(
    556        WrapRunnable(this, &IceTestPeer::SetStunResponseDelay_s, delay));
    557  }
    558 
    559  void SetStunResponseDelay_s(uint32_t delay) {
    560    nat_->delay_stun_resp_ms_ = delay;
    561  }
    562 
    563  void SetFilteringType(TestNat::NatBehavior type) {
    564    test_utils_->SyncDispatchToSTS(
    565        WrapRunnable(this, &IceTestPeer::SetFilteringType_s, type));
    566  }
    567 
    568  void SetFilteringType_s(TestNat::NatBehavior type) {
    569    MOZ_ASSERT(!nat_->has_port_mappings());
    570    nat_->filtering_type_ = type;
    571  }
    572 
    573  void SetMappingType(TestNat::NatBehavior type) {
    574    test_utils_->SyncDispatchToSTS(
    575        WrapRunnable(this, &IceTestPeer::SetMappingType_s, type));
    576  }
    577 
    578  void SetMappingType_s(TestNat::NatBehavior type) {
    579    MOZ_ASSERT(!nat_->has_port_mappings());
    580    nat_->mapping_type_ = type;
    581  }
    582 
    583  void SetBlockUdp(bool block) {
    584    test_utils_->SyncDispatchToSTS(
    585        WrapRunnable(this, &IceTestPeer::SetBlockUdp_s, block));
    586  }
    587 
    588  void SetBlockUdp_s(bool block) {
    589    MOZ_ASSERT(!nat_->has_port_mappings());
    590    nat_->block_udp_ = block;
    591  }
    592 
    593  void SetBlockStun(bool block) {
    594    test_utils_->SyncDispatchToSTS(
    595        WrapRunnable(this, &IceTestPeer::SetBlockStun_s, block));
    596  }
    597 
    598  void SetBlockStun_s(bool block) { nat_->block_stun_ = block; }
    599 
    600  // Get various pieces of state
    601  std::vector<std::string> GetGlobalAttributes() {
    602    std::vector<std::string> attrs(ice_ctx_->GetGlobalAttributes());
    603    if (simulate_ice_lite_) {
    604      attrs.push_back("ice-lite");
    605    }
    606    return attrs;
    607  }
    608 
    609  std::vector<std::string> GetAttributes(size_t stream) {
    610    std::vector<std::string> v;
    611 
    612    RUN_ON_THREAD(
    613        test_utils_->sts_target(),
    614        WrapRunnableRet(&v, this, &IceTestPeer::GetAttributes_s, stream));
    615 
    616    return v;
    617  }
    618 
    619  std::string FilterCandidate(const std::string& candidate) {
    620    if (candidate_filter_) {
    621      return candidate_filter_(candidate);
    622    }
    623    return candidate;
    624  }
    625 
    626  std::vector<std::string> GetAttributes_s(size_t index) {
    627    std::vector<std::string> attributes;
    628 
    629    auto stream = GetStream_s(index);
    630    if (!stream) {
    631      EXPECT_TRUE(false) << "No such stream " << index;
    632      return attributes;
    633    }
    634 
    635    std::vector<std::string> attributes_in = stream->GetAttributes();
    636 
    637    for (const auto& attribute : attributes_in) {
    638      if (attribute.find("candidate:") != std::string::npos) {
    639        std::string candidate(FilterCandidate(attribute));
    640        if (!candidate.empty()) {
    641          std::cerr << name_ << " Returning candidate: " << candidate
    642                    << std::endl;
    643          attributes.push_back(candidate);
    644        }
    645      } else {
    646        attributes.push_back(attribute);
    647      }
    648    }
    649 
    650    return attributes;
    651  }
    652 
    653  void SetExpectedTypes(NrIceCandidate::Type local, NrIceCandidate::Type remote,
    654                        std::string local_transport = kNrIceTransportUdp) {
    655    expected_local_type_ = local;
    656    expected_local_transport_ = local_transport;
    657    expected_remote_type_ = remote;
    658  }
    659 
    660  void SetExpectedRemoteCandidateAddr(const std::string& addr) {
    661    expected_remote_addr_ = addr;
    662  }
    663 
    664  int GetCandidatesPrivateIpv4Range(size_t stream) {
    665    std::vector<std::string> attributes = GetAttributes(stream);
    666 
    667    int host_net = 0;
    668    for (const auto& a : attributes) {
    669      if (a.find("typ host") != std::string::npos) {
    670        nr_transport_addr addr;
    671        std::vector<std::string> tokens = split(a, ' ');
    672        int r = nr_str_port_to_transport_addr(tokens.at(4).c_str(), 0,
    673                                              IPPROTO_UDP, &addr);
    674        MOZ_ASSERT(!r);
    675        if (!r && (addr.ip_version == NR_IPV4)) {
    676          int n = nr_transport_addr_get_private_addr_range(&addr);
    677          if (n) {
    678            if (host_net) {
    679              // TODO: add support for multiple private interfaces
    680              std::cerr
    681                  << "This test doesn't support multiple private interfaces";
    682              return -1;
    683            }
    684            host_net = n;
    685          }
    686        }
    687      }
    688    }
    689    return host_net;
    690  }
    691 
    692  bool gathering_complete() {
    693    auto lock = mGatheringStates.Lock();
    694    for (const auto& [id, state] : lock.ref()) {
    695      (void)id;
    696      if (state != NrIceMediaStream::ICE_STREAM_GATHER_COMPLETE) {
    697        return false;
    698      }
    699    }
    700    return true;
    701  }
    702  int ready_ct() { return ready_ct_; }
    703  bool is_ready_s(size_t index) {
    704    auto media_stream = GetStream_s(index);
    705    if (!media_stream) {
    706      EXPECT_TRUE(false) << "No such stream " << index;
    707      return false;
    708    }
    709    return media_stream->state() == NrIceMediaStream::ICE_OPEN;
    710  }
    711  bool is_ready(size_t stream) {
    712    bool result;
    713    test_utils_->SyncDispatchToSTS(
    714        WrapRunnableRet(&result, this, &IceTestPeer::is_ready_s, stream));
    715    return result;
    716  }
    717  bool ice_connected() {
    718    auto lock = mConnectionStates.Lock();
    719    for (const auto& [id, state] : lock.ref()) {
    720      if (state != NrIceCtx::ICE_CTX_CONNECTED) {
    721        return false;
    722      }
    723    }
    724    return true;
    725  }
    726  bool ice_failed() {
    727    auto lock = mConnectionStates.Lock();
    728    for (const auto& [id, state] : lock.ref()) {
    729      if (state == NrIceCtx::ICE_CTX_FAILED) {
    730        return true;
    731      }
    732    }
    733    return false;
    734  }
    735  bool ice_checking() {
    736    if (ice_failed() || ice_connected()) {
    737      return false;
    738    }
    739    auto lock = mConnectionStates.Lock();
    740    for (const auto& [id, state] : lock.ref()) {
    741      if (state == NrIceCtx::ICE_CTX_CHECKING) {
    742        return true;
    743      }
    744    }
    745    return false;
    746  }
    747  bool ice_reached_checking() { return ice_reached_checking_; }
    748  size_t received() { return received_; }
    749  size_t sent() { return sent_; }
    750 
    751  void RestartIce() {
    752    test_utils_->SyncDispatchToSTS(
    753        WrapRunnable(this, &IceTestPeer::RestartIce_s));
    754  }
    755 
    756  void RestartIce_s() {
    757    for (auto& stream : ice_ctx_->GetStreams()) {
    758      SetIceCredentials_s(*stream);
    759      {
    760        auto lock = mConnectionStates.Lock();
    761        lock.ref()[stream->GetId()] = NrIceCtx::ICE_CTX_INIT;
    762      }
    763      {
    764        auto lock = mGatheringStates.Lock();
    765        lock.ref()[stream->GetId()] = NrIceMediaStream::ICE_STREAM_GATHER_INIT;
    766      }
    767    }
    768    // take care of some local bookkeeping
    769    ready_ct_ = 0;
    770    // We do not unset ice_reached_checking_ here, since we do not expect
    771    // ICE to return to checking in an ICE restart, because the ICE stack
    772    // continues using the old streams (which are probably connected) until the
    773    // new ones are connected.
    774    remote_ = nullptr;
    775  }
    776 
    777  void RollbackIceRestart() {
    778    test_utils_->SyncDispatchToSTS(
    779        WrapRunnable(this, &IceTestPeer::RollbackIceRestart_s));
    780  }
    781 
    782  void RollbackIceRestart_s() {
    783    for (auto& stream : ice_ctx_->GetStreams()) {
    784      mIceCredentials[stream->GetId()] = mOldIceCredentials[stream->GetId()];
    785    }
    786  }
    787 
    788  // Start connecting to another peer
    789  void Connect_s(IceTestPeer* remote, TrickleMode trickle_mode,
    790                 bool start = true) {
    791    nsresult res;
    792 
    793    remote_ = remote;
    794 
    795    trickle_mode_ = trickle_mode;
    796    res = ice_ctx_->ParseGlobalAttributes(remote->GetGlobalAttributes());
    797    ASSERT_FALSE(remote->simulate_ice_lite_ &&
    798                 (ice_ctx_->GetControlling() == NrIceCtx::ICE_CONTROLLED));
    799    ASSERT_TRUE(NS_SUCCEEDED(res));
    800 
    801    for (size_t i = 0; i < stream_counter_; ++i) {
    802      auto aStream = GetStream_s(i);
    803      if (aStream) {
    804        std::vector<std::string> attributes = remote->GetAttributes(i);
    805 
    806        for (auto it = attributes.begin(); it != attributes.end();) {
    807          if (trickle_mode == TRICKLE_SIMULATE &&
    808              it->find("candidate:") != std::string::npos) {
    809            std::cerr << name_ << " Deferring remote candidate: " << *it
    810                      << std::endl;
    811            attributes.erase(it);
    812          } else {
    813            std::cerr << name_ << " Adding remote attribute: " + *it
    814                      << std::endl;
    815            ++it;
    816          }
    817        }
    818        auto credentials = mIceCredentials[aStream->GetId()];
    819        res = aStream->ConnectToPeer(credentials.first, credentials.second,
    820                                     attributes);
    821        ASSERT_TRUE(NS_SUCCEEDED(res));
    822      }
    823    }
    824 
    825    if (start) {
    826      ice_ctx_->SetControlling(offerer_ ? NrIceCtx::ICE_CONTROLLING
    827                                        : NrIceCtx::ICE_CONTROLLED);
    828      // Now start checks
    829      res = ice_ctx_->StartChecks();
    830      ASSERT_TRUE(NS_SUCCEEDED(res));
    831    }
    832  }
    833 
    834  void Connect(IceTestPeer* remote, TrickleMode trickle_mode,
    835               bool start = true) {
    836    test_utils_->SyncDispatchToSTS(WrapRunnable(this, &IceTestPeer::Connect_s,
    837                                                remote, trickle_mode, start));
    838  }
    839 
    840  void SimulateTrickle(size_t stream) {
    841    std::cerr << name_ << " Doing trickle for stream " << stream << std::endl;
    842    // If we are in trickle deferred mode, now trickle in the candidates
    843    // for |stream|
    844 
    845    std::vector<SchedulableTrickleCandidate*>& candidates =
    846        ControlTrickle(stream);
    847 
    848    for (auto& candidate : candidates) {
    849      candidate->Schedule(0);
    850    }
    851  }
    852 
    853  // Allows test case to completely control when/if candidates are trickled
    854  // (test could also do things like insert extra trickle candidates, or
    855  // change existing ones, or insert duplicates, really anything is fair game)
    856  std::vector<SchedulableTrickleCandidate*>& ControlTrickle(size_t stream) {
    857    std::cerr << "Doing controlled trickle for stream " << stream << std::endl;
    858 
    859    std::vector<std::string> attributes = remote_->GetAttributes(stream);
    860 
    861    for (const auto& attribute : attributes) {
    862      if (attribute.find("candidate:") != std::string::npos) {
    863        controlled_trickle_candidates_[stream].push_back(
    864            new SchedulableTrickleCandidate(this, stream, attribute, "",
    865                                            test_utils_));
    866      }
    867    }
    868 
    869    return controlled_trickle_candidates_[stream];
    870  }
    871 
    872  nsresult TrickleCandidate_s(const std::string& candidate,
    873                              const std::string& ufrag, size_t index) {
    874    auto stream = GetStream_s(index);
    875    if (!stream) {
    876      // stream might have gone away before the trickle timer popped
    877      std::cerr << "Trickle candidate has no stream: " << index << std::endl;
    878      return NS_OK;
    879    }
    880    std::cerr << "Trickle candidate for " << index << " (" << stream->GetId()
    881              << "):" << candidate << std::endl;
    882    return stream->ParseTrickleCandidate(candidate, ufrag, "");
    883  }
    884 
    885  void DumpCandidate(std::string which, const NrIceCandidate& cand) {
    886    std::string type;
    887    std::string tcp_type;
    888 
    889    std::string addr;
    890    int port;
    891 
    892    if (which.find("Remote") != std::string::npos) {
    893      addr = cand.cand_addr.host;
    894      port = cand.cand_addr.port;
    895    } else {
    896      addr = cand.local_addr.host;
    897      port = cand.local_addr.port;
    898    }
    899    switch (cand.type) {
    900      case NrIceCandidate::ICE_HOST:
    901        type = "host";
    902        break;
    903      case NrIceCandidate::ICE_SERVER_REFLEXIVE:
    904        type = "srflx";
    905        break;
    906      case NrIceCandidate::ICE_PEER_REFLEXIVE:
    907        type = "prflx";
    908        break;
    909      case NrIceCandidate::ICE_RELAYED:
    910        type = "relay";
    911        if (which.find("Local") != std::string::npos) {
    912          type += "(" + cand.local_addr.transport + ")";
    913        }
    914        break;
    915      default:
    916        FAIL();
    917    };
    918 
    919    switch (cand.tcp_type) {
    920      case NrIceCandidate::ICE_NONE:
    921        break;
    922      case NrIceCandidate::ICE_ACTIVE:
    923        tcp_type = " tcptype=active";
    924        break;
    925      case NrIceCandidate::ICE_PASSIVE:
    926        tcp_type = " tcptype=passive";
    927        break;
    928      case NrIceCandidate::ICE_SO:
    929        tcp_type = " tcptype=so";
    930        break;
    931      default:
    932        FAIL();
    933    };
    934 
    935    std::cerr << which << " --> " << type << " " << addr << ":" << port << "/"
    936              << cand.cand_addr.transport << tcp_type
    937              << " codeword=" << cand.codeword << std::endl;
    938  }
    939 
    940  void DumpAndCheckActiveCandidates_s() {
    941    std::cerr << name_ << " Active candidates:" << std::endl;
    942    for (const auto& stream : ice_ctx_->GetStreams()) {
    943      for (size_t j = 0; j < stream->components(); ++j) {
    944        std::cerr << name_ << " Stream " << stream->GetId() << " component "
    945                  << j + 1 << std::endl;
    946 
    947        UniquePtr<NrIceCandidate> local;
    948        UniquePtr<NrIceCandidate> remote;
    949 
    950        nsresult res = stream->GetActivePair(j + 1, &local, &remote);
    951        if (res == NS_ERROR_NOT_AVAILABLE) {
    952          std::cerr << "Component unpaired or disabled." << std::endl;
    953        } else {
    954          ASSERT_TRUE(NS_SUCCEEDED(res));
    955          DumpCandidate("Local  ", *local);
    956          /* Depending on timing, and the whims of the network
    957           * stack/configuration we're running on top of, prflx is always a
    958           * possibility. */
    959          if (expected_local_type_ == NrIceCandidate::ICE_HOST) {
    960            ASSERT_NE(NrIceCandidate::ICE_SERVER_REFLEXIVE, local->type);
    961            ASSERT_NE(NrIceCandidate::ICE_RELAYED, local->type);
    962          } else {
    963            ASSERT_EQ(expected_local_type_, local->type);
    964          }
    965          ASSERT_EQ(expected_local_transport_, local->local_addr.transport);
    966          DumpCandidate("Remote ", *remote);
    967          /* Depending on timing, and the whims of the network
    968           * stack/configuration we're running on top of, prflx is always a
    969           * possibility. */
    970          if (expected_remote_type_ == NrIceCandidate::ICE_HOST) {
    971            ASSERT_NE(NrIceCandidate::ICE_SERVER_REFLEXIVE, remote->type);
    972            ASSERT_NE(NrIceCandidate::ICE_RELAYED, remote->type);
    973          } else {
    974            ASSERT_EQ(expected_remote_type_, remote->type);
    975          }
    976          if (!expected_remote_addr_.empty()) {
    977            ASSERT_EQ(expected_remote_addr_, remote->cand_addr.host);
    978          }
    979        }
    980      }
    981    }
    982  }
    983 
    984  void DumpAndCheckActiveCandidates() {
    985    test_utils_->SyncDispatchToSTS(
    986        WrapRunnable(this, &IceTestPeer::DumpAndCheckActiveCandidates_s));
    987  }
    988 
    989  void Close() {
    990    test_utils_->SyncDispatchToSTS(
    991        WrapRunnable(ice_ctx_, &NrIceCtx::destroy_peer_ctx));
    992  }
    993 
    994  void Shutdown() {
    995    std::cerr << name_ << " Shutdown" << std::endl;
    996    shutting_down_ = true;
    997    for (auto& controlled_trickle_candidate : controlled_trickle_candidates_) {
    998      for (auto& cand : controlled_trickle_candidate.second) {
    999        delete cand;
   1000      }
   1001    }
   1002 
   1003    ice_ctx_->Destroy();
   1004    ice_ctx_ = nullptr;
   1005 
   1006    if (remote_) {
   1007      remote_->UnsetRemote();
   1008      remote_ = nullptr;
   1009    }
   1010  }
   1011 
   1012  void UnsetRemote() { remote_ = nullptr; }
   1013 
   1014  void StartChecks() {
   1015    nsresult res;
   1016 
   1017    test_utils_->SyncDispatchToSTS(WrapRunnableRet(
   1018        &res, ice_ctx_, &NrIceCtx::SetControlling,
   1019        offerer_ ? NrIceCtx::ICE_CONTROLLING : NrIceCtx::ICE_CONTROLLED));
   1020    // Now start checks
   1021    test_utils_->SyncDispatchToSTS(
   1022        WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::StartChecks));
   1023    ASSERT_TRUE(NS_SUCCEEDED(res));
   1024  }
   1025 
   1026  // Handle events
   1027  void GatheringStateChange(const std::string& aTransportId,
   1028                            NrIceMediaStream::GatheringState state) {
   1029    if (shutting_down_) {
   1030      return;
   1031    }
   1032 
   1033    {
   1034      auto lock = mGatheringStates.Lock();
   1035      lock.ref()[aTransportId] = state;
   1036    }
   1037 
   1038    if (!gathering_complete()) {
   1039      return;
   1040    }
   1041 
   1042    std::cerr << name_ << " Gathering complete" << std::endl;
   1043 
   1044    std::cerr << name_ << " ATTRIBUTES:" << std::endl;
   1045    for (const auto& stream : ice_ctx_->GetStreams()) {
   1046      std::cerr << "Stream " << stream->GetId() << std::endl;
   1047 
   1048      std::vector<std::string> attributes = stream->GetAttributes();
   1049 
   1050      for (const auto& attribute : attributes) {
   1051        std::cerr << attribute << std::endl;
   1052      }
   1053    }
   1054    std::cerr << std::endl;
   1055  }
   1056 
   1057  void CandidateInitialized(NrIceMediaStream* stream,
   1058                            const std::string& raw_candidate,
   1059                            const std::string& ufrag,
   1060                            const std::string& mdns_addr,
   1061                            const std::string& actual_addr) {
   1062    std::string candidate(FilterCandidate(raw_candidate));
   1063    if (candidate.empty()) {
   1064      return;
   1065    }
   1066    std::cerr << "Candidate for stream " << stream->GetId()
   1067              << " initialized: " << candidate << std::endl;
   1068    candidates_[stream->GetId()].push_back(candidate);
   1069 
   1070    // If we are connected, then try to trickle to the other side.
   1071    if (remote_ && remote_->remote_ && (trickle_mode_ != TRICKLE_SIMULATE)) {
   1072      // first, find the index of the stream we've been given so
   1073      // we can get the corresponding stream on the remote side
   1074      for (size_t i = 0; i < stream_counter_; ++i) {
   1075        if (GetStream_s(i) == stream) {
   1076          ASSERT_GT(remote_->stream_counter_, i);
   1077          nsresult res = remote_->GetStream_s(i)->ParseTrickleCandidate(
   1078              candidate, ufrag, "");
   1079          ASSERT_TRUE(NS_SUCCEEDED(res));
   1080          return;
   1081        }
   1082      }
   1083      ADD_FAILURE() << "No matching stream found for " << stream->GetId();
   1084    }
   1085  }
   1086 
   1087  nsresult GetCandidatePairs_s(size_t stream_index,
   1088                               std::vector<NrIceCandidatePair>* pairs) {
   1089    MOZ_ASSERT(pairs);
   1090    auto stream = GetStream_s(stream_index);
   1091    if (!stream) {
   1092      // Is there a better error for "no such index"?
   1093      ADD_FAILURE() << "No such media stream index: " << stream_index;
   1094      return NS_ERROR_INVALID_ARG;
   1095    }
   1096 
   1097    return stream->GetCandidatePairs(pairs);
   1098  }
   1099 
   1100  nsresult GetCandidatePairs(size_t stream_index,
   1101                             std::vector<NrIceCandidatePair>* pairs) {
   1102    nsresult v;
   1103    test_utils_->SyncDispatchToSTS(WrapRunnableRet(
   1104        &v, this, &IceTestPeer::GetCandidatePairs_s, stream_index, pairs));
   1105    return v;
   1106  }
   1107 
   1108  void DumpCandidatePair(const NrIceCandidatePair& pair) {
   1109    std::cerr << std::endl;
   1110    DumpCandidate("Local", pair.local);
   1111    DumpCandidate("Remote", pair.remote);
   1112    std::cerr << "state = " << pair.state << " priority = " << pair.priority
   1113              << " nominated = " << pair.nominated
   1114              << " selected = " << pair.selected
   1115              << " codeword = " << pair.codeword << std::endl;
   1116  }
   1117 
   1118  void DumpCandidatePairs_s(NrIceMediaStream* stream) {
   1119    std::vector<NrIceCandidatePair> pairs;
   1120    nsresult res = stream->GetCandidatePairs(&pairs);
   1121    ASSERT_TRUE(NS_SUCCEEDED(res));
   1122 
   1123    std::cerr << "Begin list of candidate pairs [" << std::endl;
   1124 
   1125    for (auto& pair : pairs) {
   1126      DumpCandidatePair(pair);
   1127    }
   1128    std::cerr << "]" << std::endl;
   1129  }
   1130 
   1131  void DumpCandidatePairs_s() {
   1132    std::cerr << "Dumping candidate pairs for all streams [" << std::endl;
   1133    for (const auto& stream : ice_ctx_->GetStreams()) {
   1134      DumpCandidatePairs_s(stream.get());
   1135    }
   1136    std::cerr << "]" << std::endl;
   1137  }
   1138 
   1139  bool CandidatePairsPriorityDescending(
   1140      const std::vector<NrIceCandidatePair>& pairs) {
   1141    // Verify that priority is descending
   1142    uint64_t priority = std::numeric_limits<uint64_t>::max();
   1143 
   1144    for (size_t p = 0; p < pairs.size(); ++p) {
   1145      if (priority < pairs[p].priority) {
   1146        std::cerr << "Priority increased in subsequent pairs:" << std::endl;
   1147        DumpCandidatePair(pairs[p - 1]);
   1148        DumpCandidatePair(pairs[p]);
   1149        return false;
   1150      }
   1151      if (priority == pairs[p].priority) {
   1152        if (!IceCandidatePairCompare()(pairs[p], pairs[p - 1]) &&
   1153            !IceCandidatePairCompare()(pairs[p - 1], pairs[p])) {
   1154          std::cerr << "Ignoring identical pair from trigger check"
   1155                    << std::endl;
   1156        } else {
   1157          std::cerr << "Duplicate priority in subseqent pairs:" << std::endl;
   1158          DumpCandidatePair(pairs[p - 1]);
   1159          DumpCandidatePair(pairs[p]);
   1160          return false;
   1161        }
   1162      }
   1163      priority = pairs[p].priority;
   1164    }
   1165    return true;
   1166  }
   1167 
   1168  void UpdateAndValidateCandidatePairs(
   1169      size_t stream_index, std::vector<NrIceCandidatePair>* new_pairs) {
   1170    std::vector<NrIceCandidatePair> old_pairs = *new_pairs;
   1171    GetCandidatePairs(stream_index, new_pairs);
   1172    ASSERT_TRUE(CandidatePairsPriorityDescending(*new_pairs))
   1173    << "New list of "
   1174       "candidate pairs is either not sorted in priority order, or has "
   1175       "duplicate priorities.";
   1176    ASSERT_TRUE(CandidatePairsPriorityDescending(old_pairs))
   1177    << "Old list of "
   1178       "candidate pairs is either not sorted in priority order, or has "
   1179       "duplicate priorities. This indicates some bug in the test case.";
   1180    std::vector<NrIceCandidatePair> added_pairs;
   1181    std::vector<NrIceCandidatePair> removed_pairs;
   1182 
   1183    // set_difference computes the set of elements that are present in the
   1184    // first set, but not the second
   1185    // NrIceCandidatePair::operator< compares based on the priority, local
   1186    // candidate, and remote candidate in that order. This means this will
   1187    // catch cases where the priority has remained the same, but one of the
   1188    // candidates has changed.
   1189    std::set_difference((*new_pairs).begin(), (*new_pairs).end(),
   1190                        old_pairs.begin(), old_pairs.end(),
   1191                        std::inserter(added_pairs, added_pairs.begin()),
   1192                        IceCandidatePairCompare());
   1193 
   1194    std::set_difference(old_pairs.begin(), old_pairs.end(),
   1195                        (*new_pairs).begin(), (*new_pairs).end(),
   1196                        std::inserter(removed_pairs, removed_pairs.begin()),
   1197                        IceCandidatePairCompare());
   1198 
   1199    for (auto& added_pair : added_pairs) {
   1200      std::cerr << "Found new candidate pair." << std::endl;
   1201      DumpCandidatePair(added_pair);
   1202    }
   1203 
   1204    for (auto& removed_pair : removed_pairs) {
   1205      std::cerr << "Pre-existing candidate pair is now missing:" << std::endl;
   1206      DumpCandidatePair(removed_pair);
   1207    }
   1208 
   1209    ASSERT_TRUE(removed_pairs.empty())
   1210    << "At least one candidate pair has "
   1211       "gone missing.";
   1212  }
   1213 
   1214  void StreamReady(NrIceMediaStream* stream) {
   1215    ++ready_ct_;
   1216    std::cerr << name_ << " Stream ready for " << stream->name()
   1217              << " ct=" << ready_ct_ << std::endl;
   1218    DumpCandidatePairs_s(stream);
   1219  }
   1220  void StreamFailed(NrIceMediaStream* stream) {
   1221    std::cerr << name_ << " Stream failed for " << stream->name()
   1222              << " ct=" << ready_ct_ << std::endl;
   1223    DumpCandidatePairs_s(stream);
   1224  }
   1225 
   1226  void ConnectionStateChange(NrIceMediaStream* stream,
   1227                             NrIceCtx::ConnectionState state) {
   1228    {
   1229      auto lock = mConnectionStates.Lock();
   1230      lock.ref()[stream->GetId()] = state;
   1231    }
   1232    if (ice_checking()) {
   1233      ice_reached_checking_ = true;
   1234    }
   1235 
   1236    switch (state) {
   1237      case NrIceCtx::ICE_CTX_INIT:
   1238        break;
   1239      case NrIceCtx::ICE_CTX_CHECKING:
   1240        std::cerr << name_ << " ICE reached checking (" << stream->GetId()
   1241                  << ")" << std::endl;
   1242        MOZ_ASSERT(ice_reached_checking_);
   1243        break;
   1244      case NrIceCtx::ICE_CTX_CONNECTED:
   1245        std::cerr << name_ << " ICE reached connected (" << stream->GetId()
   1246                  << ")" << std::endl;
   1247        MOZ_ASSERT(ice_reached_checking_);
   1248        break;
   1249      case NrIceCtx::ICE_CTX_COMPLETED:
   1250        std::cerr << name_ << " ICE reached completed (" << stream->GetId()
   1251                  << ")" << std::endl;
   1252        MOZ_ASSERT(ice_reached_checking_);
   1253        break;
   1254      case NrIceCtx::ICE_CTX_FAILED:
   1255        std::cerr << name_ << " ICE reached failed (" << stream->GetId() << ")"
   1256                  << std::endl;
   1257        MOZ_ASSERT(ice_reached_checking_);
   1258        break;
   1259      case NrIceCtx::ICE_CTX_DISCONNECTED:
   1260        std::cerr << name_ << " ICE reached disconnected (" << stream->GetId()
   1261                  << ")" << std::endl;
   1262        MOZ_ASSERT(ice_reached_checking_);
   1263        break;
   1264      case NrIceCtx::ICE_CTX_CLOSED:
   1265        std::cerr << name_ << " ICE reached closed (" << stream->GetId() << ")"
   1266                  << std::endl;
   1267        break;
   1268    }
   1269  }
   1270 
   1271  void PacketReceived(NrIceMediaStream* stream, int component,
   1272                      const unsigned char* data, int len) {
   1273    std::cerr << name_ << ": received " << len << " bytes" << std::endl;
   1274    ++received_;
   1275  }
   1276 
   1277  void SendPacket(int stream, int component, const unsigned char* data,
   1278                  int len) {
   1279    auto media_stream = GetStream_s(stream);
   1280    if (!media_stream) {
   1281      ADD_FAILURE() << "No such stream " << stream;
   1282      return;
   1283    }
   1284 
   1285    ASSERT_TRUE(NS_SUCCEEDED(media_stream->SendPacket(component, data, len)));
   1286 
   1287    ++sent_;
   1288    std::cerr << name_ << ": sent " << len << " bytes" << std::endl;
   1289  }
   1290 
   1291  void SendFailure(int stream, int component) {
   1292    auto media_stream = GetStream_s(stream);
   1293    if (!media_stream) {
   1294      ADD_FAILURE() << "No such stream " << stream;
   1295      return;
   1296    }
   1297 
   1298    const std::string d("FAIL");
   1299    ASSERT_TRUE(NS_FAILED(media_stream->SendPacket(
   1300        component, reinterpret_cast<const unsigned char*>(d.c_str()),
   1301        d.length())));
   1302 
   1303    std::cerr << name_ << ": send failed as expected" << std::endl;
   1304  }
   1305 
   1306  void SetCandidateFilter(CandidateFilter filter) {
   1307    candidate_filter_ = filter;
   1308  }
   1309 
   1310  void ParseCandidate_s(size_t i, const std::string& candidate,
   1311                        const std::string& mdns_addr) {
   1312    auto media_stream = GetStream_s(i);
   1313    ASSERT_TRUE(media_stream.get())
   1314    << "No such stream " << i;
   1315    media_stream->ParseTrickleCandidate(candidate, "", mdns_addr);
   1316  }
   1317 
   1318  void ParseCandidate(size_t i, const std::string& candidate,
   1319                      const std::string& mdns_addr) {
   1320    test_utils_->SyncDispatchToSTS(WrapRunnable(
   1321        this, &IceTestPeer::ParseCandidate_s, i, candidate, mdns_addr));
   1322  }
   1323 
   1324  void DisableComponent_s(size_t index, int component_id) {
   1325    ASSERT_LT(index, stream_counter_);
   1326    auto stream = GetStream_s(index);
   1327    ASSERT_TRUE(stream.get())
   1328    << "No such stream " << index;
   1329    nsresult res = stream->DisableComponent(component_id);
   1330    ASSERT_TRUE(NS_SUCCEEDED(res));
   1331  }
   1332 
   1333  void DisableComponent(size_t stream, int component_id) {
   1334    test_utils_->SyncDispatchToSTS(WrapRunnable(
   1335        this, &IceTestPeer::DisableComponent_s, stream, component_id));
   1336  }
   1337 
   1338  void AssertConsentRefresh_s(size_t index, int component_id,
   1339                              ConsentStatus status) {
   1340    ASSERT_LT(index, stream_counter_);
   1341    auto stream = GetStream_s(index);
   1342    ASSERT_TRUE(stream.get())
   1343    << "No such stream " << index;
   1344    bool can_send;
   1345    struct timeval timestamp;
   1346    nsresult res =
   1347        stream->GetConsentStatus(component_id, &can_send, &timestamp);
   1348    ASSERT_TRUE(NS_SUCCEEDED(res));
   1349    if (status == CONSENT_EXPIRED) {
   1350      ASSERT_EQ(can_send, 0);
   1351    } else {
   1352      ASSERT_EQ(can_send, 1);
   1353    }
   1354    if (consent_timestamp_.tv_sec) {
   1355      if (status == CONSENT_FRESH) {
   1356        ASSERT_EQ(r_timeval_cmp(&timestamp, &consent_timestamp_), 1);
   1357      } else {
   1358        ASSERT_EQ(r_timeval_cmp(&timestamp, &consent_timestamp_), 0);
   1359      }
   1360    }
   1361    consent_timestamp_.tv_sec = timestamp.tv_sec;
   1362    consent_timestamp_.tv_usec = timestamp.tv_usec;
   1363    std::cerr << name_
   1364              << ": new consent timestamp = " << consent_timestamp_.tv_sec
   1365              << "." << consent_timestamp_.tv_usec << std::endl;
   1366  }
   1367 
   1368  void AssertConsentRefresh(ConsentStatus status) {
   1369    test_utils_->SyncDispatchToSTS(
   1370        WrapRunnable(this, &IceTestPeer::AssertConsentRefresh_s, 0, 1, status));
   1371  }
   1372 
   1373  void ChangeNetworkState_s(bool online) {
   1374    ice_ctx_->UpdateNetworkState(online);
   1375  }
   1376 
   1377  void ChangeNetworkStateToOffline() {
   1378    test_utils_->SyncDispatchToSTS(
   1379        WrapRunnable(this, &IceTestPeer::ChangeNetworkState_s, false));
   1380  }
   1381 
   1382  void ChangeNetworkStateToOnline() {
   1383    test_utils_->SyncDispatchToSTS(
   1384        WrapRunnable(this, &IceTestPeer::ChangeNetworkState_s, true));
   1385  }
   1386 
   1387  void SetControlling(NrIceCtx::Controlling controlling) {
   1388    nsresult res;
   1389    test_utils_->SyncDispatchToSTS(WrapRunnableRet(
   1390        &res, ice_ctx_, &NrIceCtx::SetControlling, controlling));
   1391    ASSERT_TRUE(NS_SUCCEEDED(res));
   1392  }
   1393 
   1394  NrIceCtx::Controlling GetControlling() { return ice_ctx_->GetControlling(); }
   1395 
   1396  void SetTiebreaker(uint64_t tiebreaker) {
   1397    test_utils_->SyncDispatchToSTS(
   1398        WrapRunnable(this, &IceTestPeer::SetTiebreaker_s, tiebreaker));
   1399  }
   1400 
   1401  void SetTiebreaker_s(uint64_t tiebreaker) {
   1402    ice_ctx_->peer()->tiebreaker = tiebreaker;
   1403  }
   1404 
   1405  void SimulateIceLite() {
   1406    simulate_ice_lite_ = true;
   1407    SetControlling(NrIceCtx::ICE_CONTROLLED);
   1408  }
   1409 
   1410  nsresult GetDefaultCandidate(unsigned int stream, NrIceCandidate* cand) {
   1411    nsresult rv;
   1412 
   1413    test_utils_->SyncDispatchToSTS(WrapRunnableRet(
   1414        &rv, this, &IceTestPeer::GetDefaultCandidate_s, stream, cand));
   1415 
   1416    return rv;
   1417  }
   1418 
   1419  nsresult GetDefaultCandidate_s(unsigned int index, NrIceCandidate* cand) {
   1420    return GetStream_s(index)->GetDefaultCandidate(1, cand);
   1421  }
   1422 
   1423 private:
   1424  std::string name_;
   1425  RefPtr<NrIceCtx> ice_ctx_;
   1426  bool offerer_;
   1427  std::map<std::string, std::vector<std::string>> candidates_;
   1428  // Maps from stream id to list of remote trickle candidates
   1429  std::map<size_t, std::vector<SchedulableTrickleCandidate*>>
   1430      controlled_trickle_candidates_;
   1431  std::map<std::string, std::pair<std::string, std::string>> mIceCredentials;
   1432  std::map<std::string, std::pair<std::string, std::string>> mOldIceCredentials;
   1433  size_t stream_counter_;
   1434  bool shutting_down_;
   1435  DataMutex<std::map<std::string, NrIceCtx::ConnectionState>> mConnectionStates;
   1436  DataMutex<std::map<std::string, NrIceMediaStream::GatheringState>>
   1437      mGatheringStates;
   1438  std::atomic<int> ready_ct_;
   1439  bool ice_reached_checking_;
   1440  std::atomic<size_t> received_;
   1441  std::atomic<size_t> sent_;
   1442  struct timeval consent_timestamp_;
   1443  NrIceResolverFake fake_resolver_;
   1444  RefPtr<NrIceResolver> dns_resolver_;
   1445  IceTestPeer* remote_;
   1446  CandidateFilter candidate_filter_;
   1447  NrIceCandidate::Type expected_local_type_;
   1448  std::string expected_local_transport_;
   1449  NrIceCandidate::Type expected_remote_type_;
   1450  std::string expected_remote_addr_;
   1451  TrickleMode trickle_mode_;
   1452  bool simulate_ice_lite_;
   1453  RefPtr<mozilla::TestNat> nat_;
   1454  MtransportTestUtils* test_utils_;
   1455 };
   1456 
   1457 void SchedulableTrickleCandidate::Trickle() {
   1458  timer_handle_ = nullptr;
   1459  nsresult res = peer_->TrickleCandidate_s(candidate_, ufrag_, stream_);
   1460  ASSERT_TRUE(NS_SUCCEEDED(res));
   1461 }
   1462 
   1463 class WebRtcIceGatherTest : public StunTest {
   1464 public:
   1465  void SetUp() override {
   1466    StunTest::SetUp();
   1467 
   1468    Preferences::SetInt("media.peerconnection.ice.tcp_so_sock_count", 3);
   1469 
   1470    test_utils_->SyncDispatchToSTS(WrapRunnable(
   1471        TestStunServer::GetInstance(AF_INET), &TestStunServer::Reset));
   1472    if (TestStunServer::GetInstance(AF_INET6)) {
   1473      test_utils_->SyncDispatchToSTS(WrapRunnable(
   1474          TestStunServer::GetInstance(AF_INET6), &TestStunServer::Reset));
   1475    }
   1476  }
   1477 
   1478  void TearDown() override {
   1479    peer_ = nullptr;
   1480    StunTest::TearDown();
   1481  }
   1482 
   1483  void EnsurePeer() {
   1484    if (!peer_) {
   1485      peer_ =
   1486          MakeUnique<IceTestPeer>("P1", test_utils_, true, NrIceCtx::Config());
   1487    }
   1488  }
   1489 
   1490  void Gather(unsigned int waitTime = kDefaultTimeout,
   1491              bool default_route_only = false,
   1492              bool obfuscate_host_addresses = false) {
   1493    EnsurePeer();
   1494    peer_->Gather(default_route_only, obfuscate_host_addresses);
   1495 
   1496    if (waitTime) {
   1497      WaitForGather(waitTime);
   1498    }
   1499  }
   1500 
   1501  void WaitForGather(unsigned int waitTime = kDefaultTimeout) {
   1502    ASSERT_TRUE_WAIT(peer_->gathering_complete(), waitTime);
   1503  }
   1504 
   1505  void AddStunServerWithResponse(const std::string& fake_addr,
   1506                                 uint16_t fake_port, const std::string& fqdn,
   1507                                 const std::string& proto,
   1508                                 std::vector<NrIceStunServer>* stun_servers) {
   1509    int family;
   1510    if (fake_addr.find(':') != std::string::npos) {
   1511      family = AF_INET6;
   1512    } else {
   1513      family = AF_INET;
   1514    }
   1515 
   1516    std::string stun_addr;
   1517    uint16_t stun_port;
   1518    if (proto == kNrIceTransportUdp) {
   1519      TestStunServer::GetInstance(family)->SetResponseAddr(fake_addr,
   1520                                                           fake_port);
   1521      stun_addr = TestStunServer::GetInstance(family)->addr();
   1522      stun_port = TestStunServer::GetInstance(family)->port();
   1523    } else if (proto == kNrIceTransportTcp) {
   1524      TestStunTcpServer::GetInstance(family)->SetResponseAddr(fake_addr,
   1525                                                              fake_port);
   1526      stun_addr = TestStunTcpServer::GetInstance(family)->addr();
   1527      stun_port = TestStunTcpServer::GetInstance(family)->port();
   1528    } else {
   1529      MOZ_CRASH();
   1530    }
   1531 
   1532    if (!fqdn.empty()) {
   1533      peer_->SetFakeResolver(stun_addr, fqdn);
   1534      stun_addr = fqdn;
   1535    }
   1536 
   1537    stun_servers->push_back(
   1538        *NrIceStunServer::Create(stun_addr, stun_port, proto.c_str()));
   1539 
   1540    if (family == AF_INET6 && !fqdn.empty()) {
   1541      stun_servers->back().SetUseIPv6IfFqdn();
   1542    }
   1543  }
   1544 
   1545  void UseFakeStunUdpServerWithResponse(
   1546      const std::string& fake_addr, uint16_t fake_port,
   1547      const std::string& fqdn = std::string()) {
   1548    EnsurePeer();
   1549    std::vector<NrIceStunServer> stun_servers;
   1550    AddStunServerWithResponse(fake_addr, fake_port, fqdn, "udp", &stun_servers);
   1551    peer_->SetStunServers(stun_servers);
   1552  }
   1553 
   1554  void UseFakeStunTcpServerWithResponse(
   1555      const std::string& fake_addr, uint16_t fake_port,
   1556      const std::string& fqdn = std::string()) {
   1557    EnsurePeer();
   1558    std::vector<NrIceStunServer> stun_servers;
   1559    AddStunServerWithResponse(fake_addr, fake_port, fqdn, "tcp", &stun_servers);
   1560    peer_->SetStunServers(stun_servers);
   1561  }
   1562 
   1563  void UseFakeStunUdpTcpServersWithResponse(const std::string& fake_udp_addr,
   1564                                            uint16_t fake_udp_port,
   1565                                            const std::string& fake_tcp_addr,
   1566                                            uint16_t fake_tcp_port) {
   1567    EnsurePeer();
   1568    std::vector<NrIceStunServer> stun_servers;
   1569    AddStunServerWithResponse(fake_udp_addr, fake_udp_port,
   1570                              "",  // no fqdn
   1571                              "udp", &stun_servers);
   1572    AddStunServerWithResponse(fake_tcp_addr, fake_tcp_port,
   1573                              "",  // no fqdn
   1574                              "tcp", &stun_servers);
   1575 
   1576    peer_->SetStunServers(stun_servers);
   1577  }
   1578 
   1579  void UseTestStunServer() {
   1580    TestStunServer::GetInstance(AF_INET)->Reset();
   1581    peer_->SetStunServer(TestStunServer::GetInstance(AF_INET)->addr(),
   1582                         TestStunServer::GetInstance(AF_INET)->port());
   1583  }
   1584 
   1585  // NB: Only does substring matching, watch out for stuff like "1.2.3.4"
   1586  // matching "21.2.3.47". " 1.2.3.4 " should not have false positives.
   1587  bool StreamHasMatchingCandidate(unsigned int stream, const std::string& match,
   1588                                  const std::string& match2 = "") {
   1589    std::vector<std::string> attributes = peer_->GetAttributes(stream);
   1590    for (auto& attribute : attributes) {
   1591      if (std::string::npos != attribute.find(match)) {
   1592        if (!match2.length() || std::string::npos != attribute.find(match2)) {
   1593          return true;
   1594        }
   1595      }
   1596    }
   1597    return false;
   1598  }
   1599 
   1600  void DumpAttributes(unsigned int stream) {
   1601    std::vector<std::string> attributes = peer_->GetAttributes(stream);
   1602 
   1603    std::cerr << "Attributes for stream " << stream << "->" << attributes.size()
   1604              << std::endl;
   1605 
   1606    for (const auto& a : attributes) {
   1607      std::cerr << "Attribute: " << a << std::endl;
   1608    }
   1609  }
   1610 
   1611 protected:
   1612  mozilla::UniquePtr<IceTestPeer> peer_;
   1613 };
   1614 
   1615 class WebRtcIceConnectTest : public StunTest {
   1616 public:
   1617  WebRtcIceConnectTest()
   1618      : initted_(false),
   1619        test_stun_server_inited_(false),
   1620        use_nat_(false),
   1621        filtering_type_(TestNat::ENDPOINT_INDEPENDENT),
   1622        mapping_type_(TestNat::ENDPOINT_INDEPENDENT),
   1623        block_udp_(false) {}
   1624 
   1625  void SetUp() override {
   1626    StunTest::SetUp();
   1627 
   1628    nsresult rv;
   1629    target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
   1630    ASSERT_TRUE(NS_SUCCEEDED(rv));
   1631  }
   1632 
   1633  void TearDown() override {
   1634    p1_ = nullptr;
   1635    p2_ = nullptr;
   1636 
   1637    StunTest::TearDown();
   1638  }
   1639 
   1640  void AddStream(int components) {
   1641    Init();
   1642    p1_->AddStream(components);
   1643    p2_->AddStream(components);
   1644  }
   1645 
   1646  void RemoveStream(size_t index) {
   1647    p1_->RemoveStream(index);
   1648    p2_->RemoveStream(index);
   1649  }
   1650 
   1651  void Init(bool setup_stun_servers = true,
   1652            NrIceCtx::Config config = NrIceCtx::Config()) {
   1653    if (initted_) {
   1654      return;
   1655    }
   1656 
   1657    p1_ = MakeUnique<IceTestPeer>("P1", test_utils_, true, config);
   1658    p2_ = MakeUnique<IceTestPeer>("P2", test_utils_, false, config);
   1659    InitPeer(p1_.get(), setup_stun_servers);
   1660    InitPeer(p2_.get(), setup_stun_servers);
   1661 
   1662    initted_ = true;
   1663  }
   1664 
   1665  void InitPeer(IceTestPeer* peer, bool setup_stun_servers = true) {
   1666    if (use_nat_) {
   1667      // If we enable nat simulation, but still use a real STUN server somewhere
   1668      // on the internet, we will see failures if there is a real NAT in
   1669      // addition to our simulated one, particularly if it disallows
   1670      // hairpinning.
   1671      if (setup_stun_servers) {
   1672        InitTestStunServer();
   1673        peer->UseTestStunServer();
   1674      }
   1675      peer->UseNat();
   1676      peer->SetFilteringType(filtering_type_);
   1677      peer->SetMappingType(mapping_type_);
   1678      peer->SetBlockUdp(block_udp_);
   1679    } else if (setup_stun_servers) {
   1680      if (stun_server_address_.empty()) {
   1681        InitTestStunServer();
   1682        peer->UseTestStunServer();
   1683      } else {
   1684        std::vector<NrIceStunServer> stun_servers;
   1685 
   1686        stun_servers.push_back(*NrIceStunServer::Create(
   1687            stun_server_address_, kDefaultStunServerPort, kNrIceTransportUdp));
   1688 
   1689        peer->SetStunServers(stun_servers);
   1690      }
   1691    }
   1692  }
   1693 
   1694  bool Gather(unsigned int waitTime = kDefaultTimeout,
   1695              bool default_route_only = false) {
   1696    Init();
   1697 
   1698    return GatherCallerAndCallee(p1_.get(), p2_.get(), waitTime,
   1699                                 default_route_only);
   1700  }
   1701 
   1702  bool GatherCallerAndCallee(IceTestPeer* caller, IceTestPeer* callee,
   1703                             unsigned int waitTime = kDefaultTimeout,
   1704                             bool default_route_only = false) {
   1705    caller->Gather(default_route_only);
   1706    callee->Gather(default_route_only);
   1707 
   1708    if (waitTime) {
   1709      EXPECT_TRUE_WAIT(caller->gathering_complete(), waitTime);
   1710      if (!caller->gathering_complete()) return false;
   1711      EXPECT_TRUE_WAIT(callee->gathering_complete(), waitTime);
   1712      if (!callee->gathering_complete()) return false;
   1713    }
   1714    return true;
   1715  }
   1716 
   1717  void UseNat() {
   1718    // to be useful, this method should be called before Init
   1719    ASSERT_FALSE(initted_);
   1720    use_nat_ = true;
   1721  }
   1722 
   1723  void SetFilteringType(TestNat::NatBehavior type) {
   1724    // to be useful, this method should be called before Init
   1725    ASSERT_FALSE(initted_);
   1726    filtering_type_ = type;
   1727  }
   1728 
   1729  void SetMappingType(TestNat::NatBehavior type) {
   1730    // to be useful, this method should be called before Init
   1731    ASSERT_FALSE(initted_);
   1732    mapping_type_ = type;
   1733  }
   1734 
   1735  void BlockUdp() {
   1736    // note: |block_udp_| is used only in InitPeer.
   1737    // Use IceTestPeer::SetBlockUdp to act on the peer directly.
   1738    block_udp_ = true;
   1739  }
   1740 
   1741  void SetupAndCheckConsent() {
   1742    p1_->SetTimerDivider(10);
   1743    p2_->SetTimerDivider(10);
   1744    ASSERT_TRUE(Gather());
   1745    Connect();
   1746    p1_->AssertConsentRefresh(CONSENT_FRESH);
   1747    p2_->AssertConsentRefresh(CONSENT_FRESH);
   1748    SendReceive();
   1749  }
   1750 
   1751  void AssertConsentRefresh(ConsentStatus status = CONSENT_FRESH) {
   1752    p1_->AssertConsentRefresh(status);
   1753    p2_->AssertConsentRefresh(status);
   1754  }
   1755 
   1756  void InitTestStunServer() {
   1757    if (test_stun_server_inited_) {
   1758      return;
   1759    }
   1760 
   1761    std::cerr << "Resetting TestStunServer" << std::endl;
   1762    TestStunServer::GetInstance(AF_INET)->Reset();
   1763    test_stun_server_inited_ = true;
   1764  }
   1765 
   1766  void UseTestStunServer() {
   1767    InitTestStunServer();
   1768    p1_->UseTestStunServer();
   1769    p2_->UseTestStunServer();
   1770  }
   1771 
   1772  void SetTurnServer(const std::string addr, uint16_t port,
   1773                     const std::string username, const std::string password,
   1774                     const char* transport = kNrIceTransportUdp) {
   1775    p1_->SetTurnServer(addr, port, username, password, transport);
   1776    p2_->SetTurnServer(addr, port, username, password, transport);
   1777  }
   1778 
   1779  void SetTurnServers(const std::vector<NrIceTurnServer>& servers) {
   1780    p1_->SetTurnServers(servers);
   1781    p2_->SetTurnServers(servers);
   1782  }
   1783 
   1784  void SetCandidateFilter(CandidateFilter filter, bool both = true) {
   1785    p1_->SetCandidateFilter(filter);
   1786    if (both) {
   1787      p2_->SetCandidateFilter(filter);
   1788    }
   1789  }
   1790 
   1791  void Connect() { ConnectCallerAndCallee(p1_.get(), p2_.get()); }
   1792 
   1793  void ConnectCallerAndCallee(IceTestPeer* caller, IceTestPeer* callee,
   1794                              TrickleMode mode = TRICKLE_NONE) {
   1795    ASSERT_TRUE(caller->ready_ct() == 0);
   1796    ASSERT_TRUE(caller->ice_connected() == 0);
   1797    ASSERT_TRUE(callee->ready_ct() == 0);
   1798    ASSERT_TRUE(callee->ice_connected() == 0);
   1799 
   1800    // IceTestPeer::Connect grabs attributes from the first arg, and
   1801    // gives them to |this|, meaning that callee->Connect(caller, ...)
   1802    // simulates caller sending an offer to callee. Order matters here
   1803    // because it determines which peer is controlling.
   1804    callee->Connect(caller, mode);
   1805    caller->Connect(callee, mode);
   1806 
   1807    if (mode != TRICKLE_SIMULATE) {
   1808      ASSERT_TRUE_WAIT(caller->ice_connected() && callee->ice_connected(),
   1809                       kDefaultTimeout);
   1810      ASSERT_TRUE(caller->ready_ct() >= 1 && callee->ready_ct() >= 1);
   1811      ASSERT_TRUE(caller->ice_reached_checking());
   1812      ASSERT_TRUE(callee->ice_reached_checking());
   1813 
   1814      caller->DumpAndCheckActiveCandidates();
   1815      callee->DumpAndCheckActiveCandidates();
   1816    }
   1817  }
   1818 
   1819  void SetExpectedTypes(NrIceCandidate::Type local, NrIceCandidate::Type remote,
   1820                        std::string transport = kNrIceTransportUdp) {
   1821    p1_->SetExpectedTypes(local, remote, transport);
   1822    p2_->SetExpectedTypes(local, remote, transport);
   1823  }
   1824 
   1825  void SetExpectedRemoteCandidateAddr(const std::string& addr) {
   1826    p1_->SetExpectedRemoteCandidateAddr(addr);
   1827    p2_->SetExpectedRemoteCandidateAddr(addr);
   1828  }
   1829 
   1830  void ConnectP1(TrickleMode mode = TRICKLE_NONE) {
   1831    p1_->Connect(p2_.get(), mode);
   1832  }
   1833 
   1834  void ConnectP2(TrickleMode mode = TRICKLE_NONE) {
   1835    p2_->Connect(p1_.get(), mode);
   1836  }
   1837 
   1838  void WaitForConnectedStreams(int expected_streams = 1) {
   1839    ASSERT_TRUE_WAIT(p1_->ready_ct() == expected_streams &&
   1840                         p2_->ready_ct() == expected_streams,
   1841                     kDefaultTimeout);
   1842    ASSERT_TRUE_WAIT(p1_->ice_connected() && p2_->ice_connected(),
   1843                     kDefaultTimeout);
   1844  }
   1845 
   1846  void AssertCheckingReached() {
   1847    ASSERT_TRUE(p1_->ice_reached_checking());
   1848    ASSERT_TRUE(p2_->ice_reached_checking());
   1849  }
   1850 
   1851  void WaitForConnected(unsigned int timeout = kDefaultTimeout) {
   1852    ASSERT_TRUE_WAIT(p1_->ice_connected(), timeout);
   1853    ASSERT_TRUE_WAIT(p2_->ice_connected(), timeout);
   1854  }
   1855 
   1856  void WaitForGather() {
   1857    ASSERT_TRUE_WAIT(p1_->gathering_complete(), kDefaultTimeout);
   1858    ASSERT_TRUE_WAIT(p2_->gathering_complete(), kDefaultTimeout);
   1859  }
   1860 
   1861  void WaitForDisconnected(unsigned int timeout = kDefaultTimeout) {
   1862    ASSERT_TRUE(p1_->ice_connected());
   1863    ASSERT_TRUE(p2_->ice_connected());
   1864    ASSERT_TRUE_WAIT(p1_->ice_connected() == 0 && p2_->ice_connected() == 0,
   1865                     timeout);
   1866  }
   1867 
   1868  void WaitForFailed(unsigned int timeout = kDefaultTimeout) {
   1869    ASSERT_TRUE_WAIT(p1_->ice_failed() && p2_->ice_failed(), timeout);
   1870  }
   1871 
   1872  void ConnectTrickle(TrickleMode trickle = TRICKLE_SIMULATE) {
   1873    p2_->Connect(p1_.get(), trickle);
   1874    p1_->Connect(p2_.get(), trickle);
   1875  }
   1876 
   1877  void SimulateTrickle(size_t stream) {
   1878    p1_->SimulateTrickle(stream);
   1879    p2_->SimulateTrickle(stream);
   1880    ASSERT_TRUE_WAIT(p1_->is_ready(stream), kDefaultTimeout);
   1881    ASSERT_TRUE_WAIT(p2_->is_ready(stream), kDefaultTimeout);
   1882  }
   1883 
   1884  void SimulateTrickleP1(size_t stream) { p1_->SimulateTrickle(stream); }
   1885 
   1886  void SimulateTrickleP2(size_t stream) { p2_->SimulateTrickle(stream); }
   1887 
   1888  void CloseP1() { p1_->Close(); }
   1889 
   1890  void ConnectThenDelete() {
   1891    p2_->Connect(p1_.get(), TRICKLE_NONE, false);
   1892    p1_->Connect(p2_.get(), TRICKLE_NONE, true);
   1893    test_utils_->SyncDispatchToSTS(
   1894        WrapRunnable(this, &WebRtcIceConnectTest::CloseP1));
   1895    p2_->StartChecks();
   1896 
   1897    // Wait to see if we crash
   1898    PR_Sleep(PR_MillisecondsToInterval(kDefaultTimeout));
   1899  }
   1900 
   1901  // default is p1_ sending to p2_
   1902  void SendReceive() { SendReceive(p1_.get(), p2_.get()); }
   1903 
   1904  void SendReceive(IceTestPeer* p1, IceTestPeer* p2,
   1905                   bool expect_tx_failure = false,
   1906                   bool expect_rx_failure = false) {
   1907    size_t previousSent = p1->sent();
   1908    size_t previousReceived = p2->received();
   1909 
   1910    if (expect_tx_failure) {
   1911      test_utils_->SyncDispatchToSTS(
   1912          WrapRunnable(p1, &IceTestPeer::SendFailure, 0, 1));
   1913      ASSERT_EQ(previousSent, p1->sent());
   1914    } else {
   1915      test_utils_->SyncDispatchToSTS(
   1916          WrapRunnable(p1, &IceTestPeer::SendPacket, 0, 1,
   1917                       reinterpret_cast<const unsigned char*>("TEST"), 4));
   1918      ASSERT_EQ(previousSent + 1, p1->sent());
   1919    }
   1920    if (expect_rx_failure) {
   1921      usleep(1000);
   1922      ASSERT_EQ(previousReceived, p2->received());
   1923    } else {
   1924      ASSERT_TRUE_WAIT(p2->received() == previousReceived + 1, 1000);
   1925    }
   1926  }
   1927 
   1928  void SendFailure() {
   1929    test_utils_->SyncDispatchToSTS(
   1930        WrapRunnable(p1_.get(), &IceTestPeer::SendFailure, 0, 1));
   1931  }
   1932 
   1933 protected:
   1934  bool initted_;
   1935  bool test_stun_server_inited_;
   1936  nsCOMPtr<nsIEventTarget> target_;
   1937  mozilla::UniquePtr<IceTestPeer> p1_;
   1938  mozilla::UniquePtr<IceTestPeer> p2_;
   1939  bool use_nat_;
   1940  TestNat::NatBehavior filtering_type_;
   1941  TestNat::NatBehavior mapping_type_;
   1942  bool block_udp_;
   1943 };
   1944 
   1945 class WebRtcIcePrioritizerTest : public StunTest {
   1946 public:
   1947  WebRtcIcePrioritizerTest() : prioritizer_(nullptr) {}
   1948 
   1949  ~WebRtcIcePrioritizerTest() {
   1950    if (prioritizer_) {
   1951      nr_interface_prioritizer_destroy(&prioritizer_);
   1952    }
   1953  }
   1954 
   1955  void SetPriorizer(nr_interface_prioritizer* prioritizer) {
   1956    prioritizer_ = prioritizer;
   1957  }
   1958 
   1959  void AddInterface(const std::string& num, int type, int estimated_speed) {
   1960    std::string str_addr = "10.0.0." + num;
   1961    std::string ifname = "eth" + num;
   1962    nr_local_addr local_addr;
   1963    local_addr.iface.type = type;
   1964    local_addr.iface.estimated_speed = estimated_speed;
   1965 
   1966    int r = nr_str_port_to_transport_addr(str_addr.c_str(), 0, IPPROTO_UDP,
   1967                                          &(local_addr.addr));
   1968    ASSERT_EQ(0, r);
   1969    strncpy(local_addr.addr.ifname, ifname.c_str(), MAXIFNAME - 1);
   1970    local_addr.addr.ifname[MAXIFNAME - 1] = '\0';
   1971 
   1972    r = nr_interface_prioritizer_add_interface(prioritizer_, &local_addr);
   1973    ASSERT_EQ(0, r);
   1974    r = nr_interface_prioritizer_sort_preference(prioritizer_);
   1975    ASSERT_EQ(0, r);
   1976  }
   1977 
   1978  void HasLowerPreference(const std::string& num1, const std::string& num2) {
   1979    std::string key1 = "eth" + num1 + ":10.0.0." + num1;
   1980    std::string key2 = "eth" + num2 + ":10.0.0." + num2;
   1981    UCHAR pref1, pref2;
   1982    int r = nr_interface_prioritizer_get_priority(prioritizer_, key1.c_str(),
   1983                                                  &pref1);
   1984    ASSERT_EQ(0, r);
   1985    r = nr_interface_prioritizer_get_priority(prioritizer_, key2.c_str(),
   1986                                              &pref2);
   1987    ASSERT_EQ(0, r);
   1988    ASSERT_LE(pref1, pref2);
   1989  }
   1990 
   1991 private:
   1992  nr_interface_prioritizer* prioritizer_;
   1993 };
   1994 
   1995 class WebRtcIcePacketFilterTest : public StunTest {
   1996 public:
   1997  WebRtcIcePacketFilterTest() : udp_filter_(nullptr), tcp_filter_(nullptr) {}
   1998 
   1999  void SetUp() {
   2000    StunTest::SetUp();
   2001 
   2002    test_utils_->SyncDispatchToSTS(
   2003        WrapRunnable(this, &WebRtcIcePacketFilterTest::SetUp_s));
   2004 
   2005    nsCOMPtr<nsISocketFilterHandler> udp_handler =
   2006        do_GetService(NS_STUN_UDP_SOCKET_FILTER_HANDLER_CONTRACTID);
   2007    ASSERT_TRUE(udp_handler);
   2008    udp_handler->NewFilter(getter_AddRefs(udp_filter_));
   2009 
   2010    nsCOMPtr<nsISocketFilterHandler> tcp_handler =
   2011        do_GetService(NS_STUN_TCP_SOCKET_FILTER_HANDLER_CONTRACTID);
   2012    ASSERT_TRUE(tcp_handler);
   2013    tcp_handler->NewFilter(getter_AddRefs(tcp_filter_));
   2014  }
   2015 
   2016  void SetUp_s() {
   2017    NrIceCtx::InitializeGlobals(NrIceCtx::GlobalConfig());
   2018    // Set up enough of the ICE ctx to allow the packet filter to work
   2019    ice_ctx_ = NrIceCtx::Create("test");
   2020  }
   2021 
   2022  void TearDown() {
   2023    test_utils_->SyncDispatchToSTS(
   2024        WrapRunnable(this, &WebRtcIcePacketFilterTest::TearDown_s));
   2025    StunTest::TearDown();
   2026  }
   2027 
   2028  void TearDown_s() { ice_ctx_ = nullptr; }
   2029 
   2030  void TestIncoming(const uint8_t* data, uint32_t len, uint8_t from_addr,
   2031                    int from_port, bool expected_result) {
   2032    mozilla::net::NetAddr addr;
   2033    MakeNetAddr(&addr, from_addr, from_port);
   2034    bool result;
   2035    nsresult rv = udp_filter_->FilterPacket(
   2036        &addr, data, len, nsISocketFilter::SF_INCOMING, &result);
   2037    ASSERT_EQ(NS_OK, rv);
   2038    ASSERT_EQ(expected_result, result);
   2039  }
   2040 
   2041  void TestIncomingTcp(const uint8_t* data, uint32_t len,
   2042                       bool expected_result) {
   2043    mozilla::net::NetAddr addr;
   2044    bool result;
   2045    nsresult rv = tcp_filter_->FilterPacket(
   2046        &addr, data, len, nsISocketFilter::SF_INCOMING, &result);
   2047    ASSERT_EQ(NS_OK, rv);
   2048    ASSERT_EQ(expected_result, result);
   2049  }
   2050 
   2051  void TestIncomingTcpFramed(const uint8_t* data, uint32_t len,
   2052                             bool expected_result) {
   2053    mozilla::net::NetAddr addr;
   2054    bool result;
   2055    uint8_t* framed_data = new uint8_t[len + 2];
   2056    framed_data[0] = htons(len);
   2057    memcpy(&framed_data[2], data, len);
   2058    nsresult rv = tcp_filter_->FilterPacket(
   2059        &addr, framed_data, len + 2, nsISocketFilter::SF_INCOMING, &result);
   2060    ASSERT_EQ(NS_OK, rv);
   2061    ASSERT_EQ(expected_result, result);
   2062    delete[] framed_data;
   2063  }
   2064 
   2065  void TestOutgoing(const uint8_t* data, uint32_t len, uint8_t to_addr,
   2066                    int to_port, bool expected_result) {
   2067    mozilla::net::NetAddr addr;
   2068    MakeNetAddr(&addr, to_addr, to_port);
   2069    bool result;
   2070    nsresult rv = udp_filter_->FilterPacket(
   2071        &addr, data, len, nsISocketFilter::SF_OUTGOING, &result);
   2072    ASSERT_EQ(NS_OK, rv);
   2073    ASSERT_EQ(expected_result, result);
   2074  }
   2075 
   2076  void TestOutgoingTcp(const uint8_t* data, uint32_t len,
   2077                       bool expected_result) {
   2078    mozilla::net::NetAddr addr;
   2079    bool result;
   2080    nsresult rv = tcp_filter_->FilterPacket(
   2081        &addr, data, len, nsISocketFilter::SF_OUTGOING, &result);
   2082    ASSERT_EQ(NS_OK, rv);
   2083    ASSERT_EQ(expected_result, result);
   2084  }
   2085 
   2086  void TestOutgoingTcpFramed(const uint8_t* data, uint32_t len,
   2087                             bool expected_result) {
   2088    mozilla::net::NetAddr addr;
   2089    bool result;
   2090    uint8_t* framed_data = new uint8_t[len + 2];
   2091    framed_data[0] = htons(len);
   2092    memcpy(&framed_data[2], data, len);
   2093    nsresult rv = tcp_filter_->FilterPacket(
   2094        &addr, framed_data, len + 2, nsISocketFilter::SF_OUTGOING, &result);
   2095    ASSERT_EQ(NS_OK, rv);
   2096    ASSERT_EQ(expected_result, result);
   2097    delete[] framed_data;
   2098  }
   2099 
   2100 private:
   2101  void MakeNetAddr(mozilla::net::NetAddr* net_addr, uint8_t last_digit,
   2102                   uint16_t port) {
   2103    net_addr->inet.family = AF_INET;
   2104    net_addr->inet.ip = 192 << 24 | 168 << 16 | 1 << 8 | last_digit;
   2105    net_addr->inet.port = port;
   2106  }
   2107 
   2108  nsCOMPtr<nsISocketFilter> udp_filter_;
   2109  nsCOMPtr<nsISocketFilter> tcp_filter_;
   2110  RefPtr<NrIceCtx> ice_ctx_;
   2111 };
   2112 }  // end namespace
   2113 
   2114 TEST_F(WebRtcIceGatherTest, TestGatherFakeStunServerHostnameNoResolver) {
   2115  if (stun_server_hostname_.empty()) {
   2116    return;
   2117  }
   2118 
   2119  NrIceCtx::GlobalConfig globalConfig;
   2120  globalConfig.mTcpEnabled = false;
   2121  NrIceCtx::InitializeGlobals(globalConfig);
   2122  EnsurePeer();
   2123  peer_->SetStunServer(stun_server_hostname_, kDefaultStunServerPort);
   2124  peer_->AddStream(1);
   2125  Gather();
   2126 }
   2127 
   2128 // Disabled because google isn't running any TCP stun servers right now
   2129 TEST_F(WebRtcIceGatherTest,
   2130       DISABLED_TestGatherFakeStunServerTcpHostnameNoResolver) {
   2131  if (stun_server_hostname_.empty()) {
   2132    return;
   2133  }
   2134 
   2135  NrIceCtx::GlobalConfig config;
   2136  config.mTcpEnabled = true;
   2137  NrIceCtx::InitializeGlobals(config);
   2138  EnsurePeer();
   2139  peer_->SetStunServer(stun_server_hostname_, kDefaultStunServerPort,
   2140                       kNrIceTransportTcp);
   2141  peer_->AddStream(1);
   2142  Gather();
   2143  ASSERT_TRUE(StreamHasMatchingCandidate(0, " TCP "));
   2144 }
   2145 
   2146 TEST_F(WebRtcIceGatherTest, TestGatherFakeStunServerIpAddress) {
   2147  if (stun_server_address_.empty()) {
   2148    return;
   2149  }
   2150 
   2151  NrIceCtx::GlobalConfig config;
   2152  config.mTcpEnabled = false;
   2153  NrIceCtx::InitializeGlobals(config);
   2154  EnsurePeer();
   2155  peer_->SetStunServer(stun_server_address_, kDefaultStunServerPort);
   2156  peer_->SetFakeResolver(stun_server_address_, stun_server_hostname_);
   2157  peer_->AddStream(1);
   2158  Gather();
   2159 }
   2160 
   2161 TEST_F(WebRtcIceGatherTest, TestGatherStunServerIpAddressNoHost) {
   2162  if (stun_server_address_.empty()) {
   2163    return;
   2164  }
   2165 
   2166  {
   2167    NrIceCtx::GlobalConfig config;
   2168    config.mTcpEnabled = false;
   2169    NrIceCtx::InitializeGlobals(config);
   2170  }
   2171 
   2172  NrIceCtx::Config config;
   2173  config.mPolicy = NrIceCtx::ICE_POLICY_NO_HOST;
   2174  peer_ = MakeUnique<IceTestPeer>("P1", test_utils_, true, config);
   2175  peer_->AddStream(1);
   2176  peer_->SetStunServer(stun_server_address_, kDefaultStunServerPort);
   2177  peer_->SetFakeResolver(stun_server_address_, stun_server_hostname_);
   2178  Gather();
   2179  ASSERT_FALSE(StreamHasMatchingCandidate(0, " host "));
   2180 }
   2181 
   2182 TEST_F(WebRtcIceGatherTest, TestGatherFakeStunServerHostname) {
   2183  if (stun_server_hostname_.empty()) {
   2184    return;
   2185  }
   2186 
   2187  NrIceCtx::GlobalConfig config;
   2188  config.mTcpEnabled = false;
   2189  NrIceCtx::InitializeGlobals(config);
   2190  EnsurePeer();
   2191  peer_->SetStunServer(stun_server_hostname_, kDefaultStunServerPort);
   2192  peer_->SetFakeResolver(stun_server_address_, stun_server_hostname_);
   2193  peer_->AddStream(1);
   2194  Gather();
   2195 }
   2196 
   2197 TEST_F(WebRtcIceGatherTest, TestGatherFakeStunBogusHostname) {
   2198  NrIceCtx::GlobalConfig config;
   2199  config.mTcpEnabled = false;
   2200  NrIceCtx::InitializeGlobals(config);
   2201  EnsurePeer();
   2202  peer_->SetStunServer(kBogusStunServerHostname, kDefaultStunServerPort);
   2203  peer_->SetFakeResolver(stun_server_address_, stun_server_hostname_);
   2204  peer_->AddStream(1);
   2205  Gather();
   2206 }
   2207 
   2208 TEST_F(WebRtcIceGatherTest, TestGatherDNSStunServerIpAddress) {
   2209  if (stun_server_address_.empty()) {
   2210    return;
   2211  }
   2212 
   2213  {
   2214    NrIceCtx::GlobalConfig config;
   2215    config.mTcpEnabled = false;
   2216    NrIceCtx::InitializeGlobals(config);
   2217  }
   2218 
   2219  // A srflx candidate is considered redundant and discarded if its address
   2220  // equals that of a host candidate. (Frequently, a srflx candidate and a host
   2221  // candidate have equal addresses when the agent is not behind a NAT.) So set
   2222  // ICE_POLICY_NO_HOST here to ensure that a srflx candidate is not falsely
   2223  // discarded in this test.
   2224  NrIceCtx::Config config;
   2225  config.mPolicy = NrIceCtx::ICE_POLICY_NO_HOST;
   2226  peer_ = MakeUnique<IceTestPeer>("P1", test_utils_, true, config);
   2227 
   2228  peer_->SetStunServer(stun_server_address_, kDefaultStunServerPort);
   2229  peer_->SetDNSResolver();
   2230  peer_->AddStream(1);
   2231  Gather();
   2232  ASSERT_TRUE(StreamHasMatchingCandidate(0, " UDP "));
   2233  ASSERT_TRUE(StreamHasMatchingCandidate(0, "typ srflx raddr"));
   2234 }
   2235 
   2236 // Disabled because google isn't running any TCP stun servers right now
   2237 TEST_F(WebRtcIceGatherTest, DISABLED_TestGatherDNSStunServerIpAddressTcp) {
   2238  if (stun_server_address_.empty()) {
   2239    return;
   2240  }
   2241 
   2242  NrIceCtx::GlobalConfig config;
   2243  config.mTcpEnabled = true;
   2244  NrIceCtx::InitializeGlobals(config);
   2245  EnsurePeer();
   2246  peer_->SetStunServer(stun_server_address_, kDefaultStunServerPort,
   2247                       kNrIceTransportTcp);
   2248  peer_->SetDNSResolver();
   2249  peer_->AddStream(1);
   2250  Gather();
   2251  ASSERT_TRUE(StreamHasMatchingCandidate(0, "tcptype passive"));
   2252  ASSERT_FALSE(StreamHasMatchingCandidate(0, "tcptype passive", " 9 "));
   2253  ASSERT_TRUE(StreamHasMatchingCandidate(0, "tcptype so"));
   2254  ASSERT_FALSE(StreamHasMatchingCandidate(0, "tcptype so", " 9 "));
   2255  ASSERT_TRUE(StreamHasMatchingCandidate(0, "tcptype active", " 9 "));
   2256 }
   2257 
   2258 TEST_F(WebRtcIceGatherTest, TestGatherDNSStunServerHostname) {
   2259  if (stun_server_hostname_.empty()) {
   2260    return;
   2261  }
   2262 
   2263  {
   2264    NrIceCtx::GlobalConfig config;
   2265    config.mTcpEnabled = false;
   2266    NrIceCtx::InitializeGlobals(config);
   2267  }
   2268 
   2269  // A srflx candidate is considered redundant and discarded if its address
   2270  // equals that of a host candidate. (Frequently, a srflx candidate and a host
   2271  // candidate have equal addresses when the agent is not behind a NAT.) So set
   2272  // ICE_POLICY_NO_HOST here to ensure that a srflx candidate is not falsely
   2273  // discarded in this test.
   2274  NrIceCtx::Config config;
   2275  config.mPolicy = NrIceCtx::ICE_POLICY_NO_HOST;
   2276  peer_ = MakeUnique<IceTestPeer>("P1", test_utils_, true, config);
   2277 
   2278  peer_->SetStunServer(stun_server_hostname_, kDefaultStunServerPort);
   2279  peer_->SetDNSResolver();
   2280  peer_->AddStream(1);
   2281  Gather();
   2282  ASSERT_TRUE(StreamHasMatchingCandidate(0, " UDP "));
   2283  ASSERT_TRUE(StreamHasMatchingCandidate(0, "typ srflx raddr"));
   2284 }
   2285 
   2286 // Disabled because google isn't running any TCP stun servers right now
   2287 TEST_F(WebRtcIceGatherTest, DISABLED_TestGatherDNSStunServerHostnameTcp) {
   2288  NrIceCtx::GlobalConfig config;
   2289  config.mTcpEnabled = true;
   2290  NrIceCtx::InitializeGlobals(config);
   2291  EnsurePeer();
   2292  peer_->SetStunServer(stun_server_hostname_, kDefaultStunServerPort,
   2293                       kNrIceTransportTcp);
   2294  peer_->SetDNSResolver();
   2295  peer_->AddStream(1);
   2296  Gather();
   2297  ASSERT_TRUE(StreamHasMatchingCandidate(0, "tcptype passive"));
   2298  ASSERT_FALSE(StreamHasMatchingCandidate(0, "tcptype passive", " 9 "));
   2299  ASSERT_TRUE(StreamHasMatchingCandidate(0, "tcptype so"));
   2300  ASSERT_FALSE(StreamHasMatchingCandidate(0, "tcptype so", " 9 "));
   2301  ASSERT_TRUE(StreamHasMatchingCandidate(0, "tcptype active", " 9 "));
   2302 }
   2303 
   2304 // Disabled because google isn't running any TCP stun servers right now
   2305 TEST_F(WebRtcIceGatherTest,
   2306       DISABLED_TestGatherDNSStunServerHostnameBothUdpTcp) {
   2307  if (stun_server_hostname_.empty()) {
   2308    return;
   2309  }
   2310 
   2311  std::vector<NrIceStunServer> stun_servers;
   2312 
   2313  NrIceCtx::GlobalConfig config;
   2314  config.mTcpEnabled = true;
   2315  NrIceCtx::InitializeGlobals(config);
   2316  EnsurePeer();
   2317  stun_servers.push_back(*NrIceStunServer::Create(
   2318      stun_server_hostname_, kDefaultStunServerPort, kNrIceTransportUdp));
   2319  stun_servers.push_back(*NrIceStunServer::Create(
   2320      stun_server_hostname_, kDefaultStunServerPort, kNrIceTransportTcp));
   2321  peer_->SetStunServers(stun_servers);
   2322  peer_->SetDNSResolver();
   2323  peer_->AddStream(1);
   2324  Gather();
   2325  ASSERT_TRUE(StreamHasMatchingCandidate(0, " UDP "));
   2326  ASSERT_TRUE(StreamHasMatchingCandidate(0, " TCP "));
   2327 }
   2328 
   2329 // Disabled because google isn't running any TCP stun servers right now
   2330 TEST_F(WebRtcIceGatherTest,
   2331       DISABLED_TestGatherDNSStunServerIpAddressBothUdpTcp) {
   2332  if (stun_server_address_.empty()) {
   2333    return;
   2334  }
   2335 
   2336  std::vector<NrIceStunServer> stun_servers;
   2337 
   2338  NrIceCtx::GlobalConfig config;
   2339  config.mTcpEnabled = true;
   2340  NrIceCtx::InitializeGlobals(config);
   2341  EnsurePeer();
   2342  stun_servers.push_back(*NrIceStunServer::Create(
   2343      stun_server_address_, kDefaultStunServerPort, kNrIceTransportUdp));
   2344  stun_servers.push_back(*NrIceStunServer::Create(
   2345      stun_server_address_, kDefaultStunServerPort, kNrIceTransportTcp));
   2346  peer_->SetStunServers(stun_servers);
   2347  peer_->SetDNSResolver();
   2348  peer_->AddStream(1);
   2349  Gather();
   2350  ASSERT_TRUE(StreamHasMatchingCandidate(0, " UDP "));
   2351  ASSERT_TRUE(StreamHasMatchingCandidate(0, " TCP "));
   2352 }
   2353 
   2354 TEST_F(WebRtcIceGatherTest, TestGatherDNSStunBogusHostname) {
   2355  NrIceCtx::GlobalConfig config;
   2356  config.mTcpEnabled = false;
   2357  NrIceCtx::InitializeGlobals(config);
   2358  EnsurePeer();
   2359  peer_->SetStunServer(kBogusStunServerHostname, kDefaultStunServerPort);
   2360  peer_->SetDNSResolver();
   2361  peer_->AddStream(1);
   2362  Gather();
   2363  ASSERT_TRUE(StreamHasMatchingCandidate(0, " UDP "));
   2364 }
   2365 
   2366 // Disabled because google isn't running any TCP stun servers right now
   2367 TEST_F(WebRtcIceGatherTest, DISABLED_TestGatherDNSStunBogusHostnameTcp) {
   2368  NrIceCtx::GlobalConfig config;
   2369  config.mTcpEnabled = true;
   2370  NrIceCtx::InitializeGlobals(config);
   2371  EnsurePeer();
   2372  peer_->SetStunServer(kBogusStunServerHostname, kDefaultStunServerPort,
   2373                       kNrIceTransportTcp);
   2374  peer_->SetDNSResolver();
   2375  peer_->AddStream(1);
   2376  Gather();
   2377  ASSERT_TRUE(StreamHasMatchingCandidate(0, " TCP "));
   2378 }
   2379 
   2380 TEST_F(WebRtcIceGatherTest, TestDefaultCandidate) {
   2381  NrIceCtx::GlobalConfig config;
   2382  config.mTcpEnabled = false;
   2383  NrIceCtx::InitializeGlobals(config);
   2384  EnsurePeer();
   2385  peer_->SetStunServer(stun_server_hostname_, kDefaultStunServerPort);
   2386  peer_->AddStream(1);
   2387  Gather();
   2388  NrIceCandidate default_candidate;
   2389  ASSERT_TRUE(NS_SUCCEEDED(peer_->GetDefaultCandidate(0, &default_candidate)));
   2390 }
   2391 
   2392 TEST_F(WebRtcIceGatherTest, TestGatherTurn) {
   2393  NrIceCtx::GlobalConfig config;
   2394  config.mTcpEnabled = false;
   2395  NrIceCtx::InitializeGlobals(config);
   2396  EnsurePeer();
   2397  if (turn_server_.empty()) return;
   2398  peer_->SetTurnServer(turn_server_, kDefaultStunServerPort, turn_user_,
   2399                       turn_password_, kNrIceTransportUdp);
   2400  peer_->AddStream(1);
   2401  Gather();
   2402 }
   2403 
   2404 TEST_F(WebRtcIceGatherTest, TestGatherTurnTcp) {
   2405  NrIceCtx::GlobalConfig config;
   2406  config.mTcpEnabled = false;
   2407  NrIceCtx::InitializeGlobals(config);
   2408  EnsurePeer();
   2409  if (turn_server_.empty()) return;
   2410  peer_->SetTurnServer(turn_server_, kDefaultStunServerPort, turn_user_,
   2411                       turn_password_, kNrIceTransportTcp);
   2412  peer_->AddStream(1);
   2413  Gather();
   2414 }
   2415 
   2416 TEST_F(WebRtcIceGatherTest, TestGatherDisableComponent) {
   2417  if (stun_server_hostname_.empty()) {
   2418    return;
   2419  }
   2420 
   2421  NrIceCtx::GlobalConfig config;
   2422  config.mTcpEnabled = false;
   2423  NrIceCtx::InitializeGlobals(config);
   2424  EnsurePeer();
   2425  peer_->SetStunServer(stun_server_hostname_, kDefaultStunServerPort);
   2426  peer_->AddStream(1);
   2427  peer_->AddStream(2);
   2428  peer_->DisableComponent(1, 2);
   2429  Gather();
   2430  std::vector<std::string> attributes = peer_->GetAttributes(1);
   2431 
   2432  for (auto& attribute : attributes) {
   2433    if (attribute.find("candidate:") != std::string::npos) {
   2434      size_t sp1 = attribute.find(' ');
   2435      ASSERT_EQ(0, attribute.compare(sp1 + 1, 1, "1", 1));
   2436    }
   2437  }
   2438 }
   2439 
   2440 TEST_F(WebRtcIceGatherTest, TestGatherVerifyNoLoopback) {
   2441  NrIceCtx::GlobalConfig config;
   2442  config.mTcpEnabled = false;
   2443  NrIceCtx::InitializeGlobals(config);
   2444  EnsurePeer();
   2445  peer_->AddStream(1);
   2446  Gather();
   2447  ASSERT_FALSE(StreamHasMatchingCandidate(0, "127.0.0.1"));
   2448 }
   2449 
   2450 TEST_F(WebRtcIceGatherTest, TestGatherAllowLoopback) {
   2451  NrIceCtx::GlobalConfig globalConfig;
   2452  globalConfig.mTcpEnabled = false;
   2453  NrIceCtx::InitializeGlobals(globalConfig);
   2454 
   2455  NrIceCtx::Config config;
   2456  config.mAllowLoopback = true;
   2457  // Set up peer with loopback allowed.
   2458  peer_ = MakeUnique<IceTestPeer>("P1", test_utils_, true, config);
   2459  peer_->AddStream(1);
   2460  Gather();
   2461  ASSERT_TRUE(StreamHasMatchingCandidate(0, "127.0.0.1"));
   2462 }
   2463 
   2464 TEST_F(WebRtcIceGatherTest, TestGatherTcpDisabledNoStun) {
   2465  NrIceCtx::GlobalConfig config;
   2466  config.mTcpEnabled = false;
   2467  NrIceCtx::InitializeGlobals(config);
   2468  EnsurePeer();
   2469  peer_->AddStream(1);
   2470  Gather();
   2471  ASSERT_FALSE(StreamHasMatchingCandidate(0, " TCP "));
   2472  ASSERT_TRUE(StreamHasMatchingCandidate(0, " UDP "));
   2473 }
   2474 
   2475 TEST_F(WebRtcIceGatherTest, VerifyTestStunServer) {
   2476  NrIceCtx::GlobalConfig config;
   2477  config.mTcpEnabled = false;
   2478  NrIceCtx::InitializeGlobals(config);
   2479  UseFakeStunUdpServerWithResponse("192.0.2.133", 3333);
   2480  peer_->AddStream(1);
   2481  Gather();
   2482  ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.2.133 3333 "));
   2483 }
   2484 
   2485 TEST_F(WebRtcIceGatherTest, VerifyTestStunTcpServer) {
   2486  NrIceCtx::GlobalConfig config;
   2487  config.mTcpEnabled = true;
   2488  NrIceCtx::InitializeGlobals(config);
   2489  UseFakeStunTcpServerWithResponse("192.0.2.233", 3333);
   2490  peer_->AddStream(1);
   2491  Gather();
   2492  ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.2.233 3333 typ srflx",
   2493                                         " tcptype "));
   2494 }
   2495 
   2496 TEST_F(WebRtcIceGatherTest, VerifyTestStunServerV6) {
   2497  if (!TestStunServer::GetInstance(AF_INET6)) {
   2498    // No V6 addresses
   2499    return;
   2500  }
   2501  NrIceCtx::GlobalConfig config;
   2502  config.mTcpEnabled = false;
   2503  NrIceCtx::InitializeGlobals(config);
   2504  UseFakeStunUdpServerWithResponse("beef::", 3333);
   2505  peer_->AddStream(1);
   2506  Gather();
   2507  ASSERT_TRUE(StreamHasMatchingCandidate(0, " beef:: 3333 "));
   2508 }
   2509 
   2510 TEST_F(WebRtcIceGatherTest, VerifyTestStunServerFQDN) {
   2511  NrIceCtx::GlobalConfig config;
   2512  config.mTcpEnabled = false;
   2513  NrIceCtx::InitializeGlobals(config);
   2514  UseFakeStunUdpServerWithResponse("192.0.2.133", 3333, "stun.example.com");
   2515  peer_->AddStream(1);
   2516  Gather();
   2517  ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.2.133 3333 "));
   2518 }
   2519 
   2520 TEST_F(WebRtcIceGatherTest, VerifyTestStunServerV6FQDN) {
   2521  if (!TestStunServer::GetInstance(AF_INET6)) {
   2522    // No V6 addresses
   2523    return;
   2524  }
   2525  NrIceCtx::GlobalConfig config;
   2526  config.mTcpEnabled = false;
   2527  NrIceCtx::InitializeGlobals(config);
   2528  UseFakeStunUdpServerWithResponse("beef::", 3333, "stun.example.com");
   2529  peer_->AddStream(1);
   2530  Gather();
   2531  ASSERT_TRUE(StreamHasMatchingCandidate(0, " beef:: 3333 "));
   2532 }
   2533 
   2534 TEST_F(WebRtcIceGatherTest, TestStunServerReturnsWildcardAddr) {
   2535  NrIceCtx::GlobalConfig config;
   2536  config.mTcpEnabled = false;
   2537  NrIceCtx::InitializeGlobals(config);
   2538  UseFakeStunUdpServerWithResponse("0.0.0.0", 3333);
   2539  peer_->AddStream(1);
   2540  Gather(kDefaultTimeout * 3);
   2541  ASSERT_FALSE(StreamHasMatchingCandidate(0, " 0.0.0.0 "));
   2542 }
   2543 
   2544 TEST_F(WebRtcIceGatherTest, TestStunServerReturnsWildcardAddrV6) {
   2545  if (!TestStunServer::GetInstance(AF_INET6)) {
   2546    // No V6 addresses
   2547    return;
   2548  }
   2549  NrIceCtx::GlobalConfig config;
   2550  config.mTcpEnabled = false;
   2551  NrIceCtx::InitializeGlobals(config);
   2552  UseFakeStunUdpServerWithResponse("::", 3333);
   2553  peer_->AddStream(1);
   2554  Gather(kDefaultTimeout * 3);
   2555  ASSERT_FALSE(StreamHasMatchingCandidate(0, " :: "));
   2556 }
   2557 
   2558 TEST_F(WebRtcIceGatherTest, TestStunServerReturnsPort0) {
   2559  NrIceCtx::GlobalConfig config;
   2560  config.mTcpEnabled = false;
   2561  NrIceCtx::InitializeGlobals(config);
   2562  UseFakeStunUdpServerWithResponse("192.0.2.133", 0);
   2563  peer_->AddStream(1);
   2564  Gather(kDefaultTimeout * 3);
   2565  ASSERT_FALSE(StreamHasMatchingCandidate(0, " 192.0.2.133 0 "));
   2566 }
   2567 
   2568 TEST_F(WebRtcIceGatherTest, TestStunServerReturnsLoopbackAddr) {
   2569  NrIceCtx::GlobalConfig config;
   2570  config.mTcpEnabled = false;
   2571  NrIceCtx::InitializeGlobals(config);
   2572  UseFakeStunUdpServerWithResponse("127.0.0.133", 3333);
   2573  peer_->AddStream(1);
   2574  Gather(kDefaultTimeout * 3);
   2575  ASSERT_FALSE(StreamHasMatchingCandidate(0, " 127.0.0.133 "));
   2576 }
   2577 
   2578 TEST_F(WebRtcIceGatherTest, TestStunServerReturnsLoopbackAddrV6) {
   2579  if (!TestStunServer::GetInstance(AF_INET6)) {
   2580    // No V6 addresses
   2581    return;
   2582  }
   2583  NrIceCtx::GlobalConfig config;
   2584  config.mTcpEnabled = false;
   2585  NrIceCtx::InitializeGlobals(config);
   2586  UseFakeStunUdpServerWithResponse("::1", 3333);
   2587  peer_->AddStream(1);
   2588  Gather(kDefaultTimeout * 3);
   2589  ASSERT_FALSE(StreamHasMatchingCandidate(0, " ::1 "));
   2590 }
   2591 
   2592 TEST_F(WebRtcIceGatherTest, TestStunServerTrickle) {
   2593  NrIceCtx::GlobalConfig config;
   2594  config.mTcpEnabled = false;
   2595  NrIceCtx::InitializeGlobals(config);
   2596  UseFakeStunUdpServerWithResponse("192.0.2.1", 3333);
   2597  peer_->AddStream(1);
   2598  TestStunServer::GetInstance(AF_INET)->SetDropInitialPackets(3);
   2599  Gather(0);
   2600  ASSERT_FALSE(StreamHasMatchingCandidate(0, "192.0.2.1"));
   2601  WaitForGather();
   2602  ASSERT_TRUE(StreamHasMatchingCandidate(0, "192.0.2.1"));
   2603 }
   2604 
   2605 // Test no host with our fake STUN server and apparently NATted.
   2606 TEST_F(WebRtcIceGatherTest, TestFakeStunServerNatedNoHost) {
   2607  {
   2608    NrIceCtx::GlobalConfig config;
   2609    config.mTcpEnabled = false;
   2610    NrIceCtx::InitializeGlobals(config);
   2611  }
   2612 
   2613  NrIceCtx::Config config;
   2614  config.mPolicy = NrIceCtx::ICE_POLICY_NO_HOST;
   2615  peer_ = MakeUnique<IceTestPeer>("P1", test_utils_, true, config);
   2616  UseFakeStunUdpServerWithResponse("192.0.2.1", 3333);
   2617  peer_->AddStream(1);
   2618  Gather(0);
   2619  WaitForGather();
   2620  DumpAttributes(0);
   2621  ASSERT_FALSE(StreamHasMatchingCandidate(0, "host"));
   2622  ASSERT_TRUE(StreamHasMatchingCandidate(0, "srflx"));
   2623  NrIceCandidate default_candidate;
   2624  nsresult rv = peer_->GetDefaultCandidate(0, &default_candidate);
   2625  if (NS_SUCCEEDED(rv)) {
   2626    ASSERT_NE(NrIceCandidate::ICE_HOST, default_candidate.type);
   2627  }
   2628 }
   2629 
   2630 // Test no host with our fake STUN server and apparently non-NATted.
   2631 TEST_F(WebRtcIceGatherTest, TestFakeStunServerNoNatNoHost) {
   2632  {
   2633    NrIceCtx::GlobalConfig config;
   2634    config.mTcpEnabled = false;
   2635    NrIceCtx::InitializeGlobals(config);
   2636  }
   2637 
   2638  NrIceCtx::Config config;
   2639  config.mPolicy = NrIceCtx::ICE_POLICY_NO_HOST;
   2640  peer_ = MakeUnique<IceTestPeer>("P1", test_utils_, true, config);
   2641  UseTestStunServer();
   2642  peer_->AddStream(1);
   2643  Gather(0);
   2644  WaitForGather();
   2645  DumpAttributes(0);
   2646  ASSERT_FALSE(StreamHasMatchingCandidate(0, "host"));
   2647  ASSERT_TRUE(StreamHasMatchingCandidate(0, "srflx"));
   2648 }
   2649 
   2650 // Test that srflx candidate is discarded in non-NATted environment if host
   2651 // address obfuscation is not enabled.
   2652 TEST_F(WebRtcIceGatherTest,
   2653       TestSrflxCandidateDiscardedWithObfuscateHostAddressesNotEnabled) {
   2654  {
   2655    NrIceCtx::GlobalConfig config;
   2656    config.mTcpEnabled = false;
   2657    NrIceCtx::InitializeGlobals(config);
   2658  }
   2659 
   2660  NrIceCtx::Config config;
   2661  peer_ = MakeUnique<IceTestPeer>("P1", test_utils_, true, config);
   2662  UseTestStunServer();
   2663  peer_->AddStream(1);
   2664  Gather(0, false, false);
   2665  WaitForGather();
   2666  DumpAttributes(0);
   2667  EXPECT_TRUE(StreamHasMatchingCandidate(0, "host"));
   2668  EXPECT_FALSE(StreamHasMatchingCandidate(0, "srflx"));
   2669 }
   2670 
   2671 // Test that srflx candidate is generated in non-NATted environment if host
   2672 // address obfuscation is enabled.
   2673 TEST_F(WebRtcIceGatherTest,
   2674       TestSrflxCandidateGeneratedWithObfuscateHostAddressesEnabled) {
   2675  {
   2676    NrIceCtx::GlobalConfig config;
   2677    config.mTcpEnabled = false;
   2678    NrIceCtx::InitializeGlobals(config);
   2679  }
   2680 
   2681  NrIceCtx::Config config;
   2682  peer_ = MakeUnique<IceTestPeer>("P1", test_utils_, true, config);
   2683  UseTestStunServer();
   2684  peer_->AddStream(1);
   2685  Gather(0, false, true);
   2686  WaitForGather();
   2687  DumpAttributes(0);
   2688  EXPECT_TRUE(StreamHasMatchingCandidate(0, "host"));
   2689  EXPECT_TRUE(StreamHasMatchingCandidate(0, "srflx"));
   2690 }
   2691 
   2692 TEST_F(WebRtcIceGatherTest, TestStunTcpServerTrickle) {
   2693  NrIceCtx::GlobalConfig config;
   2694  config.mTcpEnabled = true;
   2695  NrIceCtx::InitializeGlobals(config);
   2696  UseFakeStunTcpServerWithResponse("192.0.3.1", 3333);
   2697  TestStunTcpServer::GetInstance(AF_INET)->SetDelay(500);
   2698  peer_->AddStream(1);
   2699  Gather(0);
   2700  ASSERT_FALSE(StreamHasMatchingCandidate(0, " 192.0.3.1 ", " tcptype "));
   2701  WaitForGather();
   2702  ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.3.1 ", " tcptype "));
   2703 }
   2704 
   2705 TEST_F(WebRtcIceGatherTest, TestStunTcpAndUdpServerTrickle) {
   2706  NrIceCtx::GlobalConfig config;
   2707  config.mTcpEnabled = true;
   2708  NrIceCtx::InitializeGlobals(config);
   2709  UseFakeStunUdpTcpServersWithResponse("192.0.2.1", 3333, "192.0.3.1", 3333);
   2710  TestStunServer::GetInstance(AF_INET)->SetDropInitialPackets(3);
   2711  TestStunTcpServer::GetInstance(AF_INET)->SetDelay(500);
   2712  peer_->AddStream(1);
   2713  Gather(0);
   2714  ASSERT_FALSE(StreamHasMatchingCandidate(0, "192.0.2.1", "UDP"));
   2715  ASSERT_FALSE(StreamHasMatchingCandidate(0, " 192.0.3.1 ", " tcptype "));
   2716  WaitForGather();
   2717  ASSERT_TRUE(StreamHasMatchingCandidate(0, "192.0.2.1", "UDP"));
   2718  ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.3.1 ", " tcptype "));
   2719 }
   2720 
   2721 TEST_F(WebRtcIceGatherTest, TestSetIceControlling) {
   2722  NrIceCtx::GlobalConfig config;
   2723  config.mTcpEnabled = false;
   2724  NrIceCtx::InitializeGlobals(config);
   2725  EnsurePeer();
   2726  peer_->AddStream(1);
   2727  peer_->SetControlling(NrIceCtx::ICE_CONTROLLING);
   2728  NrIceCtx::Controlling controlling = peer_->GetControlling();
   2729  ASSERT_EQ(NrIceCtx::ICE_CONTROLLING, controlling);
   2730  // SetControlling should only allow setting this once
   2731  peer_->SetControlling(NrIceCtx::ICE_CONTROLLED);
   2732  controlling = peer_->GetControlling();
   2733  ASSERT_EQ(NrIceCtx::ICE_CONTROLLING, controlling);
   2734 }
   2735 
   2736 TEST_F(WebRtcIceGatherTest, TestSetIceControlled) {
   2737  NrIceCtx::GlobalConfig config;
   2738  config.mTcpEnabled = false;
   2739  NrIceCtx::InitializeGlobals(config);
   2740  EnsurePeer();
   2741  peer_->AddStream(1);
   2742  peer_->SetControlling(NrIceCtx::ICE_CONTROLLED);
   2743  NrIceCtx::Controlling controlling = peer_->GetControlling();
   2744  ASSERT_EQ(NrIceCtx::ICE_CONTROLLED, controlling);
   2745  // SetControlling should only allow setting this once
   2746  peer_->SetControlling(NrIceCtx::ICE_CONTROLLING);
   2747  controlling = peer_->GetControlling();
   2748  ASSERT_EQ(NrIceCtx::ICE_CONTROLLED, controlling);
   2749 }
   2750 
   2751 TEST_F(WebRtcIceConnectTest, TestGather) {
   2752  NrIceCtx::GlobalConfig config;
   2753  config.mTcpEnabled = false;
   2754  NrIceCtx::InitializeGlobals(config);
   2755  AddStream(1);
   2756  ASSERT_TRUE(Gather());
   2757 }
   2758 
   2759 TEST_F(WebRtcIceConnectTest, TestGatherTcp) {
   2760  NrIceCtx::GlobalConfig config;
   2761  config.mTcpEnabled = true;
   2762  NrIceCtx::InitializeGlobals(config);
   2763  Init();
   2764  AddStream(1);
   2765  ASSERT_TRUE(Gather());
   2766 }
   2767 
   2768 TEST_F(WebRtcIceConnectTest, TestGatherAutoPrioritize) {
   2769  NrIceCtx::GlobalConfig config;
   2770  config.mTcpEnabled = false;
   2771  NrIceCtx::InitializeGlobals(config);
   2772  Init();
   2773  AddStream(1);
   2774  ASSERT_TRUE(Gather());
   2775 }
   2776 
   2777 TEST_F(WebRtcIceConnectTest, TestConnect) {
   2778  NrIceCtx::GlobalConfig config;
   2779  config.mTcpEnabled = false;
   2780  NrIceCtx::InitializeGlobals(config);
   2781  AddStream(1);
   2782  ASSERT_TRUE(Gather());
   2783  Connect();
   2784 }
   2785 
   2786 TEST_F(WebRtcIceConnectTest, TestConnectRestartIce) {
   2787  NrIceCtx::GlobalConfig config;
   2788  config.mTcpEnabled = false;
   2789  NrIceCtx::InitializeGlobals(config);
   2790  AddStream(1);
   2791  ASSERT_TRUE(Gather());
   2792  Connect();
   2793  SendReceive(p1_.get(), p2_.get());
   2794 
   2795  p2_->RestartIce();
   2796  ASSERT_FALSE(p2_->gathering_complete());
   2797 
   2798  // verify p1 and p2 streams are still connected after restarting ice on p2
   2799  SendReceive(p1_.get(), p2_.get());
   2800 
   2801  mozilla::UniquePtr<IceTestPeer> p3_;
   2802  p3_ = MakeUnique<IceTestPeer>("P3", test_utils_, true, NrIceCtx::Config());
   2803  InitPeer(p3_.get());
   2804  p3_->AddStream(1);
   2805 
   2806  ASSERT_TRUE(GatherCallerAndCallee(p2_.get(), p3_.get()));
   2807  std::cout << "-------------------------------------------------" << std::endl;
   2808  ConnectCallerAndCallee(p3_.get(), p2_.get(), TRICKLE_SIMULATE);
   2809  SendReceive(p1_.get(), p2_.get());  // p1 and p2 are still connected
   2810  SendReceive(p3_.get(), p2_.get(), true, true);  // p3 and p2 not yet connected
   2811  p2_->SimulateTrickle(0);
   2812  p3_->SimulateTrickle(0);
   2813  ASSERT_TRUE_WAIT(p3_->is_ready(0), kDefaultTimeout);
   2814  ASSERT_TRUE_WAIT(p2_->is_ready(0), kDefaultTimeout);
   2815  SendReceive(p1_.get(), p2_.get(), false, true);  // p1 and p2 not connected
   2816  SendReceive(p3_.get(), p2_.get());  // p3 and p2 are now connected
   2817 
   2818  p3_ = nullptr;
   2819 }
   2820 
   2821 TEST_F(WebRtcIceConnectTest, TestConnectRestartIceThenAbort) {
   2822  NrIceCtx::GlobalConfig config;
   2823  config.mTcpEnabled = false;
   2824  NrIceCtx::InitializeGlobals(config);
   2825  AddStream(1);
   2826  ASSERT_TRUE(Gather());
   2827  Connect();
   2828  SendReceive(p1_.get(), p2_.get());
   2829 
   2830  p2_->RestartIce();
   2831  ASSERT_FALSE(p2_->gathering_complete());
   2832 
   2833  // verify p1 and p2 streams are still connected after restarting ice on p2
   2834  SendReceive(p1_.get(), p2_.get());
   2835 
   2836  mozilla::UniquePtr<IceTestPeer> p3_;
   2837  p3_ = MakeUnique<IceTestPeer>("P3", test_utils_, true, NrIceCtx::Config());
   2838  InitPeer(p3_.get());
   2839  p3_->AddStream(1);
   2840 
   2841  ASSERT_TRUE(GatherCallerAndCallee(p2_.get(), p3_.get()));
   2842  std::cout << "-------------------------------------------------" << std::endl;
   2843  p2_->RollbackIceRestart();
   2844  p2_->Connect(p1_.get(), TRICKLE_NONE);
   2845  SendReceive(p1_.get(), p2_.get());
   2846  p3_ = nullptr;
   2847 }
   2848 
   2849 TEST_F(WebRtcIceConnectTest, TestConnectIceRestartRoleConflict) {
   2850  NrIceCtx::GlobalConfig config;
   2851  config.mTcpEnabled = false;
   2852  NrIceCtx::InitializeGlobals(config);
   2853  AddStream(1);
   2854  ASSERT_TRUE(Gather());
   2855  // Just for fun lets do this with switched rolls
   2856  p1_->SetControlling(NrIceCtx::ICE_CONTROLLED);
   2857  p2_->SetControlling(NrIceCtx::ICE_CONTROLLING);
   2858  Connect();
   2859  SendReceive(p1_.get(), p2_.get());
   2860  // Set rolls should not switch by connecting
   2861  ASSERT_EQ(NrIceCtx::ICE_CONTROLLED, p1_->GetControlling());
   2862  ASSERT_EQ(NrIceCtx::ICE_CONTROLLING, p2_->GetControlling());
   2863 
   2864  p2_->RestartIce();
   2865  ASSERT_FALSE(p2_->gathering_complete());
   2866  p2_->SetControlling(NrIceCtx::ICE_CONTROLLED);
   2867  ASSERT_EQ(NrIceCtx::ICE_CONTROLLING, p2_->GetControlling())
   2868      << "ICE restart should not allow role to change, unless ice-lite happens";
   2869 
   2870  mozilla::UniquePtr<IceTestPeer> p3_;
   2871  p3_ = MakeUnique<IceTestPeer>("P3", test_utils_, true, NrIceCtx::Config());
   2872  InitPeer(p3_.get());
   2873  p3_->AddStream(1);
   2874  // Set control role for p3 accordingly (with role conflict)
   2875  p3_->SetControlling(NrIceCtx::ICE_CONTROLLING);
   2876  ASSERT_EQ(NrIceCtx::ICE_CONTROLLING, p3_->GetControlling());
   2877 
   2878  ASSERT_TRUE(GatherCallerAndCallee(p2_.get(), p3_.get()));
   2879  std::cout << "-------------------------------------------------" << std::endl;
   2880  ConnectCallerAndCallee(p3_.get(), p2_.get());
   2881  auto p2role = p2_->GetControlling();
   2882  ASSERT_NE(p2role, p3_->GetControlling()) << "Conflict should be resolved";
   2883  ASSERT_EQ(NrIceCtx::ICE_CONTROLLED, p1_->GetControlling())
   2884      << "P1 should be unaffected by role conflict";
   2885 
   2886  // And again we are not allowed to switch roles at this point any more
   2887  p1_->SetControlling(NrIceCtx::ICE_CONTROLLING);
   2888  ASSERT_EQ(NrIceCtx::ICE_CONTROLLED, p1_->GetControlling());
   2889  p3_->SetControlling(p2role);
   2890  ASSERT_NE(p2role, p3_->GetControlling());
   2891 
   2892  p3_ = nullptr;
   2893 }
   2894 
   2895 TEST_F(WebRtcIceConnectTest,
   2896       TestIceRestartWithMultipleInterfacesAndUserStartingScreenSharing) {
   2897  const char* FAKE_WIFI_ADDR = "10.0.0.1";
   2898  const char* FAKE_WIFI_IF_NAME = "wlan9";
   2899 
   2900  // prepare a fake wifi interface
   2901  nr_local_addr wifi_addr;
   2902  wifi_addr.iface.type = NR_INTERFACE_TYPE_WIFI;
   2903  wifi_addr.iface.estimated_speed = 1000;
   2904 
   2905  int r = nr_str_port_to_transport_addr(FAKE_WIFI_ADDR, 0, IPPROTO_UDP,
   2906                                        &(wifi_addr.addr));
   2907  ASSERT_EQ(0, r);
   2908  strncpy(wifi_addr.addr.ifname, FAKE_WIFI_IF_NAME, MAXIFNAME);
   2909 
   2910  NrIceCtx::GlobalConfig config;
   2911  config.mTcpEnabled = false;
   2912  NrIceCtx::InitializeGlobals(config);
   2913  // setup initial ICE connection between p1_ and p2_
   2914  UseNat();
   2915  AddStream(1);
   2916  SetExpectedTypes(NrIceCandidate::Type::ICE_SERVER_REFLEXIVE,
   2917                   NrIceCandidate::Type::ICE_SERVER_REFLEXIVE);
   2918  ASSERT_TRUE(Gather(kDefaultTimeout, true));
   2919  Connect();
   2920 
   2921  // verify the connection is working
   2922  SendReceive(p1_.get(), p2_.get());
   2923 
   2924  // simulate user accepting permissions for screen sharing
   2925  p2_->SetCtxFlags(false);
   2926 
   2927  // and having an additional non-default interface
   2928  nsTArray<NrIceStunAddr> stunAddr = p2_->GetStunAddrs();
   2929  stunAddr.InsertElementAt(0, NrIceStunAddr(&wifi_addr));
   2930  p2_->SetStunAddrs(stunAddr);
   2931 
   2932  std::cout << "-------------------------------------------------" << std::endl;
   2933 
   2934  // now restart ICE
   2935  p2_->RestartIce();
   2936  ASSERT_FALSE(p2_->gathering_complete());
   2937 
   2938  // verify that we can successfully gather candidates
   2939  p2_->Gather();
   2940  EXPECT_TRUE_WAIT(p2_->gathering_complete(), kDefaultTimeout);
   2941 }
   2942 
   2943 TEST_F(WebRtcIceConnectTest, TestConnectTcp) {
   2944  NrIceCtx::GlobalConfig config;
   2945  config.mTcpEnabled = true;
   2946  NrIceCtx::InitializeGlobals(config);
   2947  Init();
   2948  AddStream(1);
   2949  ASSERT_TRUE(Gather());
   2950  SetCandidateFilter(IsTcpCandidate);
   2951  SetExpectedTypes(NrIceCandidate::Type::ICE_HOST,
   2952                   NrIceCandidate::Type::ICE_HOST, kNrIceTransportTcp);
   2953  Connect();
   2954 }
   2955 
   2956 // TCP SO tests works on localhost only with delay applied:
   2957 //  tc qdisc add dev lo root netem delay 10ms
   2958 TEST_F(WebRtcIceConnectTest, DISABLED_TestConnectTcpSo) {
   2959  NrIceCtx::GlobalConfig config;
   2960  config.mTcpEnabled = true;
   2961  NrIceCtx::InitializeGlobals(config);
   2962  Init();
   2963  AddStream(1);
   2964  ASSERT_TRUE(Gather());
   2965  SetCandidateFilter(IsTcpSoCandidate);
   2966  SetExpectedTypes(NrIceCandidate::Type::ICE_HOST,
   2967                   NrIceCandidate::Type::ICE_HOST, kNrIceTransportTcp);
   2968  Connect();
   2969 }
   2970 
   2971 // Disabled because this breaks with hairpinning.
   2972 TEST_F(WebRtcIceConnectTest, DISABLED_TestConnectNoHost) {
   2973  NrIceCtx::GlobalConfig config;
   2974  config.mTcpEnabled = false;
   2975  NrIceCtx::InitializeGlobals(config);
   2976  Init(false, NrIceCtx::Config{.mPolicy = NrIceCtx::ICE_POLICY_NO_HOST});
   2977  AddStream(1);
   2978  ASSERT_TRUE(Gather());
   2979  SetExpectedTypes(NrIceCandidate::Type::ICE_SERVER_REFLEXIVE,
   2980                   NrIceCandidate::Type::ICE_SERVER_REFLEXIVE,
   2981                   kNrIceTransportTcp);
   2982  Connect();
   2983 }
   2984 
   2985 TEST_F(WebRtcIceConnectTest, TestLoopbackOnlySortOf) {
   2986  NrIceCtx::GlobalConfig globalConfig;
   2987  globalConfig.mTcpEnabled = false;
   2988  NrIceCtx::InitializeGlobals(globalConfig);
   2989 
   2990  NrIceCtx::Config config;
   2991  config.mAllowLoopback = true;
   2992  Init(false, config);
   2993  AddStream(1);
   2994  SetCandidateFilter(IsLoopbackCandidate);
   2995  ASSERT_TRUE(Gather());
   2996  SetExpectedRemoteCandidateAddr("127.0.0.1");
   2997  Connect();
   2998 }
   2999 
   3000 TEST_F(WebRtcIceConnectTest, TestConnectBothControllingP1Wins) {
   3001  NrIceCtx::GlobalConfig config;
   3002  config.mTcpEnabled = false;
   3003  NrIceCtx::InitializeGlobals(config);
   3004  AddStream(1);
   3005  p1_->SetTiebreaker(1);
   3006  p2_->SetTiebreaker(0);
   3007  ASSERT_TRUE(Gather());
   3008  p1_->SetControlling(NrIceCtx::ICE_CONTROLLING);
   3009  p2_->SetControlling(NrIceCtx::ICE_CONTROLLING);
   3010  Connect();
   3011 }
   3012 
   3013 TEST_F(WebRtcIceConnectTest, TestConnectBothControllingP2Wins) {
   3014  NrIceCtx::GlobalConfig config;
   3015  config.mTcpEnabled = false;
   3016  NrIceCtx::InitializeGlobals(config);
   3017  AddStream(1);
   3018  p1_->SetTiebreaker(0);
   3019  p2_->SetTiebreaker(1);
   3020  ASSERT_TRUE(Gather());
   3021  p1_->SetControlling(NrIceCtx::ICE_CONTROLLING);
   3022  p2_->SetControlling(NrIceCtx::ICE_CONTROLLING);
   3023  Connect();
   3024 }
   3025 
   3026 TEST_F(WebRtcIceConnectTest, TestConnectIceLiteOfferer) {
   3027  NrIceCtx::GlobalConfig config;
   3028  config.mTcpEnabled = false;
   3029  NrIceCtx::InitializeGlobals(config);
   3030  AddStream(1);
   3031  ASSERT_TRUE(Gather());
   3032  p1_->SimulateIceLite();
   3033  Connect();
   3034 }
   3035 
   3036 TEST_F(WebRtcIceConnectTest, TestTrickleBothControllingP1Wins) {
   3037  NrIceCtx::GlobalConfig config;
   3038  config.mTcpEnabled = false;
   3039  NrIceCtx::InitializeGlobals(config);
   3040  AddStream(1);
   3041  p1_->SetTiebreaker(1);
   3042  p2_->SetTiebreaker(0);
   3043  ASSERT_TRUE(Gather());
   3044  p1_->SetControlling(NrIceCtx::ICE_CONTROLLING);
   3045  p2_->SetControlling(NrIceCtx::ICE_CONTROLLING);
   3046  ConnectTrickle();
   3047  SimulateTrickle(0);
   3048  WaitForConnected(1000);
   3049  AssertCheckingReached();
   3050 }
   3051 
   3052 TEST_F(WebRtcIceConnectTest, TestTrickleBothControllingP2Wins) {
   3053  NrIceCtx::GlobalConfig config;
   3054  config.mTcpEnabled = false;
   3055  NrIceCtx::InitializeGlobals(config);
   3056  AddStream(1);
   3057  p1_->SetTiebreaker(0);
   3058  p2_->SetTiebreaker(1);
   3059  ASSERT_TRUE(Gather());
   3060  p1_->SetControlling(NrIceCtx::ICE_CONTROLLING);
   3061  p2_->SetControlling(NrIceCtx::ICE_CONTROLLING);
   3062  ConnectTrickle();
   3063  SimulateTrickle(0);
   3064  WaitForConnected(1000);
   3065  AssertCheckingReached();
   3066 }
   3067 
   3068 TEST_F(WebRtcIceConnectTest, TestTrickleIceLiteOfferer) {
   3069  NrIceCtx::GlobalConfig config;
   3070  config.mTcpEnabled = false;
   3071  NrIceCtx::InitializeGlobals(config);
   3072  AddStream(1);
   3073  ASSERT_TRUE(Gather());
   3074  p1_->SimulateIceLite();
   3075  ConnectTrickle();
   3076  SimulateTrickle(0);
   3077  WaitForConnected(1000);
   3078  AssertCheckingReached();
   3079 }
   3080 
   3081 TEST_F(WebRtcIceConnectTest, TestGatherFullCone) {
   3082  NrIceCtx::GlobalConfig config;
   3083  config.mTcpEnabled = false;
   3084  NrIceCtx::InitializeGlobals(config);
   3085  UseNat();
   3086  AddStream(1);
   3087  ASSERT_TRUE(Gather());
   3088 }
   3089 
   3090 TEST_F(WebRtcIceConnectTest, TestGatherFullConeAutoPrioritize) {
   3091  NrIceCtx::GlobalConfig config;
   3092  config.mTcpEnabled = false;
   3093  NrIceCtx::InitializeGlobals(config);
   3094  UseNat();
   3095  Init();
   3096  AddStream(1);
   3097  ASSERT_TRUE(Gather());
   3098 }
   3099 
   3100 TEST_F(WebRtcIceConnectTest, TestConnectFullCone) {
   3101  NrIceCtx::GlobalConfig config;
   3102  config.mTcpEnabled = false;
   3103  NrIceCtx::InitializeGlobals(config);
   3104  UseNat();
   3105  AddStream(1);
   3106  SetExpectedTypes(NrIceCandidate::Type::ICE_SERVER_REFLEXIVE,
   3107                   NrIceCandidate::Type::ICE_SERVER_REFLEXIVE);
   3108  ASSERT_TRUE(Gather());
   3109  Connect();
   3110 }
   3111 
   3112 TEST_F(WebRtcIceConnectTest, TestConnectNoNatNoHost) {
   3113  NrIceCtx::GlobalConfig config;
   3114  config.mTcpEnabled = false;
   3115  NrIceCtx::InitializeGlobals(config);
   3116  Init(false, NrIceCtx::Config{.mPolicy = NrIceCtx::ICE_POLICY_NO_HOST});
   3117  UseTestStunServer();
   3118  // Because we are connecting from our host candidate to the
   3119  // other side's apparent srflx (which is also their host)
   3120  // we see a host/srflx pair.
   3121  SetExpectedTypes(NrIceCandidate::Type::ICE_HOST,
   3122                   NrIceCandidate::Type::ICE_SERVER_REFLEXIVE);
   3123  AddStream(1);
   3124  ASSERT_TRUE(Gather());
   3125  Connect();
   3126 }
   3127 
   3128 TEST_F(WebRtcIceConnectTest, TestConnectFullConeNoHost) {
   3129  NrIceCtx::GlobalConfig config;
   3130  config.mTcpEnabled = false;
   3131  NrIceCtx::InitializeGlobals(config);
   3132  UseNat();
   3133  Init(false, NrIceCtx::Config{.mPolicy = NrIceCtx::ICE_POLICY_NO_HOST});
   3134  UseTestStunServer();
   3135  SetExpectedTypes(NrIceCandidate::Type::ICE_SERVER_REFLEXIVE,
   3136                   NrIceCandidate::Type::ICE_SERVER_REFLEXIVE);
   3137  AddStream(1);
   3138  ASSERT_TRUE(Gather());
   3139  Connect();
   3140 }
   3141 
   3142 TEST_F(WebRtcIceConnectTest, TestGatherAddressRestrictedCone) {
   3143  NrIceCtx::GlobalConfig config;
   3144  config.mTcpEnabled = false;
   3145  NrIceCtx::InitializeGlobals(config);
   3146  UseNat();
   3147  SetFilteringType(TestNat::ADDRESS_DEPENDENT);
   3148  SetMappingType(TestNat::ENDPOINT_INDEPENDENT);
   3149  AddStream(1);
   3150  ASSERT_TRUE(Gather());
   3151 }
   3152 
   3153 TEST_F(WebRtcIceConnectTest, TestConnectAddressRestrictedCone) {
   3154  NrIceCtx::GlobalConfig config;
   3155  config.mTcpEnabled = false;
   3156  NrIceCtx::InitializeGlobals(config);
   3157  UseNat();
   3158  SetFilteringType(TestNat::ADDRESS_DEPENDENT);
   3159  SetMappingType(TestNat::ENDPOINT_INDEPENDENT);
   3160  AddStream(1);
   3161  SetExpectedTypes(NrIceCandidate::Type::ICE_SERVER_REFLEXIVE,
   3162                   NrIceCandidate::Type::ICE_SERVER_REFLEXIVE);
   3163  ASSERT_TRUE(Gather());
   3164  Connect();
   3165 }
   3166 
   3167 TEST_F(WebRtcIceConnectTest, TestGatherPortRestrictedCone) {
   3168  NrIceCtx::GlobalConfig config;
   3169  config.mTcpEnabled = false;
   3170  NrIceCtx::InitializeGlobals(config);
   3171  UseNat();
   3172  SetFilteringType(TestNat::PORT_DEPENDENT);
   3173  SetMappingType(TestNat::ENDPOINT_INDEPENDENT);
   3174  AddStream(1);
   3175  ASSERT_TRUE(Gather());
   3176 }
   3177 
   3178 TEST_F(WebRtcIceConnectTest, TestConnectPortRestrictedCone) {
   3179  NrIceCtx::GlobalConfig config;
   3180  config.mTcpEnabled = false;
   3181  NrIceCtx::InitializeGlobals(config);
   3182  UseNat();
   3183  SetFilteringType(TestNat::PORT_DEPENDENT);
   3184  SetMappingType(TestNat::ENDPOINT_INDEPENDENT);
   3185  AddStream(1);
   3186  SetExpectedTypes(NrIceCandidate::Type::ICE_SERVER_REFLEXIVE,
   3187                   NrIceCandidate::Type::ICE_SERVER_REFLEXIVE);
   3188  ASSERT_TRUE(Gather());
   3189  Connect();
   3190 }
   3191 
   3192 TEST_F(WebRtcIceConnectTest, TestGatherSymmetricNat) {
   3193  NrIceCtx::GlobalConfig config;
   3194  config.mTcpEnabled = false;
   3195  NrIceCtx::InitializeGlobals(config);
   3196  UseNat();
   3197  SetFilteringType(TestNat::PORT_DEPENDENT);
   3198  SetMappingType(TestNat::PORT_DEPENDENT);
   3199  AddStream(1);
   3200  ASSERT_TRUE(Gather());
   3201 }
   3202 
   3203 TEST_F(WebRtcIceConnectTest, TestConnectSymmetricNat) {
   3204  if (turn_server_.empty()) return;
   3205 
   3206  NrIceCtx::GlobalConfig config;
   3207  config.mTcpEnabled = false;
   3208  NrIceCtx::InitializeGlobals(config);
   3209  UseNat();
   3210  SetFilteringType(TestNat::PORT_DEPENDENT);
   3211  SetMappingType(TestNat::PORT_DEPENDENT);
   3212  p1_->SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
   3213                        NrIceCandidate::Type::ICE_RELAYED);
   3214  p2_->SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
   3215                        NrIceCandidate::Type::ICE_RELAYED);
   3216  SetTurnServer(turn_server_, kDefaultStunServerPort, turn_user_,
   3217                turn_password_);
   3218  AddStream(1);
   3219  ASSERT_TRUE(Gather());
   3220  Connect();
   3221 }
   3222 
   3223 TEST_F(WebRtcIceConnectTest, TestConnectSymmetricNatAndNoNat) {
   3224  {
   3225    NrIceCtx::GlobalConfig config;
   3226    config.mTcpEnabled = true;
   3227    NrIceCtx::InitializeGlobals(config);
   3228  }
   3229 
   3230  NrIceCtx::Config config;
   3231  p1_ = MakeUnique<IceTestPeer>("P1", test_utils_, true, config);
   3232  p1_->UseNat();
   3233  p1_->SetFilteringType(TestNat::PORT_DEPENDENT);
   3234  p1_->SetMappingType(TestNat::PORT_DEPENDENT);
   3235 
   3236  p2_ = MakeUnique<IceTestPeer>("P2", test_utils_, false, config);
   3237  initted_ = true;
   3238 
   3239  AddStream(1);
   3240  p1_->SetExpectedTypes(NrIceCandidate::Type::ICE_PEER_REFLEXIVE,
   3241                        NrIceCandidate::Type::ICE_HOST);
   3242  p2_->SetExpectedTypes(NrIceCandidate::Type::ICE_HOST,
   3243                        NrIceCandidate::Type::ICE_PEER_REFLEXIVE);
   3244  ASSERT_TRUE(Gather());
   3245  Connect();
   3246 }
   3247 
   3248 TEST_F(WebRtcIceConnectTest, TestGatherNatBlocksUDP) {
   3249  if (turn_server_.empty()) return;
   3250 
   3251  NrIceCtx::GlobalConfig config;
   3252  config.mTcpEnabled = false;
   3253  NrIceCtx::InitializeGlobals(config);
   3254  UseNat();
   3255  BlockUdp();
   3256  std::vector<NrIceTurnServer> turn_servers;
   3257  std::vector<unsigned char> password_vec(turn_password_.begin(),
   3258                                          turn_password_.end());
   3259  turn_servers.push_back(
   3260      *NrIceTurnServer::Create(turn_server_, kDefaultStunServerPort, turn_user_,
   3261                               password_vec, kNrIceTransportTcp));
   3262  turn_servers.push_back(
   3263      *NrIceTurnServer::Create(turn_server_, kDefaultStunServerPort, turn_user_,
   3264                               password_vec, kNrIceTransportUdp));
   3265  SetTurnServers(turn_servers);
   3266  AddStream(1);
   3267  // We have to wait for the UDP-based stuff to time out.
   3268  ASSERT_TRUE(Gather(kDefaultTimeout * 3));
   3269 }
   3270 
   3271 TEST_F(WebRtcIceConnectTest, TestConnectNatBlocksUDP) {
   3272  if (turn_server_.empty()) return;
   3273 
   3274  NrIceCtx::GlobalConfig config;
   3275  config.mTcpEnabled = false;
   3276  NrIceCtx::InitializeGlobals(config);
   3277  UseNat();
   3278  BlockUdp();
   3279  std::vector<NrIceTurnServer> turn_servers;
   3280  std::vector<unsigned char> password_vec(turn_password_.begin(),
   3281                                          turn_password_.end());
   3282  turn_servers.push_back(
   3283      *NrIceTurnServer::Create(turn_server_, kDefaultStunServerPort, turn_user_,
   3284                               password_vec, kNrIceTransportTcp));
   3285  turn_servers.push_back(
   3286      *NrIceTurnServer::Create(turn_server_, kDefaultStunServerPort, turn_user_,
   3287                               password_vec, kNrIceTransportUdp));
   3288  SetTurnServers(turn_servers);
   3289  p1_->SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
   3290                        NrIceCandidate::Type::ICE_RELAYED, kNrIceTransportTcp);
   3291  p2_->SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
   3292                        NrIceCandidate::Type::ICE_RELAYED, kNrIceTransportTcp);
   3293  AddStream(1);
   3294  ASSERT_TRUE(Gather(kDefaultTimeout * 3));
   3295  Connect();
   3296 }
   3297 
   3298 TEST_F(WebRtcIceConnectTest, TestConnectTwoComponents) {
   3299  NrIceCtx::GlobalConfig config;
   3300  config.mTcpEnabled = false;
   3301  NrIceCtx::InitializeGlobals(config);
   3302  AddStream(2);
   3303  ASSERT_TRUE(Gather());
   3304  Connect();
   3305 }
   3306 
   3307 TEST_F(WebRtcIceConnectTest, TestConnectTwoComponentsDisableSecond) {
   3308  NrIceCtx::GlobalConfig config;
   3309  config.mTcpEnabled = false;
   3310  NrIceCtx::InitializeGlobals(config);
   3311  AddStream(2);
   3312  ASSERT_TRUE(Gather());
   3313  p1_->DisableComponent(0, 2);
   3314  p2_->DisableComponent(0, 2);
   3315  Connect();
   3316 }
   3317 
   3318 TEST_F(WebRtcIceConnectTest, TestConnectP2ThenP1) {
   3319  NrIceCtx::GlobalConfig config;
   3320  config.mTcpEnabled = false;
   3321  NrIceCtx::InitializeGlobals(config);
   3322  AddStream(1);
   3323  ASSERT_TRUE(Gather());
   3324  ConnectP2();
   3325  PR_Sleep(1000);
   3326  ConnectP1();
   3327  WaitForConnectedStreams();
   3328 }
   3329 
   3330 TEST_F(WebRtcIceConnectTest, TestConnectP2ThenP1Trickle) {
   3331  NrIceCtx::GlobalConfig config;
   3332  config.mTcpEnabled = false;
   3333  NrIceCtx::InitializeGlobals(config);
   3334  AddStream(1);
   3335  ASSERT_TRUE(Gather());
   3336  ConnectP2();
   3337  PR_Sleep(1000);
   3338  ConnectP1(TRICKLE_SIMULATE);
   3339  SimulateTrickleP1(0);
   3340  WaitForConnectedStreams();
   3341 }
   3342 
   3343 TEST_F(WebRtcIceConnectTest, TestConnectP2ThenP1TrickleTwoComponents) {
   3344  NrIceCtx::GlobalConfig config;
   3345  config.mTcpEnabled = false;
   3346  NrIceCtx::InitializeGlobals(config);
   3347  AddStream(1);
   3348  AddStream(2);
   3349  ASSERT_TRUE(Gather());
   3350  ConnectP2();
   3351  PR_Sleep(1000);
   3352  ConnectP1(TRICKLE_SIMULATE);
   3353  SimulateTrickleP1(0);
   3354  std::cerr << "Sleeping between trickle streams" << std::endl;
   3355  PR_Sleep(1000);  // Give this some time to settle but not complete
   3356                   // all of ICE.
   3357  SimulateTrickleP1(1);
   3358  WaitForConnectedStreams(2);
   3359 }
   3360 
   3361 TEST_F(WebRtcIceConnectTest, TestConnectAutoPrioritize) {
   3362  NrIceCtx::GlobalConfig config;
   3363  config.mTcpEnabled = false;
   3364  NrIceCtx::InitializeGlobals(config);
   3365  Init();
   3366  AddStream(1);
   3367  ASSERT_TRUE(Gather());
   3368  Connect();
   3369 }
   3370 
   3371 TEST_F(WebRtcIceConnectTest, TestConnectTrickleOneStreamOneComponent) {
   3372  NrIceCtx::GlobalConfig config;
   3373  config.mTcpEnabled = false;
   3374  NrIceCtx::InitializeGlobals(config);
   3375  AddStream(1);
   3376  ASSERT_TRUE(Gather());
   3377  ConnectTrickle();
   3378  SimulateTrickle(0);
   3379  WaitForConnected(1000);
   3380  AssertCheckingReached();
   3381 }
   3382 
   3383 TEST_F(WebRtcIceConnectTest, TestConnectTrickleTwoStreamsOneComponent) {
   3384  NrIceCtx::GlobalConfig config;
   3385  config.mTcpEnabled = false;
   3386  NrIceCtx::InitializeGlobals(config);
   3387  AddStream(1);
   3388  AddStream(1);
   3389  ASSERT_TRUE(Gather());
   3390  ConnectTrickle();
   3391  SimulateTrickle(0);
   3392  SimulateTrickle(1);
   3393  WaitForConnected(1000);
   3394  AssertCheckingReached();
   3395 }
   3396 
   3397 void RealisticTrickleDelay(
   3398    std::vector<SchedulableTrickleCandidate*>& candidates) {
   3399  for (size_t i = 0; i < candidates.size(); ++i) {
   3400    SchedulableTrickleCandidate* cand = candidates[i];
   3401    if (cand->IsHost()) {
   3402      cand->Schedule(i * 10);
   3403    } else if (cand->IsReflexive()) {
   3404      cand->Schedule(i * 10 + 100);
   3405    } else if (cand->IsRelay()) {
   3406      cand->Schedule(i * 10 + 200);
   3407    }
   3408  }
   3409 }
   3410 
   3411 void DelayRelayCandidates(std::vector<SchedulableTrickleCandidate*>& candidates,
   3412                          unsigned int ms) {
   3413  for (auto& candidate : candidates) {
   3414    if (candidate->IsRelay()) {
   3415      candidate->Schedule(ms);
   3416    } else {
   3417      candidate->Schedule(0);
   3418    }
   3419  }
   3420 }
   3421 
   3422 void AddNonPairableCandidates(
   3423    std::vector<SchedulableTrickleCandidate*>& candidates, IceTestPeer* peer,
   3424    size_t stream, int net_type, MtransportTestUtils* test_utils_) {
   3425  for (int i = 1; i < 5; i++) {
   3426    if (net_type == i) continue;
   3427    switch (i) {
   3428      case 1:
   3429        candidates.push_back(new SchedulableTrickleCandidate(
   3430            peer, stream,
   3431            "candidate:0 1 UDP 2113601790 10.0.0.1 12345 typ host", "",
   3432            test_utils_));
   3433        break;
   3434      case 2:
   3435        candidates.push_back(new SchedulableTrickleCandidate(
   3436            peer, stream,
   3437            "candidate:0 1 UDP 2113601791 172.16.1.1 12345 typ host", "",
   3438            test_utils_));
   3439        break;
   3440      case 3:
   3441        candidates.push_back(new SchedulableTrickleCandidate(
   3442            peer, stream,
   3443            "candidate:0 1 UDP 2113601792 192.168.0.1 12345 typ host", "",
   3444            test_utils_));
   3445        break;
   3446      case 4:
   3447        candidates.push_back(new SchedulableTrickleCandidate(
   3448            peer, stream,
   3449            "candidate:0 1 UDP 2113601793 100.64.1.1 12345 typ host", "",
   3450            test_utils_));
   3451        break;
   3452      default:
   3453        NR_UNIMPLEMENTED;
   3454    }
   3455  }
   3456 
   3457  for (auto i = candidates.rbegin(); i != candidates.rend(); ++i) {
   3458    std::cerr << "Scheduling candidate: " << (*i)->Candidate().c_str()
   3459              << std::endl;
   3460    (*i)->Schedule(0);
   3461  }
   3462 }
   3463 
   3464 void DropTrickleCandidates(
   3465    std::vector<SchedulableTrickleCandidate*>& candidates) {}
   3466 
   3467 TEST_F(WebRtcIceConnectTest, TestConnectTrickleAddStreamDuringICE) {
   3468  NrIceCtx::GlobalConfig config;
   3469  config.mTcpEnabled = false;
   3470  NrIceCtx::InitializeGlobals(config);
   3471  AddStream(1);
   3472  ASSERT_TRUE(Gather());
   3473  ConnectTrickle();
   3474  RealisticTrickleDelay(p1_->ControlTrickle(0));
   3475  RealisticTrickleDelay(p2_->ControlTrickle(0));
   3476  AddStream(1);
   3477  ASSERT_TRUE(Gather());
   3478  ConnectTrickle();
   3479  RealisticTrickleDelay(p1_->ControlTrickle(1));
   3480  RealisticTrickleDelay(p2_->ControlTrickle(1));
   3481  WaitForConnected(1000);
   3482  AssertCheckingReached();
   3483 }
   3484 
   3485 TEST_F(WebRtcIceConnectTest, TestConnectTrickleAddStreamAfterICE) {
   3486  NrIceCtx::GlobalConfig config;
   3487  config.mTcpEnabled = false;
   3488  NrIceCtx::InitializeGlobals(config);
   3489  AddStream(1);
   3490  ASSERT_TRUE(Gather());
   3491  ConnectTrickle();
   3492  RealisticTrickleDelay(p1_->ControlTrickle(0));
   3493  RealisticTrickleDelay(p2_->ControlTrickle(0));
   3494  WaitForConnected(1000);
   3495  AddStream(1);
   3496  ASSERT_TRUE(Gather());
   3497  ConnectTrickle();
   3498  RealisticTrickleDelay(p1_->ControlTrickle(1));
   3499  RealisticTrickleDelay(p2_->ControlTrickle(1));
   3500  WaitForConnected(1000);
   3501  AssertCheckingReached();
   3502 }
   3503 
   3504 TEST_F(WebRtcIceConnectTest, RemoveStream) {
   3505  NrIceCtx::GlobalConfig config;
   3506  config.mTcpEnabled = false;
   3507  NrIceCtx::InitializeGlobals(config);
   3508  AddStream(1);
   3509  AddStream(1);
   3510  ASSERT_TRUE(Gather());
   3511  ConnectTrickle();
   3512  RealisticTrickleDelay(p1_->ControlTrickle(0));
   3513  RealisticTrickleDelay(p2_->ControlTrickle(0));
   3514  RealisticTrickleDelay(p1_->ControlTrickle(1));
   3515  RealisticTrickleDelay(p2_->ControlTrickle(1));
   3516  WaitForConnected(1000);
   3517 
   3518  RemoveStream(0);
   3519  ASSERT_TRUE(Gather());
   3520  ConnectTrickle();
   3521 }
   3522 
   3523 TEST_F(WebRtcIceConnectTest, P1NoTrickle) {
   3524  NrIceCtx::GlobalConfig config;
   3525  config.mTcpEnabled = false;
   3526  NrIceCtx::InitializeGlobals(config);
   3527  AddStream(1);
   3528  ASSERT_TRUE(Gather());
   3529  ConnectTrickle();
   3530  DropTrickleCandidates(p1_->ControlTrickle(0));
   3531  RealisticTrickleDelay(p2_->ControlTrickle(0));
   3532  WaitForConnected(1000);
   3533 }
   3534 
   3535 TEST_F(WebRtcIceConnectTest, P2NoTrickle) {
   3536  NrIceCtx::GlobalConfig config;
   3537  config.mTcpEnabled = false;
   3538  NrIceCtx::InitializeGlobals(config);
   3539  AddStream(1);
   3540  ASSERT_TRUE(Gather());
   3541  ConnectTrickle();
   3542  RealisticTrickleDelay(p1_->ControlTrickle(0));
   3543  DropTrickleCandidates(p2_->ControlTrickle(0));
   3544  WaitForConnected(1000);
   3545 }
   3546 
   3547 TEST_F(WebRtcIceConnectTest, RemoveAndAddStream) {
   3548  NrIceCtx::GlobalConfig config;
   3549  config.mTcpEnabled = false;
   3550  NrIceCtx::InitializeGlobals(config);
   3551  AddStream(1);
   3552  AddStream(1);
   3553  ASSERT_TRUE(Gather());
   3554  ConnectTrickle();
   3555  RealisticTrickleDelay(p1_->ControlTrickle(0));
   3556  RealisticTrickleDelay(p2_->ControlTrickle(0));
   3557  RealisticTrickleDelay(p1_->ControlTrickle(1));
   3558  RealisticTrickleDelay(p2_->ControlTrickle(1));
   3559  WaitForConnected(1000);
   3560 
   3561  RemoveStream(0);
   3562  AddStream(1);
   3563  ASSERT_TRUE(Gather());
   3564  ConnectTrickle();
   3565  RealisticTrickleDelay(p1_->ControlTrickle(2));
   3566  RealisticTrickleDelay(p2_->ControlTrickle(2));
   3567  WaitForConnected(1000);
   3568 }
   3569 
   3570 TEST_F(WebRtcIceConnectTest, RemoveStreamBeforeGather) {
   3571  NrIceCtx::GlobalConfig config;
   3572  config.mTcpEnabled = false;
   3573  NrIceCtx::InitializeGlobals(config);
   3574  AddStream(1);
   3575  AddStream(1);
   3576  ASSERT_TRUE(Gather(0));
   3577  RemoveStream(0);
   3578  WaitForGather();
   3579  ConnectTrickle();
   3580  RealisticTrickleDelay(p1_->ControlTrickle(1));
   3581  RealisticTrickleDelay(p2_->ControlTrickle(1));
   3582  WaitForConnected(1000);
   3583 }
   3584 
   3585 TEST_F(WebRtcIceConnectTest, RemoveStreamDuringGather) {
   3586  NrIceCtx::GlobalConfig config;
   3587  config.mTcpEnabled = false;
   3588  NrIceCtx::InitializeGlobals(config);
   3589  AddStream(1);
   3590  AddStream(1);
   3591  RemoveStream(0);
   3592  ASSERT_TRUE(Gather());
   3593  ConnectTrickle();
   3594  RealisticTrickleDelay(p1_->ControlTrickle(1));
   3595  RealisticTrickleDelay(p2_->ControlTrickle(1));
   3596  WaitForConnected(1000);
   3597 }
   3598 
   3599 TEST_F(WebRtcIceConnectTest, RemoveStreamDuringConnect) {
   3600  NrIceCtx::GlobalConfig config;
   3601  config.mTcpEnabled = false;
   3602  NrIceCtx::InitializeGlobals(config);
   3603  AddStream(1);
   3604  AddStream(1);
   3605  ASSERT_TRUE(Gather());
   3606  ConnectTrickle();
   3607  RealisticTrickleDelay(p1_->ControlTrickle(0));
   3608  RealisticTrickleDelay(p2_->ControlTrickle(0));
   3609  RealisticTrickleDelay(p1_->ControlTrickle(1));
   3610  RealisticTrickleDelay(p2_->ControlTrickle(1));
   3611  RemoveStream(0);
   3612  WaitForConnected(1000);
   3613 }
   3614 
   3615 TEST_F(WebRtcIceConnectTest, TestConnectRealTrickleOneStreamOneComponent) {
   3616  NrIceCtx::GlobalConfig config;
   3617  config.mTcpEnabled = false;
   3618  NrIceCtx::InitializeGlobals(config);
   3619  AddStream(1);
   3620  AddStream(1);
   3621  ASSERT_TRUE(Gather(0));
   3622  ConnectTrickle(TRICKLE_REAL);
   3623  WaitForConnected();
   3624  WaitForGather();  // ICE can complete before we finish gathering.
   3625  AssertCheckingReached();
   3626 }
   3627 
   3628 TEST_F(WebRtcIceConnectTest, TestSendReceive) {
   3629  NrIceCtx::GlobalConfig config;
   3630  config.mTcpEnabled = false;
   3631  NrIceCtx::InitializeGlobals(config);
   3632  AddStream(1);
   3633  ASSERT_TRUE(Gather());
   3634  Connect();
   3635  SendReceive();
   3636 }
   3637 
   3638 TEST_F(WebRtcIceConnectTest, TestSendReceiveTcp) {
   3639  NrIceCtx::GlobalConfig config;
   3640  config.mTcpEnabled = true;
   3641  NrIceCtx::InitializeGlobals(config);
   3642  Init();
   3643  AddStream(1);
   3644  ASSERT_TRUE(Gather());
   3645  SetCandidateFilter(IsTcpCandidate);
   3646  SetExpectedTypes(NrIceCandidate::Type::ICE_HOST,
   3647                   NrIceCandidate::Type::ICE_HOST, kNrIceTransportTcp);
   3648  Connect();
   3649  SendReceive();
   3650 }
   3651 
   3652 // TCP SO tests works on localhost only with delay applied:
   3653 //  tc qdisc add dev lo root netem delay 10ms
   3654 TEST_F(WebRtcIceConnectTest, DISABLED_TestSendReceiveTcpSo) {
   3655  NrIceCtx::GlobalConfig config;
   3656  config.mTcpEnabled = true;
   3657  NrIceCtx::InitializeGlobals(config);
   3658  Init();
   3659  AddStream(1);
   3660  ASSERT_TRUE(Gather());
   3661  SetCandidateFilter(IsTcpSoCandidate);
   3662  SetExpectedTypes(NrIceCandidate::Type::ICE_HOST,
   3663                   NrIceCandidate::Type::ICE_HOST, kNrIceTransportTcp);
   3664  Connect();
   3665  SendReceive();
   3666 }
   3667 
   3668 TEST_F(WebRtcIceConnectTest, TestConsent) {
   3669  NrIceCtx::GlobalConfig config;
   3670  config.mTcpEnabled = false;
   3671  NrIceCtx::InitializeGlobals(config);
   3672  AddStream(1);
   3673  SetupAndCheckConsent();
   3674  PR_Sleep(1500);
   3675  AssertConsentRefresh();
   3676  SendReceive();
   3677 }
   3678 
   3679 TEST_F(WebRtcIceConnectTest, TestConsentTcp) {
   3680  NrIceCtx::GlobalConfig config;
   3681  config.mTcpEnabled = true;
   3682  NrIceCtx::InitializeGlobals(config);
   3683  Init();
   3684  AddStream(1);
   3685  SetCandidateFilter(IsTcpCandidate);
   3686  SetExpectedTypes(NrIceCandidate::Type::ICE_HOST,
   3687                   NrIceCandidate::Type::ICE_HOST, kNrIceTransportTcp);
   3688  SetupAndCheckConsent();
   3689  PR_Sleep(1500);
   3690  AssertConsentRefresh();
   3691  SendReceive();
   3692 }
   3693 
   3694 TEST_F(WebRtcIceConnectTest, TestConsentIntermittent) {
   3695  NrIceCtx::GlobalConfig config;
   3696  config.mTcpEnabled = false;
   3697  NrIceCtx::InitializeGlobals(config);
   3698  AddStream(1);
   3699  SetupAndCheckConsent();
   3700  p1_->SetBlockStun(true);
   3701  p2_->SetBlockStun(true);
   3702  WaitForDisconnected();
   3703  AssertConsentRefresh(CONSENT_STALE);
   3704  SendReceive();
   3705  p1_->SetBlockStun(false);
   3706  p2_->SetBlockStun(false);
   3707  WaitForConnected();
   3708  AssertConsentRefresh();
   3709  SendReceive();
   3710  p1_->SetBlockStun(true);
   3711  p2_->SetBlockStun(true);
   3712  WaitForDisconnected();
   3713  AssertConsentRefresh(CONSENT_STALE);
   3714  SendReceive();
   3715  p1_->SetBlockStun(false);
   3716  p2_->SetBlockStun(false);
   3717  WaitForConnected();
   3718  AssertConsentRefresh();
   3719 }
   3720 
   3721 TEST_F(WebRtcIceConnectTest, TestConsentTimeout) {
   3722  NrIceCtx::GlobalConfig config;
   3723  config.mTcpEnabled = false;
   3724  NrIceCtx::InitializeGlobals(config);
   3725  AddStream(1);
   3726  SetupAndCheckConsent();
   3727  p1_->SetBlockStun(true);
   3728  p2_->SetBlockStun(true);
   3729  WaitForDisconnected();
   3730  AssertConsentRefresh(CONSENT_STALE);
   3731  SendReceive();
   3732  WaitForFailed();
   3733  AssertConsentRefresh(CONSENT_EXPIRED);
   3734  SendFailure();
   3735 }
   3736 
   3737 TEST_F(WebRtcIceConnectTest, TestConsentDelayed) {
   3738  NrIceCtx::GlobalConfig config;
   3739  config.mTcpEnabled = false;
   3740  NrIceCtx::InitializeGlobals(config);
   3741  AddStream(1);
   3742  SetupAndCheckConsent();
   3743  /* Note: We don't have a list of STUN transaction IDs of the previously timed
   3744           out consent requests. Thus responses after sending the next consent
   3745           request are ignored. */
   3746  p1_->SetStunResponseDelay(200);
   3747  p2_->SetStunResponseDelay(200);
   3748  PR_Sleep(1000);
   3749  AssertConsentRefresh();
   3750  SendReceive();
   3751 }
   3752 
   3753 TEST_F(WebRtcIceConnectTest, TestNetworkForcedOfflineAndRecovery) {
   3754  NrIceCtx::GlobalConfig config;
   3755  config.mTcpEnabled = false;
   3756  NrIceCtx::InitializeGlobals(config);
   3757  AddStream(1);
   3758  SetupAndCheckConsent();
   3759  p1_->ChangeNetworkStateToOffline();
   3760  ASSERT_TRUE_WAIT(p1_->ice_connected() == 0, kDefaultTimeout);
   3761  // Next round of consent check should switch it back to online
   3762  ASSERT_TRUE_WAIT(p1_->ice_connected(), kDefaultTimeout);
   3763 }
   3764 
   3765 TEST_F(WebRtcIceConnectTest, TestNetworkForcedOfflineTwice) {
   3766  NrIceCtx::GlobalConfig config;
   3767  config.mTcpEnabled = false;
   3768  NrIceCtx::InitializeGlobals(config);
   3769  AddStream(1);
   3770  SetupAndCheckConsent();
   3771  p2_->ChangeNetworkStateToOffline();
   3772  ASSERT_TRUE_WAIT(p2_->ice_connected() == 0, kDefaultTimeout);
   3773  p2_->ChangeNetworkStateToOffline();
   3774  ASSERT_TRUE_WAIT(p2_->ice_connected() == 0, kDefaultTimeout);
   3775 }
   3776 
   3777 TEST_F(WebRtcIceConnectTest, TestNetworkOnlineDoesntChangeState) {
   3778  NrIceCtx::GlobalConfig config;
   3779  config.mTcpEnabled = false;
   3780  NrIceCtx::InitializeGlobals(config);
   3781  AddStream(1);
   3782  SetupAndCheckConsent();
   3783  p2_->ChangeNetworkStateToOnline();
   3784  ASSERT_TRUE(p2_->ice_connected());
   3785  PR_Sleep(1500);
   3786  p2_->ChangeNetworkStateToOnline();
   3787  ASSERT_TRUE(p2_->ice_connected());
   3788 }
   3789 
   3790 TEST_F(WebRtcIceConnectTest, TestNetworkOnlineTriggersConsent) {
   3791  NrIceCtx::GlobalConfig config;
   3792  config.mTcpEnabled = false;
   3793  NrIceCtx::InitializeGlobals(config);
   3794  // Let's emulate audio + video w/o rtcp-mux
   3795  AddStream(2);
   3796  AddStream(2);
   3797  SetupAndCheckConsent();
   3798  p1_->ChangeNetworkStateToOffline();
   3799  p1_->SetBlockStun(true);
   3800  ASSERT_TRUE_WAIT(p1_->ice_connected() == 0, kDefaultTimeout);
   3801  PR_Sleep(1500);
   3802  ASSERT_TRUE(p1_->ice_connected() == 0);
   3803  p1_->SetBlockStun(false);
   3804  p1_->ChangeNetworkStateToOnline();
   3805  ASSERT_TRUE_WAIT(p1_->ice_connected(), 500);
   3806 }
   3807 
   3808 TEST_F(WebRtcIceConnectTest, TestConnectTurn) {
   3809  if (turn_server_.empty()) return;
   3810 
   3811  NrIceCtx::GlobalConfig config;
   3812  config.mTcpEnabled = false;
   3813  NrIceCtx::InitializeGlobals(config);
   3814  SetTurnServer(turn_server_, kDefaultStunServerPort, turn_user_,
   3815                turn_password_);
   3816  AddStream(1);
   3817  ASSERT_TRUE(Gather());
   3818  Connect();
   3819 }
   3820 
   3821 TEST_F(WebRtcIceConnectTest, TestConnectTurnWithDelay) {
   3822  if (turn_server_.empty()) return;
   3823 
   3824  NrIceCtx::GlobalConfig config;
   3825  config.mTcpEnabled = false;
   3826  NrIceCtx::InitializeGlobals(config);
   3827  SetTurnServer(turn_server_, kDefaultStunServerPort, turn_user_,
   3828                turn_password_);
   3829  SetCandidateFilter(SabotageHostCandidateAndDropReflexive);
   3830  AddStream(1);
   3831  p1_->Gather();
   3832  PR_Sleep(500);
   3833  p2_->Gather();
   3834  ConnectTrickle(TRICKLE_REAL);
   3835  WaitForGather();
   3836  WaitForConnectedStreams();
   3837 }
   3838 
   3839 TEST_F(WebRtcIceConnectTest, TestConnectTurnWithNormalTrickleDelay) {
   3840  if (turn_server_.empty()) return;
   3841 
   3842  NrIceCtx::GlobalConfig config;
   3843  config.mTcpEnabled = false;
   3844  NrIceCtx::InitializeGlobals(config);
   3845  SetTurnServer(turn_server_, kDefaultStunServerPort, turn_user_,
   3846                turn_password_);
   3847  AddStream(1);
   3848  ASSERT_TRUE(Gather());
   3849  ConnectTrickle();
   3850  RealisticTrickleDelay(p1_->ControlTrickle(0));
   3851  RealisticTrickleDelay(p2_->ControlTrickle(0));
   3852 
   3853  WaitForConnected();
   3854  AssertCheckingReached();
   3855 }
   3856 
   3857 TEST_F(WebRtcIceConnectTest, TestConnectTurnWithNormalTrickleDelayOneSided) {
   3858  if (turn_server_.empty()) return;
   3859 
   3860  NrIceCtx::GlobalConfig config;
   3861  config.mTcpEnabled = false;
   3862  NrIceCtx::InitializeGlobals(config);
   3863  SetTurnServer(turn_server_, kDefaultStunServerPort, turn_user_,
   3864                turn_password_);
   3865  AddStream(1);
   3866  ASSERT_TRUE(Gather());
   3867  ConnectTrickle();
   3868  RealisticTrickleDelay(p1_->ControlTrickle(0));
   3869  p2_->SimulateTrickle(0);
   3870 
   3871  WaitForConnected();
   3872  AssertCheckingReached();
   3873 }
   3874 
   3875 TEST_F(WebRtcIceConnectTest, TestConnectTurnWithLargeTrickleDelay) {
   3876  if (turn_server_.empty()) return;
   3877 
   3878  NrIceCtx::GlobalConfig config;
   3879  config.mTcpEnabled = false;
   3880  NrIceCtx::InitializeGlobals(config);
   3881  SetTurnServer(turn_server_, kDefaultStunServerPort, turn_user_,
   3882                turn_password_);
   3883  SetCandidateFilter(SabotageHostCandidateAndDropReflexive);
   3884  AddStream(1);
   3885  ASSERT_TRUE(Gather());
   3886  ConnectTrickle();
   3887  // Trickle host candidates immediately, but delay relay candidates
   3888  DelayRelayCandidates(p1_->ControlTrickle(0), 3700);
   3889  DelayRelayCandidates(p2_->ControlTrickle(0), 3700);
   3890 
   3891  WaitForConnected();
   3892  AssertCheckingReached();
   3893 }
   3894 
   3895 TEST_F(WebRtcIceConnectTest, TestConnectTurnTcp) {
   3896  if (turn_server_.empty()) return;
   3897 
   3898  NrIceCtx::GlobalConfig config;
   3899  config.mTcpEnabled = false;
   3900  NrIceCtx::InitializeGlobals(config);
   3901  SetTurnServer(turn_server_, kDefaultStunServerPort, turn_user_,
   3902                turn_password_, kNrIceTransportTcp);
   3903  AddStream(1);
   3904  ASSERT_TRUE(Gather());
   3905  Connect();
   3906 }
   3907 
   3908 TEST_F(WebRtcIceConnectTest, TestConnectTurnOnly) {
   3909  if (turn_server_.empty()) return;
   3910 
   3911  NrIceCtx::GlobalConfig config;
   3912  config.mTcpEnabled = false;
   3913  NrIceCtx::InitializeGlobals(config);
   3914  SetTurnServer(turn_server_, kDefaultStunServerPort, turn_user_,
   3915                turn_password_);
   3916  AddStream(1);
   3917  ASSERT_TRUE(Gather());
   3918  SetCandidateFilter(IsRelayCandidate);
   3919  SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
   3920                   NrIceCandidate::Type::ICE_RELAYED);
   3921  Connect();
   3922 }
   3923 
   3924 TEST_F(WebRtcIceConnectTest, TestConnectTurnTcpOnly) {
   3925  if (turn_server_.empty()) return;
   3926 
   3927  NrIceCtx::GlobalConfig config;
   3928  config.mTcpEnabled = false;
   3929  NrIceCtx::InitializeGlobals(config);
   3930  SetTurnServer(turn_server_, kDefaultStunServerPort, turn_user_,
   3931                turn_password_, kNrIceTransportTcp);
   3932  AddStream(1);
   3933  ASSERT_TRUE(Gather());
   3934  SetCandidateFilter(IsRelayCandidate);
   3935  SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
   3936                   NrIceCandidate::Type::ICE_RELAYED, kNrIceTransportTcp);
   3937  Connect();
   3938 }
   3939 
   3940 TEST_F(WebRtcIceConnectTest, TestSendReceiveTurnOnly) {
   3941  if (turn_server_.empty()) return;
   3942 
   3943  NrIceCtx::GlobalConfig config;
   3944  config.mTcpEnabled = false;
   3945  NrIceCtx::InitializeGlobals(config);
   3946  SetTurnServer(turn_server_, kDefaultStunServerPort, turn_user_,
   3947                turn_password_);
   3948  AddStream(1);
   3949  ASSERT_TRUE(Gather());
   3950  SetCandidateFilter(IsRelayCandidate);
   3951  SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
   3952                   NrIceCandidate::Type::ICE_RELAYED);
   3953  Connect();
   3954  SendReceive();
   3955 }
   3956 
   3957 TEST_F(WebRtcIceConnectTest, TestSendReceiveTurnTcpOnly) {
   3958  if (turn_server_.empty()) return;
   3959 
   3960  NrIceCtx::GlobalConfig config;
   3961  config.mTcpEnabled = false;
   3962  NrIceCtx::InitializeGlobals(config);
   3963  SetTurnServer(turn_server_, kDefaultStunServerPort, turn_user_,
   3964                turn_password_, kNrIceTransportTcp);
   3965  AddStream(1);
   3966  ASSERT_TRUE(Gather());
   3967  SetCandidateFilter(IsRelayCandidate);
   3968  SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
   3969                   NrIceCandidate::Type::ICE_RELAYED, kNrIceTransportTcp);
   3970  Connect();
   3971  SendReceive();
   3972 }
   3973 
   3974 TEST_F(WebRtcIceConnectTest, TestSendReceiveTurnBothOnly) {
   3975  if (turn_server_.empty()) return;
   3976 
   3977  NrIceCtx::GlobalConfig config;
   3978  config.mTcpEnabled = false;
   3979  NrIceCtx::InitializeGlobals(config);
   3980  std::vector<NrIceTurnServer> turn_servers;
   3981  std::vector<unsigned char> password_vec(turn_password_.begin(),
   3982                                          turn_password_.end());
   3983  turn_servers.push_back(
   3984      *NrIceTurnServer::Create(turn_server_, kDefaultStunServerPort, turn_user_,
   3985                               password_vec, kNrIceTransportTcp));
   3986  turn_servers.push_back(
   3987      *NrIceTurnServer::Create(turn_server_, kDefaultStunServerPort, turn_user_,
   3988                               password_vec, kNrIceTransportUdp));
   3989  SetTurnServers(turn_servers);
   3990  AddStream(1);
   3991  ASSERT_TRUE(Gather());
   3992  SetCandidateFilter(IsRelayCandidate);
   3993  // UDP is preferred.
   3994  SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
   3995                   NrIceCandidate::Type::ICE_RELAYED, kNrIceTransportUdp);
   3996  Connect();
   3997  SendReceive();
   3998 }
   3999 
   4000 TEST_F(WebRtcIceConnectTest, TestConnectShutdownOneSide) {
   4001  NrIceCtx::GlobalConfig config;
   4002  config.mTcpEnabled = false;
   4003  NrIceCtx::InitializeGlobals(config);
   4004  AddStream(1);
   4005  ASSERT_TRUE(Gather());
   4006  ConnectThenDelete();
   4007 }
   4008 
   4009 TEST_F(WebRtcIceConnectTest, TestPollCandPairsBeforeConnect) {
   4010  NrIceCtx::GlobalConfig config;
   4011  config.mTcpEnabled = false;
   4012  NrIceCtx::InitializeGlobals(config);
   4013  AddStream(1);
   4014  ASSERT_TRUE(Gather());
   4015 
   4016  std::vector<NrIceCandidatePair> pairs;
   4017  nsresult res = p1_->GetCandidatePairs(0, &pairs);
   4018  // There should be no candidate pairs prior to calling Connect()
   4019  ASSERT_EQ(NS_OK, res);
   4020  ASSERT_EQ(0U, pairs.size());
   4021 
   4022  res = p2_->GetCandidatePairs(0, &pairs);
   4023  ASSERT_EQ(NS_OK, res);
   4024  ASSERT_EQ(0U, pairs.size());
   4025 }
   4026 
   4027 TEST_F(WebRtcIceConnectTest, TestPollCandPairsAfterConnect) {
   4028  NrIceCtx::GlobalConfig config;
   4029  config.mTcpEnabled = false;
   4030  NrIceCtx::InitializeGlobals(config);
   4031  AddStream(1);
   4032  ASSERT_TRUE(Gather());
   4033  Connect();
   4034 
   4035  std::vector<NrIceCandidatePair> pairs;
   4036  nsresult r = p1_->GetCandidatePairs(0, &pairs);
   4037  ASSERT_EQ(NS_OK, r);
   4038  // How detailed of a check do we want to do here? If the turn server is
   4039  // functioning, we'll get at least two pairs, but this is probably not
   4040  // something we should assume.
   4041  ASSERT_NE(0U, pairs.size());
   4042  ASSERT_TRUE(p1_->CandidatePairsPriorityDescending(pairs));
   4043  ASSERT_TRUE(ContainsSucceededPair(pairs));
   4044  pairs.clear();
   4045 
   4046  r = p2_->GetCandidatePairs(0, &pairs);
   4047  ASSERT_EQ(NS_OK, r);
   4048  ASSERT_NE(0U, pairs.size());
   4049  ASSERT_TRUE(p2_->CandidatePairsPriorityDescending(pairs));
   4050  ASSERT_TRUE(ContainsSucceededPair(pairs));
   4051 }
   4052 
   4053 // TODO Bug 1259842 - disabled until we find a better way to handle two
   4054 // candidates from different RFC1918 ranges
   4055 TEST_F(WebRtcIceConnectTest, DISABLED_TestHostCandPairingFilter) {
   4056  NrIceCtx::GlobalConfig config;
   4057  config.mTcpEnabled = false;
   4058  NrIceCtx::InitializeGlobals(config);
   4059  Init(false);
   4060  AddStream(1);
   4061  ASSERT_TRUE(Gather());
   4062  SetCandidateFilter(IsIpv4Candidate);
   4063 
   4064  int host_net = p1_->GetCandidatesPrivateIpv4Range(0);
   4065  if (host_net <= 0) {
   4066    // TODO bug 1226838: make this work with multiple private IPs
   4067    FAIL() << "This test needs exactly one private IPv4 host candidate to work"
   4068           << std::endl;
   4069  }
   4070 
   4071  ConnectTrickle();
   4072  AddNonPairableCandidates(p1_->ControlTrickle(0), p1_.get(), 0, host_net,
   4073                           test_utils_);
   4074  AddNonPairableCandidates(p2_->ControlTrickle(0), p2_.get(), 0, host_net,
   4075                           test_utils_);
   4076 
   4077  std::vector<NrIceCandidatePair> pairs;
   4078  p1_->GetCandidatePairs(0, &pairs);
   4079  for (auto p : pairs) {
   4080    std::cerr << "Verifying pair:" << std::endl;
   4081    p1_->DumpCandidatePair(p);
   4082    nr_transport_addr addr;
   4083    nr_str_port_to_transport_addr(p.local.local_addr.host.c_str(), 0,
   4084                                  IPPROTO_UDP, &addr);
   4085    ASSERT_TRUE(nr_transport_addr_get_private_addr_range(&addr) == host_net);
   4086    nr_str_port_to_transport_addr(p.remote.cand_addr.host.c_str(), 0,
   4087                                  IPPROTO_UDP, &addr);
   4088    ASSERT_TRUE(nr_transport_addr_get_private_addr_range(&addr) == host_net);
   4089  }
   4090 }
   4091 
   4092 // TODO Bug 1226838 - See Comment 2 - this test can't work as written
   4093 TEST_F(WebRtcIceConnectTest, DISABLED_TestSrflxCandPairingFilter) {
   4094  if (stun_server_address_.empty()) {
   4095    return;
   4096  }
   4097 
   4098  NrIceCtx::GlobalConfig config;
   4099  config.mTcpEnabled = false;
   4100  NrIceCtx::InitializeGlobals(config);
   4101  Init(false);
   4102  AddStream(1);
   4103  ASSERT_TRUE(Gather());
   4104  SetCandidateFilter(IsSrflxCandidate);
   4105 
   4106  if (p1_->GetCandidatesPrivateIpv4Range(0) <= 0) {
   4107    // TODO bug 1226838: make this work with public IP addresses
   4108    std::cerr << "Don't run this test at IETF meetings!" << std::endl;
   4109    FAIL() << "This test needs one private IPv4 host candidate to work"
   4110           << std::endl;
   4111  }
   4112 
   4113  ConnectTrickle();
   4114  SimulateTrickleP1(0);
   4115  SimulateTrickleP2(0);
   4116 
   4117  std::vector<NrIceCandidatePair> pairs;
   4118  p1_->GetCandidatePairs(0, &pairs);
   4119  for (auto p : pairs) {
   4120    std::cerr << "Verifying P1 pair:" << std::endl;
   4121    p1_->DumpCandidatePair(p);
   4122    nr_transport_addr addr;
   4123    nr_str_port_to_transport_addr(p.local.local_addr.host.c_str(), 0,
   4124                                  IPPROTO_UDP, &addr);
   4125    ASSERT_TRUE(nr_transport_addr_get_private_addr_range(&addr) != 0);
   4126    nr_str_port_to_transport_addr(p.remote.cand_addr.host.c_str(), 0,
   4127                                  IPPROTO_UDP, &addr);
   4128    ASSERT_TRUE(nr_transport_addr_get_private_addr_range(&addr) == 0);
   4129  }
   4130  p2_->GetCandidatePairs(0, &pairs);
   4131  for (auto p : pairs) {
   4132    std::cerr << "Verifying P2 pair:" << std::endl;
   4133    p2_->DumpCandidatePair(p);
   4134    nr_transport_addr addr;
   4135    nr_str_port_to_transport_addr(p.local.local_addr.host.c_str(), 0,
   4136                                  IPPROTO_UDP, &addr);
   4137    ASSERT_TRUE(nr_transport_addr_get_private_addr_range(&addr) != 0);
   4138    nr_str_port_to_transport_addr(p.remote.cand_addr.host.c_str(), 0,
   4139                                  IPPROTO_UDP, &addr);
   4140    ASSERT_TRUE(nr_transport_addr_get_private_addr_range(&addr) == 0);
   4141  }
   4142 }
   4143 
   4144 TEST_F(WebRtcIceConnectTest, TestPollCandPairsDuringConnect) {
   4145  NrIceCtx::GlobalConfig config;
   4146  config.mTcpEnabled = false;
   4147  NrIceCtx::InitializeGlobals(config);
   4148  AddStream(1);
   4149  ASSERT_TRUE(Gather());
   4150 
   4151  p2_->Connect(p1_.get(), TRICKLE_NONE, false);
   4152  p1_->Connect(p2_.get(), TRICKLE_NONE, false);
   4153 
   4154  std::vector<NrIceCandidatePair> pairs1;
   4155  std::vector<NrIceCandidatePair> pairs2;
   4156 
   4157  p1_->StartChecks();
   4158  p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
   4159  p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
   4160 
   4161  p2_->StartChecks();
   4162  p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
   4163  p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
   4164 
   4165  WaitForConnectedStreams();
   4166  p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
   4167  p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
   4168  ASSERT_TRUE(ContainsSucceededPair(pairs1));
   4169  ASSERT_TRUE(ContainsSucceededPair(pairs2));
   4170 }
   4171 
   4172 TEST_F(WebRtcIceConnectTest, TestRLogConnector) {
   4173  NrIceCtx::GlobalConfig config;
   4174  config.mTcpEnabled = false;
   4175  NrIceCtx::InitializeGlobals(config);
   4176  AddStream(1);
   4177  ASSERT_TRUE(Gather());
   4178 
   4179  p2_->Connect(p1_.get(), TRICKLE_NONE, false);
   4180  p1_->Connect(p2_.get(), TRICKLE_NONE, false);
   4181 
   4182  std::vector<NrIceCandidatePair> pairs1;
   4183  std::vector<NrIceCandidatePair> pairs2;
   4184 
   4185  p1_->StartChecks();
   4186  p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
   4187  p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
   4188 
   4189  p2_->StartChecks();
   4190  p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
   4191  p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
   4192 
   4193  WaitForConnectedStreams();
   4194  p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
   4195  p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
   4196  ASSERT_TRUE(ContainsSucceededPair(pairs1));
   4197  ASSERT_TRUE(ContainsSucceededPair(pairs2));
   4198 
   4199  for (auto& p : pairs1) {
   4200    std::deque<std::string> logs;
   4201    std::string substring("CAND-PAIR(");
   4202    substring += p.codeword;
   4203    RLogConnector::GetInstance()->Filter(substring, 0, &logs);
   4204    ASSERT_NE(0U, logs.size());
   4205  }
   4206 
   4207  for (auto& p : pairs2) {
   4208    std::deque<std::string> logs;
   4209    std::string substring("CAND-PAIR(");
   4210    substring += p.codeword;
   4211    RLogConnector::GetInstance()->Filter(substring, 0, &logs);
   4212    ASSERT_NE(0U, logs.size());
   4213  }
   4214 }
   4215 
   4216 // Verify that a bogus candidate doesn't cause crashes on the
   4217 // main thread. See bug 856433.
   4218 TEST_F(WebRtcIceConnectTest, TestBogusCandidate) {
   4219  NrIceCtx::GlobalConfig config;
   4220  config.mTcpEnabled = false;
   4221  NrIceCtx::InitializeGlobals(config);
   4222  AddStream(1);
   4223  Gather();
   4224  ConnectTrickle();
   4225  p1_->ParseCandidate(0, kBogusIceCandidate, "");
   4226 
   4227  std::vector<NrIceCandidatePair> pairs;
   4228  nsresult res = p1_->GetCandidatePairs(0, &pairs);
   4229  ASSERT_EQ(NS_OK, res);
   4230  ASSERT_EQ(0U, pairs.size());
   4231 }
   4232 
   4233 TEST_F(WebRtcIceConnectTest, TestNonMDNSCandidate) {
   4234  NrIceCtx::GlobalConfig config;
   4235  config.mTcpEnabled = false;
   4236  NrIceCtx::InitializeGlobals(config);
   4237  AddStream(1);
   4238  Gather();
   4239  ConnectTrickle();
   4240  p1_->ParseCandidate(0, kUnreachableHostIceCandidate, "");
   4241 
   4242  std::vector<NrIceCandidatePair> pairs;
   4243  nsresult res = p1_->GetCandidatePairs(0, &pairs);
   4244  ASSERT_EQ(NS_OK, res);
   4245  ASSERT_EQ(1U, pairs.size());
   4246  ASSERT_EQ(pairs[0].remote.mdns_addr, "");
   4247 }
   4248 
   4249 TEST_F(WebRtcIceConnectTest, TestMDNSCandidate) {
   4250  NrIceCtx::GlobalConfig config;
   4251  config.mTcpEnabled = false;
   4252  NrIceCtx::InitializeGlobals(config);
   4253  AddStream(1);
   4254  Gather();
   4255  ConnectTrickle();
   4256  p1_->ParseCandidate(0, kUnreachableHostIceCandidate, "host.local");
   4257 
   4258  std::vector<NrIceCandidatePair> pairs;
   4259  nsresult res = p1_->GetCandidatePairs(0, &pairs);
   4260  ASSERT_EQ(NS_OK, res);
   4261  ASSERT_EQ(1U, pairs.size());
   4262  ASSERT_EQ(pairs[0].remote.mdns_addr, "host.local");
   4263 }
   4264 
   4265 TEST_F(WebRtcIcePrioritizerTest, TestPrioritizer) {
   4266  SetPriorizer(::mozilla::CreateInterfacePrioritizer());
   4267 
   4268  AddInterface("0", NR_INTERFACE_TYPE_VPN, 100);  // unknown vpn
   4269  AddInterface("1", NR_INTERFACE_TYPE_VPN | NR_INTERFACE_TYPE_WIRED,
   4270               100);  // wired vpn
   4271  AddInterface("2", NR_INTERFACE_TYPE_VPN | NR_INTERFACE_TYPE_WIFI,
   4272               100);  // wifi vpn
   4273  AddInterface("3", NR_INTERFACE_TYPE_VPN | NR_INTERFACE_TYPE_MOBILE,
   4274               100);                                    // wifi vpn
   4275  AddInterface("4", NR_INTERFACE_TYPE_WIRED, 1000);     // wired, high speed
   4276  AddInterface("5", NR_INTERFACE_TYPE_WIRED, 10);       // wired, low speed
   4277  AddInterface("6", NR_INTERFACE_TYPE_WIFI, 10);        // wifi, low speed
   4278  AddInterface("7", NR_INTERFACE_TYPE_WIFI, 1000);      // wifi, high speed
   4279  AddInterface("8", NR_INTERFACE_TYPE_MOBILE, 10);      // mobile, low speed
   4280  AddInterface("9", NR_INTERFACE_TYPE_MOBILE, 1000);    // mobile, high speed
   4281  AddInterface("10", NR_INTERFACE_TYPE_UNKNOWN, 10);    // unknown, low speed
   4282  AddInterface("11", NR_INTERFACE_TYPE_UNKNOWN, 1000);  // unknown, high speed
   4283 
   4284  // expected preference "4" > "5" > "1" > "7" > "6" > "2" > "9" > "8" > "3" >
   4285  // "11" > "10" > "0"
   4286 
   4287  HasLowerPreference("0", "10");
   4288  HasLowerPreference("10", "11");
   4289  HasLowerPreference("11", "3");
   4290  HasLowerPreference("3", "8");
   4291  HasLowerPreference("8", "9");
   4292  HasLowerPreference("9", "2");
   4293  HasLowerPreference("2", "6");
   4294  HasLowerPreference("6", "7");
   4295  HasLowerPreference("7", "1");
   4296  HasLowerPreference("1", "5");
   4297  HasLowerPreference("5", "4");
   4298 }
   4299 
   4300 TEST_F(WebRtcIcePacketFilterTest, TestSendNonStunPacket) {
   4301  const unsigned char data[] = "12345abcde";
   4302  TestOutgoing(data, sizeof(data), 123, 45, false);
   4303  TestOutgoingTcp(data, sizeof(data), false);
   4304 }
   4305 
   4306 TEST_F(WebRtcIcePacketFilterTest, TestRecvNonStunPacket) {
   4307  const unsigned char data[] = "12345abcde";
   4308  TestIncoming(data, sizeof(data), 123, 45, false);
   4309  TestIncomingTcp(data, sizeof(data), true);
   4310 }
   4311 
   4312 TEST_F(WebRtcIcePacketFilterTest, TestSendStunPacket) {
   4313  nr_stun_message* msg;
   4314  ASSERT_EQ(0, nr_stun_build_req_no_auth(nullptr, &msg));
   4315  msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
   4316  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4317  TestOutgoing(msg->buffer, msg->length, 123, 45, true);
   4318  TestOutgoingTcp(msg->buffer, msg->length, true);
   4319  TestOutgoingTcpFramed(msg->buffer, msg->length, true);
   4320  ASSERT_EQ(0, nr_stun_message_destroy(&msg));
   4321 }
   4322 
   4323 TEST_F(WebRtcIcePacketFilterTest, TestRecvStunPacketWithoutAPendingId) {
   4324  nr_stun_message* msg;
   4325  ASSERT_EQ(0, nr_stun_build_req_no_auth(nullptr, &msg));
   4326 
   4327  msg->header.id.octet[0] = 1;
   4328  msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
   4329  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4330  TestOutgoing(msg->buffer, msg->length, 123, 45, true);
   4331  TestOutgoingTcp(msg->buffer, msg->length, true);
   4332 
   4333  msg->header.id.octet[0] = 0;
   4334  msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
   4335  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4336  TestIncoming(msg->buffer, msg->length, 123, 45, true);
   4337  TestIncomingTcp(msg->buffer, msg->length, true);
   4338 
   4339  ASSERT_EQ(0, nr_stun_message_destroy(&msg));
   4340 }
   4341 
   4342 TEST_F(WebRtcIcePacketFilterTest, TestRecvStunBindingRequestWithoutAPendingId) {
   4343  nr_stun_message* msg;
   4344  ASSERT_EQ(0, nr_stun_build_req_no_auth(nullptr, &msg));
   4345 
   4346  msg->header.id.octet[0] = 1;
   4347  msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
   4348  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4349  TestIncoming(msg->buffer, msg->length, 123, 45, true);
   4350  TestIncomingTcp(msg->buffer, msg->length, true);
   4351 
   4352  msg->header.id.octet[0] = 1;
   4353  msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
   4354  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4355  TestOutgoing(msg->buffer, msg->length, 123, 45, true);
   4356  TestOutgoingTcp(msg->buffer, msg->length, true);
   4357 
   4358  ASSERT_EQ(0, nr_stun_message_destroy(&msg));
   4359 }
   4360 
   4361 TEST_F(WebRtcIcePacketFilterTest,
   4362       TestRecvStunPacketWithoutAPendingIdTcpFramed) {
   4363  nr_stun_message* msg;
   4364  ASSERT_EQ(0, nr_stun_build_req_no_auth(nullptr, &msg));
   4365 
   4366  msg->header.id.octet[0] = 1;
   4367  msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
   4368  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4369  TestOutgoingTcpFramed(msg->buffer, msg->length, true);
   4370 
   4371  msg->header.id.octet[0] = 0;
   4372  msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
   4373  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4374  TestIncomingTcpFramed(msg->buffer, msg->length, true);
   4375 
   4376  ASSERT_EQ(0, nr_stun_message_destroy(&msg));
   4377 }
   4378 
   4379 TEST_F(WebRtcIcePacketFilterTest, TestRecvStunPacketWithoutAPendingAddress) {
   4380  nr_stun_message* msg;
   4381  ASSERT_EQ(0, nr_stun_build_req_no_auth(nullptr, &msg));
   4382 
   4383  msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
   4384  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4385  TestOutgoing(msg->buffer, msg->length, 123, 45, true);
   4386  // nothing to test here for the TCP filter
   4387 
   4388  msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
   4389  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4390  TestIncoming(msg->buffer, msg->length, 123, 46, false);
   4391  TestIncoming(msg->buffer, msg->length, 124, 45, false);
   4392 
   4393  ASSERT_EQ(0, nr_stun_message_destroy(&msg));
   4394 }
   4395 
   4396 TEST_F(WebRtcIcePacketFilterTest, TestRecvStunPacketWithPendingIdAndAddress) {
   4397  nr_stun_message* msg;
   4398  ASSERT_EQ(0, nr_stun_build_req_no_auth(nullptr, &msg));
   4399 
   4400  msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
   4401  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4402  TestOutgoing(msg->buffer, msg->length, 123, 45, true);
   4403  TestOutgoingTcp(msg->buffer, msg->length, true);
   4404 
   4405  msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
   4406  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4407  TestIncoming(msg->buffer, msg->length, 123, 45, true);
   4408  TestIncomingTcp(msg->buffer, msg->length, true);
   4409 
   4410  // Test whitelist by filtering non-stun packets.
   4411  const unsigned char data[] = "12345abcde";
   4412 
   4413  // 123:45 is white-listed.
   4414  TestOutgoing(data, sizeof(data), 123, 45, true);
   4415  TestOutgoingTcp(data, sizeof(data), true);
   4416  TestIncoming(data, sizeof(data), 123, 45, true);
   4417  TestIncomingTcp(data, sizeof(data), true);
   4418 
   4419  // Indications pass as well.
   4420  msg->header.type = NR_STUN_MSG_BINDING_INDICATION;
   4421  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4422  TestOutgoing(msg->buffer, msg->length, 123, 45, true);
   4423  TestOutgoingTcp(msg->buffer, msg->length, true);
   4424  TestIncoming(msg->buffer, msg->length, 123, 45, true);
   4425  TestIncomingTcp(msg->buffer, msg->length, true);
   4426 
   4427  // Packets from and to other address are still disallowed.
   4428  // Note: this doesn't apply for TCP connections
   4429  TestOutgoing(data, sizeof(data), 123, 46, false);
   4430  TestIncoming(data, sizeof(data), 123, 46, false);
   4431  TestOutgoing(data, sizeof(data), 124, 45, false);
   4432  TestIncoming(data, sizeof(data), 124, 45, false);
   4433 
   4434  ASSERT_EQ(0, nr_stun_message_destroy(&msg));
   4435 }
   4436 
   4437 TEST_F(WebRtcIcePacketFilterTest, TestRecvStunPacketWithPendingIdTcpFramed) {
   4438  nr_stun_message* msg;
   4439  ASSERT_EQ(0, nr_stun_build_req_no_auth(nullptr, &msg));
   4440 
   4441  msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
   4442  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4443  TestOutgoingTcpFramed(msg->buffer, msg->length, true);
   4444 
   4445  msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
   4446  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4447  TestIncomingTcpFramed(msg->buffer, msg->length, true);
   4448 
   4449  // Test whitelist by filtering non-stun packets.
   4450  const unsigned char data[] = "12345abcde";
   4451 
   4452  TestOutgoingTcpFramed(data, sizeof(data), true);
   4453  TestIncomingTcpFramed(data, sizeof(data), true);
   4454 
   4455  ASSERT_EQ(0, nr_stun_message_destroy(&msg));
   4456 }
   4457 
   4458 TEST_F(WebRtcIcePacketFilterTest, TestSendNonRequestStunPacket) {
   4459  nr_stun_message* msg;
   4460  ASSERT_EQ(0, nr_stun_build_req_no_auth(nullptr, &msg));
   4461 
   4462  msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
   4463  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4464  TestOutgoing(msg->buffer, msg->length, 123, 45, false);
   4465  TestOutgoingTcp(msg->buffer, msg->length, false);
   4466 
   4467  // Send a packet so we allow the incoming request.
   4468  msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
   4469  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4470  TestOutgoing(msg->buffer, msg->length, 123, 45, true);
   4471  TestOutgoingTcp(msg->buffer, msg->length, true);
   4472 
   4473  // This packet makes us able to send a response.
   4474  msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
   4475  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4476  TestIncoming(msg->buffer, msg->length, 123, 45, true);
   4477  TestIncomingTcp(msg->buffer, msg->length, true);
   4478 
   4479  msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
   4480  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4481  TestOutgoing(msg->buffer, msg->length, 123, 45, true);
   4482  TestOutgoingTcp(msg->buffer, msg->length, true);
   4483 
   4484  ASSERT_EQ(0, nr_stun_message_destroy(&msg));
   4485 }
   4486 
   4487 TEST_F(WebRtcIcePacketFilterTest, TestRecvDataPacketWithAPendingAddress) {
   4488  nr_stun_message* msg;
   4489  ASSERT_EQ(0, nr_stun_build_req_no_auth(nullptr, &msg));
   4490 
   4491  msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
   4492  ASSERT_EQ(0, nr_stun_encode_message(msg));
   4493  TestOutgoing(msg->buffer, msg->length, 123, 45, true);
   4494  TestOutgoingTcp(msg->buffer, msg->length, true);
   4495 
   4496  const unsigned char data[] = "12345abcde";
   4497  TestIncoming(data, sizeof(data), 123, 45, true);
   4498  TestIncomingTcp(data, sizeof(data), true);
   4499 
   4500  ASSERT_EQ(0, nr_stun_message_destroy(&msg));
   4501 }
   4502 
   4503 TEST(WebRtcIceInternalsTest, TestAddBogusAttribute)
   4504 {
   4505  nr_stun_message* req;
   4506  ASSERT_EQ(0, nr_stun_message_create(&req));
   4507  Data* data;
   4508  ASSERT_EQ(0, r_data_alloc(&data, 3000));
   4509  memset(data->data, 'A', data->len);
   4510  ASSERT_TRUE(nr_stun_message_add_message_integrity_attribute(req, data));
   4511  ASSERT_EQ(0, r_data_destroy(&data));
   4512  ASSERT_EQ(0, nr_stun_message_destroy(&req));
   4513 }