Coverage Report

Created: 2018-09-25 14:53

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