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