media/mtransport/test/ice_unittest.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=2 et sw=2 tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 // Original author: ekr@rtfm.com
michael@0 8
michael@0 9 #include <algorithm>
michael@0 10 #include <deque>
michael@0 11 #include <iostream>
michael@0 12 #include <limits>
michael@0 13 #include <map>
michael@0 14 #include <string>
michael@0 15 #include <vector>
michael@0 16
michael@0 17 #include "sigslot.h"
michael@0 18
michael@0 19 #include "logging.h"
michael@0 20 #include "nspr.h"
michael@0 21 #include "nss.h"
michael@0 22 #include "ssl.h"
michael@0 23
michael@0 24 #include "mozilla/Scoped.h"
michael@0 25 #include "nsThreadUtils.h"
michael@0 26 #include "nsXPCOM.h"
michael@0 27
michael@0 28 #include "nricectx.h"
michael@0 29 #include "nricemediastream.h"
michael@0 30 #include "nriceresolverfake.h"
michael@0 31 #include "nriceresolver.h"
michael@0 32 #include "nrinterfaceprioritizer.h"
michael@0 33 #include "mtransport_test_utils.h"
michael@0 34 #include "gtest_ringbuffer_dumper.h"
michael@0 35 #include "rlogringbuffer.h"
michael@0 36 #include "runnable_utils.h"
michael@0 37 #include "stunserver.h"
michael@0 38 // TODO(bcampen@mozilla.com): Big fat hack since the build system doesn't give
michael@0 39 // us a clean way to add object files to a single executable.
michael@0 40 #include "stunserver.cpp"
michael@0 41 #include "stun_udp_socket_filter.h"
michael@0 42 #include "mozilla/net/DNS.h"
michael@0 43
michael@0 44 #define GTEST_HAS_RTTI 0
michael@0 45 #include "gtest/gtest.h"
michael@0 46 #include "gtest_utils.h"
michael@0 47
michael@0 48 using namespace mozilla;
michael@0 49 MtransportTestUtils *test_utils;
michael@0 50
michael@0 51 bool stream_added = false;
michael@0 52
michael@0 53 static int kDefaultTimeout = 7000;
michael@0 54
michael@0 55 const std::string kDefaultStunServerAddress((char *)"23.21.150.121");
michael@0 56 const std::string kDefaultStunServerHostname(
michael@0 57 (char *)"ec2-23-21-150-121.compute-1.amazonaws.com");
michael@0 58 const std::string kBogusStunServerHostname(
michael@0 59 (char *)"stun-server-nonexistent.invalid");
michael@0 60 const uint16_t kDefaultStunServerPort=3478;
michael@0 61 const std::string kBogusIceCandidate(
michael@0 62 (char *)"candidate:0 2 UDP 2113601790 192.168.178.20 50769 typ");
michael@0 63
michael@0 64 std::string g_stun_server_address(kDefaultStunServerAddress);
michael@0 65 std::string g_stun_server_hostname(kDefaultStunServerHostname);
michael@0 66 std::string g_turn_server;
michael@0 67 std::string g_turn_user;
michael@0 68 std::string g_turn_password;
michael@0 69
michael@0 70 namespace {
michael@0 71
michael@0 72 enum TrickleMode { TRICKLE_NONE, TRICKLE_SIMULATE, TRICKLE_REAL };
michael@0 73
michael@0 74 typedef bool (*CandidateFilter)(const std::string& candidate);
michael@0 75
michael@0 76 static bool IsRelayCandidate(const std::string& candidate) {
michael@0 77 return candidate.find("typ relay") != std::string::npos;
michael@0 78 }
michael@0 79
michael@0 80 bool ContainsSucceededPair(const std::vector<NrIceCandidatePair>& pairs) {
michael@0 81 for (size_t i = 0; i < pairs.size(); ++i) {
michael@0 82 if (pairs[i].state == NrIceCandidatePair::STATE_SUCCEEDED) {
michael@0 83 return true;
michael@0 84 }
michael@0 85 }
michael@0 86 return false;
michael@0 87 }
michael@0 88
michael@0 89 // Note: Does not correspond to any notion of prioritization; this is just
michael@0 90 // so we can use stl containers/algorithms that need a comparator
michael@0 91 bool operator<(const NrIceCandidate& lhs,
michael@0 92 const NrIceCandidate& rhs) {
michael@0 93 if (lhs.cand_addr.host == rhs.cand_addr.host) {
michael@0 94 if (lhs.cand_addr.port == rhs.cand_addr.port) {
michael@0 95 if (lhs.cand_addr.transport == rhs.cand_addr.transport) {
michael@0 96 return lhs.type < rhs.type;
michael@0 97 }
michael@0 98 return lhs.cand_addr.transport < rhs.cand_addr.transport;
michael@0 99 }
michael@0 100 return lhs.cand_addr.port < rhs.cand_addr.port;
michael@0 101 }
michael@0 102 return lhs.cand_addr.host < rhs.cand_addr.host;
michael@0 103 }
michael@0 104
michael@0 105 bool operator==(const NrIceCandidate& lhs,
michael@0 106 const NrIceCandidate& rhs) {
michael@0 107 return !((lhs < rhs) || (rhs < lhs));
michael@0 108 }
michael@0 109
michael@0 110 class IceCandidatePairCompare {
michael@0 111 public:
michael@0 112 bool operator()(const NrIceCandidatePair& lhs,
michael@0 113 const NrIceCandidatePair& rhs) const {
michael@0 114 if (lhs.priority == rhs.priority) {
michael@0 115 if (lhs.local == rhs.local) {
michael@0 116 if (lhs.remote == rhs.remote) {
michael@0 117 return lhs.codeword < rhs.codeword;
michael@0 118 }
michael@0 119 return lhs.remote < rhs.remote;
michael@0 120 }
michael@0 121 return lhs.local < rhs.local;
michael@0 122 }
michael@0 123 return lhs.priority < rhs.priority;
michael@0 124 }
michael@0 125 };
michael@0 126
michael@0 127 class IceTestPeer : public sigslot::has_slots<> {
michael@0 128 public:
michael@0 129
michael@0 130 IceTestPeer(const std::string& name, bool offerer, bool set_priorities) :
michael@0 131 name_(name),
michael@0 132 ice_ctx_(NrIceCtx::Create(name, offerer, set_priorities)),
michael@0 133 streams_(),
michael@0 134 candidates_(),
michael@0 135 gathering_complete_(false),
michael@0 136 ready_ct_(0),
michael@0 137 ice_complete_(false),
michael@0 138 received_(0),
michael@0 139 sent_(0),
michael@0 140 fake_resolver_(),
michael@0 141 dns_resolver_(new NrIceResolver()),
michael@0 142 remote_(nullptr),
michael@0 143 candidate_filter_(nullptr),
michael@0 144 expected_local_type_(NrIceCandidate::ICE_HOST),
michael@0 145 expected_local_transport_(kNrIceTransportUdp),
michael@0 146 expected_remote_type_(NrIceCandidate::ICE_HOST),
michael@0 147 trickle_mode_(TRICKLE_NONE),
michael@0 148 trickled_(0) {
michael@0 149 ice_ctx_->SignalGatheringStateChange.connect(
michael@0 150 this,
michael@0 151 &IceTestPeer::GatheringStateChange);
michael@0 152 ice_ctx_->SignalConnectionStateChange.connect(
michael@0 153 this,
michael@0 154 &IceTestPeer::ConnectionStateChange);
michael@0 155 }
michael@0 156
michael@0 157 ~IceTestPeer() {
michael@0 158 test_utils->sts_target()->Dispatch(WrapRunnable(this,
michael@0 159 &IceTestPeer::Shutdown),
michael@0 160 NS_DISPATCH_SYNC);
michael@0 161
michael@0 162 // Give the ICE destruction callback time to fire before
michael@0 163 // we destroy the resolver.
michael@0 164 PR_Sleep(1000);
michael@0 165 }
michael@0 166
michael@0 167 void AddStream(int components) {
michael@0 168 char name[100];
michael@0 169 snprintf(name, sizeof(name), "%s:stream%d", name_.c_str(),
michael@0 170 (int)streams_.size());
michael@0 171
michael@0 172 mozilla::RefPtr<NrIceMediaStream> stream =
michael@0 173 ice_ctx_->CreateStream(static_cast<char *>(name), components);
michael@0 174
michael@0 175 ASSERT_TRUE(stream);
michael@0 176 streams_.push_back(stream);
michael@0 177 stream->SignalCandidate.connect(this, &IceTestPeer::CandidateInitialized);
michael@0 178 stream->SignalReady.connect(this, &IceTestPeer::StreamReady);
michael@0 179 stream->SignalFailed.connect(this, &IceTestPeer::StreamFailed);
michael@0 180 stream->SignalPacketReceived.connect(this, &IceTestPeer::PacketReceived);
michael@0 181 }
michael@0 182
michael@0 183 void SetStunServer(const std::string addr, uint16_t port) {
michael@0 184 std::vector<NrIceStunServer> stun_servers;
michael@0 185 ScopedDeletePtr<NrIceStunServer> server(NrIceStunServer::Create(addr,
michael@0 186 port));
michael@0 187 stun_servers.push_back(*server);
michael@0 188 ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetStunServers(stun_servers)));
michael@0 189 }
michael@0 190
michael@0 191 void SetTurnServer(const std::string addr, uint16_t port,
michael@0 192 const std::string username,
michael@0 193 const std::string password,
michael@0 194 const char* transport) {
michael@0 195 std::vector<unsigned char> password_vec(password.begin(), password.end());
michael@0 196 SetTurnServer(addr, port, username, password_vec, transport);
michael@0 197 }
michael@0 198
michael@0 199
michael@0 200 void SetTurnServer(const std::string addr, uint16_t port,
michael@0 201 const std::string username,
michael@0 202 const std::vector<unsigned char> password,
michael@0 203 const char* transport) {
michael@0 204 std::vector<NrIceTurnServer> turn_servers;
michael@0 205 ScopedDeletePtr<NrIceTurnServer> server(NrIceTurnServer::Create(
michael@0 206 addr, port, username, password, transport));
michael@0 207 turn_servers.push_back(*server);
michael@0 208 ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetTurnServers(turn_servers)));
michael@0 209 }
michael@0 210
michael@0 211 void SetTurnServers(const std::vector<NrIceTurnServer> servers) {
michael@0 212 ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetTurnServers(servers)));
michael@0 213 }
michael@0 214
michael@0 215 void SetFakeResolver() {
michael@0 216 ASSERT_TRUE(NS_SUCCEEDED(dns_resolver_->Init()));
michael@0 217 PRNetAddr addr;
michael@0 218 PRStatus status = PR_StringToNetAddr(g_stun_server_address.c_str(),
michael@0 219 &addr);
michael@0 220 addr.inet.port = kDefaultStunServerPort;
michael@0 221 ASSERT_EQ(PR_SUCCESS, status);
michael@0 222 fake_resolver_.SetAddr(g_stun_server_hostname, addr);
michael@0 223 ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetResolver(
michael@0 224 fake_resolver_.AllocateResolver())));
michael@0 225 }
michael@0 226
michael@0 227 void SetDNSResolver() {
michael@0 228 ASSERT_TRUE(NS_SUCCEEDED(dns_resolver_->Init()));
michael@0 229 ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetResolver(
michael@0 230 dns_resolver_->AllocateResolver())));
michael@0 231 }
michael@0 232
michael@0 233 void Gather() {
michael@0 234 nsresult res;
michael@0 235
michael@0 236 test_utils->sts_target()->Dispatch(
michael@0 237 WrapRunnableRet(ice_ctx_, &NrIceCtx::StartGathering, &res),
michael@0 238 NS_DISPATCH_SYNC);
michael@0 239
michael@0 240 ASSERT_TRUE(NS_SUCCEEDED(res));
michael@0 241 }
michael@0 242
michael@0 243 // Get various pieces of state
michael@0 244 std::vector<std::string> GetGlobalAttributes() {
michael@0 245 return ice_ctx_->GetGlobalAttributes();
michael@0 246 }
michael@0 247
michael@0 248 std::vector<std::string> GetCandidates(size_t stream) {
michael@0 249 std::vector<std::string> v;
michael@0 250
michael@0 251 RUN_ON_THREAD(
michael@0 252 test_utils->sts_target(),
michael@0 253 WrapRunnableRet(this, &IceTestPeer::GetCandidates_s, stream, &v),
michael@0 254 NS_DISPATCH_SYNC);
michael@0 255
michael@0 256 return v;
michael@0 257 }
michael@0 258
michael@0 259 std::vector<std::string> GetCandidates_s(size_t stream) {
michael@0 260 std::vector<std::string> candidates;
michael@0 261
michael@0 262 if (stream >= streams_.size())
michael@0 263 return candidates;
michael@0 264
michael@0 265 std::vector<std::string> candidates_in =
michael@0 266 streams_[stream]->GetCandidates();
michael@0 267
michael@0 268
michael@0 269 for (size_t i=0; i < candidates_in.size(); i++) {
michael@0 270 if ((!candidate_filter_) || candidate_filter_(candidates_in[i])) {
michael@0 271 std::cerr << "Returning candidate: " << candidates_in[i] << std::endl;
michael@0 272 candidates.push_back(candidates_in[i]);
michael@0 273 }
michael@0 274 }
michael@0 275
michael@0 276 return candidates;
michael@0 277 }
michael@0 278
michael@0 279 void SetExpectedTypes(NrIceCandidate::Type local,
michael@0 280 NrIceCandidate::Type remote,
michael@0 281 std::string local_transport = kNrIceTransportUdp) {
michael@0 282 expected_local_type_ = local;
michael@0 283 expected_local_transport_ = local_transport;
michael@0 284 expected_remote_type_ = remote;
michael@0 285 }
michael@0 286
michael@0 287 bool gathering_complete() { return gathering_complete_; }
michael@0 288 int ready_ct() { return ready_ct_; }
michael@0 289 bool is_ready(size_t stream) {
michael@0 290 return streams_[stream]->state() == NrIceMediaStream::ICE_OPEN;
michael@0 291 }
michael@0 292 bool ice_complete() { return ice_complete_; }
michael@0 293 size_t received() { return received_; }
michael@0 294 size_t sent() { return sent_; }
michael@0 295
michael@0 296 // Start connecting to another peer
michael@0 297 void Connect_s(IceTestPeer *remote, TrickleMode trickle_mode,
michael@0 298 bool start = true) {
michael@0 299 nsresult res;
michael@0 300
michael@0 301 remote_ = remote;
michael@0 302
michael@0 303 trickle_mode_ = trickle_mode;
michael@0 304 res = ice_ctx_->ParseGlobalAttributes(remote->GetGlobalAttributes());
michael@0 305 ASSERT_TRUE(NS_SUCCEEDED(res));
michael@0 306
michael@0 307 if (trickle_mode == TRICKLE_NONE ||
michael@0 308 trickle_mode == TRICKLE_REAL) {
michael@0 309 for (size_t i=0; i<streams_.size(); ++i) {
michael@0 310 std::vector<std::string> candidates =
michael@0 311 remote->GetCandidates(i);
michael@0 312
michael@0 313 for (size_t j=0; j<candidates.size(); ++j) {
michael@0 314 std::cerr << "Candidate: " + candidates[j] << std::endl;
michael@0 315 }
michael@0 316 res = streams_[i]->ParseAttributes(candidates);
michael@0 317 ASSERT_TRUE(NS_SUCCEEDED(res));
michael@0 318 }
michael@0 319 } else {
michael@0 320 // Parse empty attributes and then trickle them out later
michael@0 321 for (size_t i=0; i<streams_.size(); ++i) {
michael@0 322 std::vector<std::string> empty_attrs;
michael@0 323 res = streams_[i]->ParseAttributes(empty_attrs);
michael@0 324 ASSERT_TRUE(NS_SUCCEEDED(res));
michael@0 325 }
michael@0 326 }
michael@0 327
michael@0 328 if (start) {
michael@0 329 // Now start checks
michael@0 330 res = ice_ctx_->StartChecks();
michael@0 331 ASSERT_TRUE(NS_SUCCEEDED(res));
michael@0 332 }
michael@0 333 }
michael@0 334
michael@0 335 void Connect(IceTestPeer *remote, TrickleMode trickle_mode,
michael@0 336 bool start = true) {
michael@0 337 test_utils->sts_target()->Dispatch(
michael@0 338 WrapRunnable(
michael@0 339 this, &IceTestPeer::Connect_s, remote, trickle_mode, start),
michael@0 340 NS_DISPATCH_SYNC);
michael@0 341 }
michael@0 342
michael@0 343 void SimulateTrickle(size_t stream) {
michael@0 344 std::cerr << "Doing trickle for stream " << stream << std::endl;
michael@0 345 // If we are in trickle deferred mode, now trickle in the candidates
michael@0 346 // for |stream}
michael@0 347 nsresult res;
michael@0 348
michael@0 349 ASSERT_GT(remote_->streams_.size(), stream);
michael@0 350
michael@0 351 std::vector<std::string> candidates =
michael@0 352 remote_->GetCandidates(stream);
michael@0 353
michael@0 354 for (size_t j=0; j<candidates.size(); j++) {
michael@0 355 test_utils->sts_target()->Dispatch(
michael@0 356 WrapRunnableRet(streams_[stream],
michael@0 357 &NrIceMediaStream::ParseTrickleCandidate,
michael@0 358 candidates[j],
michael@0 359 &res), NS_DISPATCH_SYNC);
michael@0 360
michael@0 361 ASSERT_TRUE(NS_SUCCEEDED(res));
michael@0 362 }
michael@0 363 }
michael@0 364
michael@0 365 void DumpCandidate(std::string which, const NrIceCandidate& cand) {
michael@0 366 std::string type;
michael@0 367
michael@0 368 switch(cand.type) {
michael@0 369 case NrIceCandidate::ICE_HOST:
michael@0 370 type = "host";
michael@0 371 break;
michael@0 372 case NrIceCandidate::ICE_SERVER_REFLEXIVE:
michael@0 373 type = "srflx";
michael@0 374 break;
michael@0 375 case NrIceCandidate::ICE_PEER_REFLEXIVE:
michael@0 376 type = "prflx";
michael@0 377 break;
michael@0 378 case NrIceCandidate::ICE_RELAYED:
michael@0 379 type = "relay";
michael@0 380 if (which.find("Local") != std::string::npos) {
michael@0 381 type += "(" + cand.local_addr.transport + ")";
michael@0 382 }
michael@0 383 break;
michael@0 384 default:
michael@0 385 FAIL();
michael@0 386 };
michael@0 387
michael@0 388 std::cerr << which
michael@0 389 << " --> "
michael@0 390 << type
michael@0 391 << " "
michael@0 392 << cand.local_addr.host
michael@0 393 << ":"
michael@0 394 << cand.local_addr.port
michael@0 395 << " codeword="
michael@0 396 << cand.codeword
michael@0 397 << std::endl;
michael@0 398 }
michael@0 399
michael@0 400 void DumpAndCheckActiveCandidates_s() {
michael@0 401 std::cerr << "Active candidates:" << std::endl;
michael@0 402 for (size_t i=0; i < streams_.size(); ++i) {
michael@0 403 for (int j=0; j < streams_[i]->components(); ++j) {
michael@0 404 std::cerr << "Stream " << i << " component " << j+1 << std::endl;
michael@0 405
michael@0 406 NrIceCandidate *local;
michael@0 407 NrIceCandidate *remote;
michael@0 408
michael@0 409 nsresult res = streams_[i]->GetActivePair(j+1, &local, &remote);
michael@0 410 if (res == NS_ERROR_NOT_AVAILABLE) {
michael@0 411 std::cerr << "Component unpaired or disabled." << std::endl;
michael@0 412 } else {
michael@0 413 ASSERT_TRUE(NS_SUCCEEDED(res));
michael@0 414 DumpCandidate("Local ", *local);
michael@0 415 ASSERT_EQ(expected_local_type_, local->type);
michael@0 416 ASSERT_EQ(expected_local_transport_, local->local_addr.transport);
michael@0 417 DumpCandidate("Remote ", *remote);
michael@0 418 ASSERT_EQ(expected_remote_type_, remote->type);
michael@0 419 delete local;
michael@0 420 delete remote;
michael@0 421 }
michael@0 422 }
michael@0 423 }
michael@0 424 }
michael@0 425
michael@0 426 void DumpAndCheckActiveCandidates() {
michael@0 427 test_utils->sts_target()->Dispatch(
michael@0 428 WrapRunnable(this, &IceTestPeer::DumpAndCheckActiveCandidates_s),
michael@0 429 NS_DISPATCH_SYNC);
michael@0 430 }
michael@0 431
michael@0 432 void Close() {
michael@0 433 test_utils->sts_target()->Dispatch(
michael@0 434 WrapRunnable(ice_ctx_, &NrIceCtx::destroy_peer_ctx),
michael@0 435 NS_DISPATCH_SYNC);
michael@0 436 }
michael@0 437
michael@0 438 void Shutdown() {
michael@0 439 ice_ctx_ = nullptr;
michael@0 440 }
michael@0 441
michael@0 442 void StartChecks() {
michael@0 443 nsresult res;
michael@0 444
michael@0 445 // Now start checks
michael@0 446 test_utils->sts_target()->Dispatch(
michael@0 447 WrapRunnableRet(ice_ctx_, &NrIceCtx::StartChecks, &res),
michael@0 448 NS_DISPATCH_SYNC);
michael@0 449 ASSERT_TRUE(NS_SUCCEEDED(res));
michael@0 450 }
michael@0 451
michael@0 452 // Handle events
michael@0 453 void GatheringStateChange(NrIceCtx* ctx,
michael@0 454 NrIceCtx::GatheringState state) {
michael@0 455 (void)ctx;
michael@0 456 if (state != NrIceCtx::ICE_CTX_GATHER_COMPLETE) {
michael@0 457 return;
michael@0 458 }
michael@0 459
michael@0 460 std::cerr << "Gathering complete for " << name_ << std::endl;
michael@0 461 gathering_complete_ = true;
michael@0 462
michael@0 463 std::cerr << "CANDIDATES:" << std::endl;
michael@0 464 for (size_t i=0; i<streams_.size(); ++i) {
michael@0 465 std::cerr << "Stream " << name_ << std::endl;
michael@0 466 std::vector<std::string> candidates =
michael@0 467 streams_[i]->GetCandidates();
michael@0 468
michael@0 469 for(size_t j=0; j<candidates.size(); ++j) {
michael@0 470 std::cerr << candidates[j] << std::endl;
michael@0 471 }
michael@0 472 }
michael@0 473 std::cerr << std::endl;
michael@0 474
michael@0 475 }
michael@0 476
michael@0 477 void CandidateInitialized(NrIceMediaStream *stream, const std::string &candidate) {
michael@0 478 std::cerr << "Candidate initialized: " << candidate << std::endl;
michael@0 479 candidates_[stream->name()].push_back(candidate);
michael@0 480
michael@0 481 // If we are connected, then try to trickle to the
michael@0 482 // other side.
michael@0 483 if (remote_ && remote_->remote_) {
michael@0 484 std::vector<mozilla::RefPtr<NrIceMediaStream> >::iterator it =
michael@0 485 std::find(streams_.begin(), streams_.end(), stream);
michael@0 486 ASSERT_NE(streams_.end(), it);
michael@0 487 size_t index = it - streams_.begin();
michael@0 488
michael@0 489 ASSERT_GT(remote_->streams_.size(), index);
michael@0 490 nsresult res = remote_->streams_[index]->ParseTrickleCandidate(
michael@0 491 candidate);
michael@0 492 ASSERT_TRUE(NS_SUCCEEDED(res));
michael@0 493 ++trickled_;
michael@0 494 }
michael@0 495 }
michael@0 496
michael@0 497 nsresult GetCandidatePairs(size_t stream_index,
michael@0 498 std::vector<NrIceCandidatePair>* pairs) {
michael@0 499 MOZ_ASSERT(pairs);
michael@0 500 if (stream_index >= streams_.size()) {
michael@0 501 // Is there a better error for "no such index"?
michael@0 502 ADD_FAILURE() << "No such media stream index: " << stream_index;
michael@0 503 return NS_ERROR_INVALID_ARG;
michael@0 504 }
michael@0 505
michael@0 506 nsresult res;
michael@0 507 test_utils->sts_target()->Dispatch(
michael@0 508 WrapRunnableRet(streams_[stream_index],
michael@0 509 &NrIceMediaStream::GetCandidatePairs,
michael@0 510 pairs,
michael@0 511 &res),
michael@0 512 NS_DISPATCH_SYNC);
michael@0 513 return res;
michael@0 514 }
michael@0 515
michael@0 516 void DumpCandidatePair(const NrIceCandidatePair& pair) {
michael@0 517 std::cerr << std::endl;
michael@0 518 DumpCandidate("Local", pair.local);
michael@0 519 DumpCandidate("Remote", pair.remote);
michael@0 520 std::cerr << "state = " << pair.state
michael@0 521 << " priority = " << pair.priority
michael@0 522 << " nominated = " << pair.nominated
michael@0 523 << " selected = " << pair.selected
michael@0 524 << " codeword = " << pair.codeword << std::endl;
michael@0 525 }
michael@0 526
michael@0 527 void DumpCandidatePairs(NrIceMediaStream *stream) {
michael@0 528 std::vector<NrIceCandidatePair> pairs;
michael@0 529 nsresult res = stream->GetCandidatePairs(&pairs);
michael@0 530 ASSERT_TRUE(NS_SUCCEEDED(res));
michael@0 531
michael@0 532 std::cerr << "Begin list of candidate pairs [" << std::endl;
michael@0 533
michael@0 534 for (std::vector<NrIceCandidatePair>::iterator p = pairs.begin();
michael@0 535 p != pairs.end(); ++p) {
michael@0 536 DumpCandidatePair(*p);
michael@0 537 }
michael@0 538 std::cerr << "]" << std::endl;
michael@0 539 }
michael@0 540
michael@0 541 void DumpCandidatePairs() {
michael@0 542 std::cerr << "Dumping candidate pairs for all streams [" << std::endl;
michael@0 543 for (size_t s = 0; s < streams_.size(); ++s) {
michael@0 544 DumpCandidatePairs(streams_[s]);
michael@0 545 }
michael@0 546 std::cerr << "]" << std::endl;
michael@0 547 }
michael@0 548
michael@0 549 bool CandidatePairsPriorityDescending(const std::vector<NrIceCandidatePair>&
michael@0 550 pairs) {
michael@0 551 // Verify that priority is descending
michael@0 552 uint64_t priority = std::numeric_limits<uint64_t>::max();
michael@0 553
michael@0 554 for (size_t p = 0; p < pairs.size(); ++p) {
michael@0 555 if (priority < pairs[p].priority) {
michael@0 556 std::cerr << "Priority increased in subsequent pairs:" << std::endl;
michael@0 557 DumpCandidatePair(pairs[p-1]);
michael@0 558 DumpCandidatePair(pairs[p]);
michael@0 559 return false;
michael@0 560 } else if (priority == pairs[p].priority) {
michael@0 561 std::cerr << "Duplicate priority in subseqent pairs:" << std::endl;
michael@0 562 DumpCandidatePair(pairs[p-1]);
michael@0 563 DumpCandidatePair(pairs[p]);
michael@0 564 return false;
michael@0 565 }
michael@0 566 priority = pairs[p].priority;
michael@0 567 }
michael@0 568 return true;
michael@0 569 }
michael@0 570
michael@0 571 void UpdateAndValidateCandidatePairs(size_t stream_index,
michael@0 572 std::vector<NrIceCandidatePair>*
michael@0 573 new_pairs) {
michael@0 574 std::vector<NrIceCandidatePair> old_pairs = *new_pairs;
michael@0 575 GetCandidatePairs(stream_index, new_pairs);
michael@0 576 ASSERT_TRUE(CandidatePairsPriorityDescending(*new_pairs)) << "New list of "
michael@0 577 "candidate pairs is either not sorted in priority order, or has "
michael@0 578 "duplicate priorities.";
michael@0 579 ASSERT_TRUE(CandidatePairsPriorityDescending(old_pairs)) << "Old list of "
michael@0 580 "candidate pairs is either not sorted in priority order, or has "
michael@0 581 "duplicate priorities. This indicates some bug in the test case.";
michael@0 582 std::vector<NrIceCandidatePair> added_pairs;
michael@0 583 std::vector<NrIceCandidatePair> removed_pairs;
michael@0 584
michael@0 585 // set_difference computes the set of elements that are present in the
michael@0 586 // first set, but not the second
michael@0 587 // NrIceCandidatePair::operator< compares based on the priority, local
michael@0 588 // candidate, and remote candidate in that order. This means this will
michael@0 589 // catch cases where the priority has remained the same, but one of the
michael@0 590 // candidates has changed.
michael@0 591 std::set_difference((*new_pairs).begin(),
michael@0 592 (*new_pairs).end(),
michael@0 593 old_pairs.begin(),
michael@0 594 old_pairs.end(),
michael@0 595 std::inserter(added_pairs, added_pairs.begin()),
michael@0 596 IceCandidatePairCompare());
michael@0 597
michael@0 598 std::set_difference(old_pairs.begin(),
michael@0 599 old_pairs.end(),
michael@0 600 (*new_pairs).begin(),
michael@0 601 (*new_pairs).end(),
michael@0 602 std::inserter(removed_pairs, removed_pairs.begin()),
michael@0 603 IceCandidatePairCompare());
michael@0 604
michael@0 605 for (std::vector<NrIceCandidatePair>::iterator a = added_pairs.begin();
michael@0 606 a != added_pairs.end(); ++a) {
michael@0 607 std::cerr << "Found new candidate pair." << std::endl;
michael@0 608 DumpCandidatePair(*a);
michael@0 609 }
michael@0 610
michael@0 611 for (std::vector<NrIceCandidatePair>::iterator r = removed_pairs.begin();
michael@0 612 r != removed_pairs.end(); ++r) {
michael@0 613 std::cerr << "Pre-existing candidate pair is now missing:" << std::endl;
michael@0 614 DumpCandidatePair(*r);
michael@0 615 }
michael@0 616
michael@0 617 ASSERT_TRUE(removed_pairs.empty()) << "At least one candidate pair has "
michael@0 618 "gone missing.";
michael@0 619 }
michael@0 620
michael@0 621 void StreamReady(NrIceMediaStream *stream) {
michael@0 622 ++ready_ct_;
michael@0 623 std::cerr << "Stream ready " << stream->name() << " ct=" << ready_ct_ << std::endl;
michael@0 624 DumpCandidatePairs(stream);
michael@0 625 }
michael@0 626 void StreamFailed(NrIceMediaStream *stream) {
michael@0 627 std::cerr << "Stream failed " << stream->name() << " ct=" << ready_ct_ << std::endl;
michael@0 628 DumpCandidatePairs(stream);
michael@0 629 }
michael@0 630
michael@0 631 void ConnectionStateChange(NrIceCtx* ctx,
michael@0 632 NrIceCtx::ConnectionState state) {
michael@0 633 (void)ctx;
michael@0 634 if (state != NrIceCtx::ICE_CTX_OPEN) {
michael@0 635 return;
michael@0 636 }
michael@0 637 std::cerr << "ICE completed " << name_ << std::endl;
michael@0 638 ice_complete_ = true;
michael@0 639 }
michael@0 640
michael@0 641 void PacketReceived(NrIceMediaStream *stream, int component, const unsigned char *data,
michael@0 642 int len) {
michael@0 643 std::cerr << "Received " << len << " bytes" << std::endl;
michael@0 644 ++received_;
michael@0 645 }
michael@0 646
michael@0 647 void SendPacket(int stream, int component, const unsigned char *data,
michael@0 648 int len) {
michael@0 649 ASSERT_TRUE(NS_SUCCEEDED(streams_[stream]->SendPacket(component, data, len)));
michael@0 650
michael@0 651 ++sent_;
michael@0 652 std::cerr << "Sent " << len << " bytes" << std::endl;
michael@0 653 }
michael@0 654
michael@0 655 void SetCandidateFilter(CandidateFilter filter) {
michael@0 656 candidate_filter_ = filter;
michael@0 657 }
michael@0 658
michael@0 659 // Allow us to parse candidates directly on the current thread.
michael@0 660 void ParseCandidate(size_t i, const std::string& candidate) {
michael@0 661 std::vector<std::string> attributes;
michael@0 662
michael@0 663 attributes.push_back(candidate);
michael@0 664 streams_[i]->ParseAttributes(attributes);
michael@0 665 }
michael@0 666
michael@0 667 void DisableComponent(size_t stream, int component_id) {
michael@0 668 ASSERT_LT(stream, streams_.size());
michael@0 669 nsresult res = streams_[stream]->DisableComponent(component_id);
michael@0 670 ASSERT_TRUE(NS_SUCCEEDED(res));
michael@0 671 }
michael@0 672
michael@0 673 int trickled() { return trickled_; }
michael@0 674
michael@0 675 private:
michael@0 676 std::string name_;
michael@0 677 nsRefPtr<NrIceCtx> ice_ctx_;
michael@0 678 std::vector<mozilla::RefPtr<NrIceMediaStream> > streams_;
michael@0 679 std::map<std::string, std::vector<std::string> > candidates_;
michael@0 680 bool gathering_complete_;
michael@0 681 int ready_ct_;
michael@0 682 bool ice_complete_;
michael@0 683 size_t received_;
michael@0 684 size_t sent_;
michael@0 685 NrIceResolverFake fake_resolver_;
michael@0 686 nsRefPtr<NrIceResolver> dns_resolver_;
michael@0 687 IceTestPeer *remote_;
michael@0 688 CandidateFilter candidate_filter_;
michael@0 689 NrIceCandidate::Type expected_local_type_;
michael@0 690 std::string expected_local_transport_;
michael@0 691 NrIceCandidate::Type expected_remote_type_;
michael@0 692 TrickleMode trickle_mode_;
michael@0 693 int trickled_;
michael@0 694 };
michael@0 695
michael@0 696 class IceGatherTest : public ::testing::Test {
michael@0 697 public:
michael@0 698 void SetUp() {
michael@0 699 test_utils->sts_target()->Dispatch(WrapRunnable(TestStunServer::GetInstance(),
michael@0 700 &TestStunServer::Reset),
michael@0 701 NS_DISPATCH_SYNC);
michael@0 702 peer_ = new IceTestPeer("P1", true, false);
michael@0 703 peer_->AddStream(1);
michael@0 704 }
michael@0 705
michael@0 706 void Gather(bool wait = true) {
michael@0 707 peer_->Gather();
michael@0 708
michael@0 709 if (wait) {
michael@0 710 WaitForGather();
michael@0 711 }
michael@0 712 }
michael@0 713
michael@0 714 void WaitForGather() {
michael@0 715 ASSERT_TRUE_WAIT(peer_->gathering_complete(), kDefaultTimeout);
michael@0 716 }
michael@0 717
michael@0 718 void UseFakeStunServerWithResponse(const std::string& fake_addr,
michael@0 719 uint16_t fake_port) {
michael@0 720 TestStunServer::GetInstance()->SetResponseAddr(fake_addr, fake_port);
michael@0 721 // Sets an additional stun server
michael@0 722 peer_->SetStunServer(TestStunServer::GetInstance()->addr(),
michael@0 723 TestStunServer::GetInstance()->port());
michael@0 724 }
michael@0 725
michael@0 726 // NB: Only does substring matching, watch out for stuff like "1.2.3.4"
michael@0 727 // matching "21.2.3.47". " 1.2.3.4 " should not have false positives.
michael@0 728 bool StreamHasMatchingCandidate(unsigned int stream,
michael@0 729 const std::string& match) {
michael@0 730 std::vector<std::string> candidates = peer_->GetCandidates(stream);
michael@0 731 for (size_t c = 0; c < candidates.size(); ++c) {
michael@0 732 if (std::string::npos != candidates[c].find(match)) {
michael@0 733 return true;
michael@0 734 }
michael@0 735 }
michael@0 736 return false;
michael@0 737 }
michael@0 738
michael@0 739 protected:
michael@0 740 mozilla::ScopedDeletePtr<IceTestPeer> peer_;
michael@0 741 };
michael@0 742
michael@0 743 class IceConnectTest : public ::testing::Test {
michael@0 744 public:
michael@0 745 IceConnectTest() : initted_(false) {}
michael@0 746
michael@0 747 void SetUp() {
michael@0 748 nsresult rv;
michael@0 749 target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
michael@0 750 ASSERT_TRUE(NS_SUCCEEDED(rv));
michael@0 751 }
michael@0 752
michael@0 753 void AddStream(const std::string& name, int components) {
michael@0 754 Init(false);
michael@0 755 p1_->AddStream(components);
michael@0 756 p2_->AddStream(components);
michael@0 757 }
michael@0 758
michael@0 759 void Init(bool set_priorities) {
michael@0 760 if (!initted_) {
michael@0 761 p1_ = new IceTestPeer("P1", true, set_priorities);
michael@0 762 p2_ = new IceTestPeer("P2", false, set_priorities);
michael@0 763 }
michael@0 764 initted_ = true;
michael@0 765 }
michael@0 766
michael@0 767 bool Gather(bool wait) {
michael@0 768 Init(false);
michael@0 769 p1_->SetStunServer(g_stun_server_address, kDefaultStunServerPort);
michael@0 770 p2_->SetStunServer(g_stun_server_address, kDefaultStunServerPort);
michael@0 771 p1_->Gather();
michael@0 772 p2_->Gather();
michael@0 773
michael@0 774 if (wait) {
michael@0 775 EXPECT_TRUE_WAIT(p1_->gathering_complete(), kDefaultTimeout);
michael@0 776 if (!p1_->gathering_complete())
michael@0 777 return false;
michael@0 778 EXPECT_TRUE_WAIT(p2_->gathering_complete(), kDefaultTimeout);
michael@0 779 if (!p2_->gathering_complete())
michael@0 780 return false;
michael@0 781 }
michael@0 782 return true;
michael@0 783 }
michael@0 784
michael@0 785 void SetTurnServer(const std::string addr, uint16_t port,
michael@0 786 const std::string username,
michael@0 787 const std::string password,
michael@0 788 const char* transport = kNrIceTransportUdp) {
michael@0 789 p1_->SetTurnServer(addr, port, username, password, transport);
michael@0 790 p2_->SetTurnServer(addr, port, username, password, transport);
michael@0 791 }
michael@0 792
michael@0 793 void SetTurnServers(const std::vector<NrIceTurnServer>& servers) {
michael@0 794 p1_->SetTurnServers(servers);
michael@0 795 p2_->SetTurnServers(servers);
michael@0 796 }
michael@0 797
michael@0 798 void SetCandidateFilter(CandidateFilter filter, bool both=true) {
michael@0 799 p1_->SetCandidateFilter(filter);
michael@0 800 if (both) {
michael@0 801 p2_->SetCandidateFilter(filter);
michael@0 802 }
michael@0 803 }
michael@0 804
michael@0 805 void Connect() {
michael@0 806 p1_->Connect(p2_, TRICKLE_NONE);
michael@0 807 p2_->Connect(p1_, TRICKLE_NONE);
michael@0 808
michael@0 809 ASSERT_TRUE_WAIT(p1_->ready_ct() == 1 && p2_->ready_ct() == 1,
michael@0 810 kDefaultTimeout);
michael@0 811 ASSERT_TRUE_WAIT(p1_->ice_complete() && p2_->ice_complete(),
michael@0 812 kDefaultTimeout);
michael@0 813
michael@0 814 p1_->DumpAndCheckActiveCandidates();
michael@0 815 p2_->DumpAndCheckActiveCandidates();
michael@0 816 }
michael@0 817
michael@0 818 void SetExpectedTypes(NrIceCandidate::Type local, NrIceCandidate::Type remote,
michael@0 819 std::string transport = kNrIceTransportUdp) {
michael@0 820 p1_->SetExpectedTypes(local, remote, transport);
michael@0 821 p2_->SetExpectedTypes(local, remote, transport);
michael@0 822 }
michael@0 823
michael@0 824 void SetExpectedTypes(NrIceCandidate::Type local1, NrIceCandidate::Type remote1,
michael@0 825 NrIceCandidate::Type local2, NrIceCandidate::Type remote2) {
michael@0 826 p1_->SetExpectedTypes(local1, remote1);
michael@0 827 p2_->SetExpectedTypes(local2, remote2);
michael@0 828 }
michael@0 829
michael@0 830 void ConnectP1(TrickleMode mode = TRICKLE_NONE) {
michael@0 831 p1_->Connect(p2_, mode);
michael@0 832 }
michael@0 833
michael@0 834 void ConnectP2(TrickleMode mode = TRICKLE_NONE) {
michael@0 835 p2_->Connect(p1_, mode);
michael@0 836 }
michael@0 837
michael@0 838 void WaitForComplete(int expected_streams = 1) {
michael@0 839 ASSERT_TRUE_WAIT(p1_->ready_ct() == expected_streams &&
michael@0 840 p2_->ready_ct() == expected_streams, kDefaultTimeout);
michael@0 841 ASSERT_TRUE_WAIT(p1_->ice_complete() && p2_->ice_complete(),
michael@0 842 kDefaultTimeout);
michael@0 843 }
michael@0 844
michael@0 845 void WaitForGather() {
michael@0 846 ASSERT_TRUE_WAIT(p1_->gathering_complete(), kDefaultTimeout);
michael@0 847 ASSERT_TRUE_WAIT(p2_->gathering_complete(), kDefaultTimeout);
michael@0 848 }
michael@0 849
michael@0 850 void ConnectTrickle(TrickleMode trickle = TRICKLE_SIMULATE) {
michael@0 851 p1_->Connect(p2_, trickle);
michael@0 852 p2_->Connect(p1_, trickle);
michael@0 853 }
michael@0 854
michael@0 855 void SimulateTrickle(size_t stream) {
michael@0 856 p1_->SimulateTrickle(stream);
michael@0 857 p2_->SimulateTrickle(stream);
michael@0 858 ASSERT_TRUE_WAIT(p1_->is_ready(stream), kDefaultTimeout);
michael@0 859 ASSERT_TRUE_WAIT(p2_->is_ready(stream), kDefaultTimeout);
michael@0 860 }
michael@0 861
michael@0 862 void SimulateTrickleP1(size_t stream) {
michael@0 863 p1_->SimulateTrickle(stream);
michael@0 864 }
michael@0 865
michael@0 866 void SimulateTrickleP2(size_t stream) {
michael@0 867 p2_->SimulateTrickle(stream);
michael@0 868 }
michael@0 869
michael@0 870 void VerifyConnected() {
michael@0 871 }
michael@0 872
michael@0 873 void CloseP1() {
michael@0 874 p1_->Close();
michael@0 875 }
michael@0 876
michael@0 877 void ConnectThenDelete() {
michael@0 878 p1_->Connect(p2_, TRICKLE_NONE, true);
michael@0 879 p2_->Connect(p1_, TRICKLE_NONE, false);
michael@0 880 test_utils->sts_target()->Dispatch(WrapRunnable(this,
michael@0 881 &IceConnectTest::CloseP1),
michael@0 882 NS_DISPATCH_SYNC);
michael@0 883 p2_->StartChecks();
michael@0 884
michael@0 885 // Wait to see if we crash
michael@0 886 PR_Sleep(PR_MillisecondsToInterval(kDefaultTimeout));
michael@0 887 }
michael@0 888
michael@0 889 void SendReceive() {
michael@0 890 // p1_->Send(2);
michael@0 891 test_utils->sts_target()->Dispatch(
michael@0 892 WrapRunnable(p1_.get(),
michael@0 893 &IceTestPeer::SendPacket, 0, 1,
michael@0 894 reinterpret_cast<const unsigned char *>("TEST"), 4),
michael@0 895 NS_DISPATCH_SYNC);
michael@0 896 ASSERT_EQ(1u, p1_->sent());
michael@0 897 ASSERT_TRUE_WAIT(p2_->received() == 1, 1000);
michael@0 898 }
michael@0 899
michael@0 900 protected:
michael@0 901 bool initted_;
michael@0 902 nsCOMPtr<nsIEventTarget> target_;
michael@0 903 mozilla::ScopedDeletePtr<IceTestPeer> p1_;
michael@0 904 mozilla::ScopedDeletePtr<IceTestPeer> p2_;
michael@0 905 };
michael@0 906
michael@0 907 class PrioritizerTest : public ::testing::Test {
michael@0 908 public:
michael@0 909 PrioritizerTest():
michael@0 910 prioritizer_(nullptr) {}
michael@0 911
michael@0 912 ~PrioritizerTest() {
michael@0 913 if (prioritizer_) {
michael@0 914 nr_interface_prioritizer_destroy(&prioritizer_);
michael@0 915 }
michael@0 916 }
michael@0 917
michael@0 918 void SetPriorizer(nr_interface_prioritizer *prioritizer) {
michael@0 919 prioritizer_ = prioritizer;
michael@0 920 }
michael@0 921
michael@0 922 void AddInterface(const std::string& num, int type, int estimated_speed) {
michael@0 923 std::string str_addr = "10.0.0." + num;
michael@0 924 std::string ifname = "eth" + num;
michael@0 925 nr_local_addr local_addr;
michael@0 926 local_addr.interface.type = type;
michael@0 927 local_addr.interface.estimated_speed = estimated_speed;
michael@0 928
michael@0 929 int r = nr_ip4_str_port_to_transport_addr(str_addr.c_str(), 0,
michael@0 930 IPPROTO_UDP, &(local_addr.addr));
michael@0 931 ASSERT_EQ(0, r);
michael@0 932 strncpy(local_addr.addr.ifname, ifname.c_str(), MAXIFNAME);
michael@0 933
michael@0 934 r = nr_interface_prioritizer_add_interface(prioritizer_, &local_addr);
michael@0 935 ASSERT_EQ(0, r);
michael@0 936 r = nr_interface_prioritizer_sort_preference(prioritizer_);
michael@0 937 ASSERT_EQ(0, r);
michael@0 938 }
michael@0 939
michael@0 940 void HasLowerPreference(const std::string& num1, const std::string& num2) {
michael@0 941 std::string key1 = "eth" + num1 + ":10.0.0." + num1;
michael@0 942 std::string key2 = "eth" + num2 + ":10.0.0." + num2;
michael@0 943 UCHAR pref1, pref2;
michael@0 944 int r = nr_interface_prioritizer_get_priority(prioritizer_, key1.c_str(), &pref1);
michael@0 945 ASSERT_EQ(0, r);
michael@0 946 r = nr_interface_prioritizer_get_priority(prioritizer_, key2.c_str(), &pref2);
michael@0 947 ASSERT_EQ(0, r);
michael@0 948 ASSERT_LE(pref1, pref2);
michael@0 949 }
michael@0 950
michael@0 951 private:
michael@0 952 nr_interface_prioritizer *prioritizer_;
michael@0 953 };
michael@0 954
michael@0 955 class PacketFilterTest : public ::testing::Test {
michael@0 956 public:
michael@0 957 PacketFilterTest(): filter_(nullptr) {}
michael@0 958
michael@0 959 void SetUp() {
michael@0 960 nsCOMPtr<nsIUDPSocketFilterHandler> handler =
michael@0 961 do_GetService(NS_STUN_UDP_SOCKET_FILTER_HANDLER_CONTRACTID);
michael@0 962 handler->NewFilter(getter_AddRefs(filter_));
michael@0 963 }
michael@0 964
michael@0 965 void TestIncoming(const uint8_t* data, uint32_t len,
michael@0 966 uint8_t from_addr, int from_port,
michael@0 967 bool expected_result) {
michael@0 968 mozilla::net::NetAddr addr;
michael@0 969 MakeNetAddr(&addr, from_addr, from_port);
michael@0 970 bool result;
michael@0 971 nsresult rv = filter_->FilterPacket(&addr, data, len,
michael@0 972 nsIUDPSocketFilter::SF_INCOMING,
michael@0 973 &result);
michael@0 974 ASSERT_EQ(NS_OK, rv);
michael@0 975 ASSERT_EQ(expected_result, result);
michael@0 976 }
michael@0 977
michael@0 978 void TestOutgoing(const uint8_t* data, uint32_t len,
michael@0 979 uint8_t to_addr, int to_port,
michael@0 980 bool expected_result) {
michael@0 981 mozilla::net::NetAddr addr;
michael@0 982 MakeNetAddr(&addr, to_addr, to_port);
michael@0 983 bool result;
michael@0 984 nsresult rv = filter_->FilterPacket(&addr, data, len,
michael@0 985 nsIUDPSocketFilter::SF_OUTGOING,
michael@0 986 &result);
michael@0 987 ASSERT_EQ(NS_OK, rv);
michael@0 988 ASSERT_EQ(expected_result, result);
michael@0 989 }
michael@0 990
michael@0 991 private:
michael@0 992 void MakeNetAddr(mozilla::net::NetAddr* net_addr,
michael@0 993 uint8_t last_digit, uint16_t port) {
michael@0 994 net_addr->inet.family = AF_INET;
michael@0 995 net_addr->inet.ip = 192 << 24 | 168 << 16 | 1 << 8 | last_digit;
michael@0 996 net_addr->inet.port = port;
michael@0 997 }
michael@0 998
michael@0 999 nsCOMPtr<nsIUDPSocketFilter> filter_;
michael@0 1000 };
michael@0 1001 } // end namespace
michael@0 1002
michael@0 1003 TEST_F(IceGatherTest, TestGatherFakeStunServerHostnameNoResolver) {
michael@0 1004 peer_->SetStunServer(g_stun_server_hostname, kDefaultStunServerPort);
michael@0 1005 Gather();
michael@0 1006 }
michael@0 1007
michael@0 1008 TEST_F(IceGatherTest, TestGatherFakeStunServerIpAddress) {
michael@0 1009 peer_->SetStunServer(g_stun_server_address, kDefaultStunServerPort);
michael@0 1010 peer_->SetFakeResolver();
michael@0 1011 Gather();
michael@0 1012 }
michael@0 1013
michael@0 1014 TEST_F(IceGatherTest, TestGatherFakeStunServerHostname) {
michael@0 1015 peer_->SetStunServer(g_stun_server_hostname, kDefaultStunServerPort);
michael@0 1016 peer_->SetFakeResolver();
michael@0 1017 Gather();
michael@0 1018 }
michael@0 1019
michael@0 1020 TEST_F(IceGatherTest, TestGatherFakeStunBogusHostname) {
michael@0 1021 peer_->SetStunServer(kBogusStunServerHostname, kDefaultStunServerPort);
michael@0 1022 peer_->SetFakeResolver();
michael@0 1023 Gather();
michael@0 1024 }
michael@0 1025
michael@0 1026 TEST_F(IceGatherTest, TestGatherDNSStunServerIpAddress) {
michael@0 1027 peer_->SetStunServer(g_stun_server_address, kDefaultStunServerPort);
michael@0 1028 peer_->SetDNSResolver();
michael@0 1029 Gather();
michael@0 1030 // TODO(jib@mozilla.com): ensure we get server reflexive candidates Bug 848094
michael@0 1031 }
michael@0 1032
michael@0 1033 TEST_F(IceGatherTest, TestGatherDNSStunServerHostname) {
michael@0 1034 peer_->SetStunServer(g_stun_server_hostname, kDefaultStunServerPort);
michael@0 1035 peer_->SetDNSResolver();
michael@0 1036 Gather();
michael@0 1037 }
michael@0 1038
michael@0 1039 TEST_F(IceGatherTest, TestGatherDNSStunBogusHostname) {
michael@0 1040 peer_->SetStunServer(kBogusStunServerHostname, kDefaultStunServerPort);
michael@0 1041 peer_->SetDNSResolver();
michael@0 1042 Gather();
michael@0 1043 }
michael@0 1044
michael@0 1045 TEST_F(IceGatherTest, TestGatherTurn) {
michael@0 1046 if (g_turn_server.empty())
michael@0 1047 return;
michael@0 1048 peer_->SetTurnServer(g_turn_server, kDefaultStunServerPort,
michael@0 1049 g_turn_user, g_turn_password, kNrIceTransportUdp);
michael@0 1050 Gather();
michael@0 1051 }
michael@0 1052
michael@0 1053 TEST_F(IceGatherTest, TestGatherTurnTcp) {
michael@0 1054 if (g_turn_server.empty())
michael@0 1055 return;
michael@0 1056 peer_->SetTurnServer(g_turn_server, kDefaultStunServerPort,
michael@0 1057 g_turn_user, g_turn_password, kNrIceTransportTcp);
michael@0 1058 Gather();
michael@0 1059 }
michael@0 1060
michael@0 1061 TEST_F(IceGatherTest, TestGatherDisableComponent) {
michael@0 1062 peer_->SetStunServer(kDefaultStunServerHostname, kDefaultStunServerPort);
michael@0 1063 peer_->AddStream(2);
michael@0 1064 peer_->DisableComponent(1, 2);
michael@0 1065 Gather();
michael@0 1066 std::vector<std::string> candidates =
michael@0 1067 peer_->GetCandidates(1);
michael@0 1068
michael@0 1069 for (size_t i=0; i<candidates.size(); ++i) {
michael@0 1070 size_t sp1 = candidates[i].find(' ');
michael@0 1071 ASSERT_EQ(0, candidates[i].compare(sp1+1, 1, "1", 1));
michael@0 1072 }
michael@0 1073 }
michael@0 1074
michael@0 1075
michael@0 1076 // Verify that a bogus candidate doesn't cause crashes on the
michael@0 1077 // main thread. See bug 856433.
michael@0 1078 TEST_F(IceGatherTest, TestBogusCandidate) {
michael@0 1079 Gather();
michael@0 1080 peer_->ParseCandidate(0, kBogusIceCandidate);
michael@0 1081 }
michael@0 1082
michael@0 1083 TEST_F(IceGatherTest, VerifyTestStunServer) {
michael@0 1084 UseFakeStunServerWithResponse("192.0.2.133", 3333);
michael@0 1085 Gather();
michael@0 1086 ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.2.133 3333 "));
michael@0 1087 }
michael@0 1088
michael@0 1089 TEST_F(IceGatherTest, TestStunServerReturnsWildcardAddr) {
michael@0 1090 UseFakeStunServerWithResponse("0.0.0.0", 3333);
michael@0 1091 Gather();
michael@0 1092 ASSERT_FALSE(StreamHasMatchingCandidate(0, " 0.0.0.0 "));
michael@0 1093 }
michael@0 1094
michael@0 1095 TEST_F(IceGatherTest, TestStunServerReturnsPort0) {
michael@0 1096 UseFakeStunServerWithResponse("192.0.2.133", 0);
michael@0 1097 Gather();
michael@0 1098 ASSERT_FALSE(StreamHasMatchingCandidate(0, " 192.0.2.133 0 "));
michael@0 1099 }
michael@0 1100
michael@0 1101 TEST_F(IceGatherTest, TestStunServerReturnsLoopbackAddr) {
michael@0 1102 UseFakeStunServerWithResponse("127.0.0.133", 3333);
michael@0 1103 Gather();
michael@0 1104 ASSERT_FALSE(StreamHasMatchingCandidate(0, " 127.0.0.133 "));
michael@0 1105 }
michael@0 1106
michael@0 1107 TEST_F(IceGatherTest, TestStunServerTrickle) {
michael@0 1108 UseFakeStunServerWithResponse("192.0.2.1", 3333);
michael@0 1109 TestStunServer::GetInstance()->SetActive(false);
michael@0 1110 Gather(false);
michael@0 1111 ASSERT_FALSE(StreamHasMatchingCandidate(0, "192.0.2.1"));
michael@0 1112 TestStunServer::GetInstance()->SetActive(true);
michael@0 1113 WaitForGather();
michael@0 1114 ASSERT_TRUE(StreamHasMatchingCandidate(0, "192.0.2.1"));
michael@0 1115 }
michael@0 1116
michael@0 1117 TEST_F(IceConnectTest, TestGather) {
michael@0 1118 AddStream("first", 1);
michael@0 1119 ASSERT_TRUE(Gather(true));
michael@0 1120 }
michael@0 1121
michael@0 1122 TEST_F(IceConnectTest, TestGatherAutoPrioritize) {
michael@0 1123 Init(false);
michael@0 1124 AddStream("first", 1);
michael@0 1125 ASSERT_TRUE(Gather(true));
michael@0 1126 }
michael@0 1127
michael@0 1128
michael@0 1129 TEST_F(IceConnectTest, TestConnect) {
michael@0 1130 AddStream("first", 1);
michael@0 1131 ASSERT_TRUE(Gather(true));
michael@0 1132 Connect();
michael@0 1133 }
michael@0 1134
michael@0 1135 TEST_F(IceConnectTest, TestConnectTwoComponents) {
michael@0 1136 AddStream("first", 2);
michael@0 1137 ASSERT_TRUE(Gather(true));
michael@0 1138 Connect();
michael@0 1139 }
michael@0 1140
michael@0 1141 TEST_F(IceConnectTest, TestConnectTwoComponentsDisableSecond) {
michael@0 1142 AddStream("first", 2);
michael@0 1143 ASSERT_TRUE(Gather(true));
michael@0 1144 p1_->DisableComponent(0, 2);
michael@0 1145 p2_->DisableComponent(0, 2);
michael@0 1146 Connect();
michael@0 1147 }
michael@0 1148
michael@0 1149
michael@0 1150 TEST_F(IceConnectTest, TestConnectP2ThenP1) {
michael@0 1151 AddStream("first", 1);
michael@0 1152 ASSERT_TRUE(Gather(true));
michael@0 1153 ConnectP2();
michael@0 1154 PR_Sleep(1000);
michael@0 1155 ConnectP1();
michael@0 1156 WaitForComplete();
michael@0 1157 }
michael@0 1158
michael@0 1159 TEST_F(IceConnectTest, TestConnectP2ThenP1Trickle) {
michael@0 1160 AddStream("first", 1);
michael@0 1161 ASSERT_TRUE(Gather(true));
michael@0 1162 ConnectP2();
michael@0 1163 PR_Sleep(1000);
michael@0 1164 ConnectP1(TRICKLE_SIMULATE);
michael@0 1165 SimulateTrickleP1(0);
michael@0 1166 WaitForComplete();
michael@0 1167 }
michael@0 1168
michael@0 1169 TEST_F(IceConnectTest, TestConnectP2ThenP1TrickleTwoComponents) {
michael@0 1170 AddStream("first", 1);
michael@0 1171 AddStream("second", 2);
michael@0 1172 ASSERT_TRUE(Gather(true));
michael@0 1173 ConnectP2();
michael@0 1174 PR_Sleep(1000);
michael@0 1175 ConnectP1(TRICKLE_SIMULATE);
michael@0 1176 SimulateTrickleP1(0);
michael@0 1177 std::cerr << "Sleeping between trickle streams" << std::endl;
michael@0 1178 PR_Sleep(1000); // Give this some time to settle but not complete
michael@0 1179 // all of ICE.
michael@0 1180 SimulateTrickleP1(1);
michael@0 1181 WaitForComplete(2);
michael@0 1182 }
michael@0 1183
michael@0 1184 TEST_F(IceConnectTest, TestConnectAutoPrioritize) {
michael@0 1185 Init(false);
michael@0 1186 AddStream("first", 1);
michael@0 1187 ASSERT_TRUE(Gather(true));
michael@0 1188 Connect();
michael@0 1189 }
michael@0 1190
michael@0 1191 TEST_F(IceConnectTest, TestConnectTrickleOneStreamOneComponent) {
michael@0 1192 AddStream("first", 1);
michael@0 1193 ASSERT_TRUE(Gather(true));
michael@0 1194 ConnectTrickle();
michael@0 1195 SimulateTrickle(0);
michael@0 1196 ASSERT_TRUE_WAIT(p1_->ice_complete(), 1000);
michael@0 1197 ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
michael@0 1198 }
michael@0 1199
michael@0 1200 TEST_F(IceConnectTest, TestConnectTrickleTwoStreamsOneComponent) {
michael@0 1201 AddStream("first", 1);
michael@0 1202 AddStream("second", 1);
michael@0 1203 ASSERT_TRUE(Gather(true));
michael@0 1204 ConnectTrickle();
michael@0 1205 SimulateTrickle(0);
michael@0 1206 SimulateTrickle(1);
michael@0 1207 ASSERT_TRUE_WAIT(p1_->ice_complete(), 1000);
michael@0 1208 ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
michael@0 1209 }
michael@0 1210
michael@0 1211 TEST_F(IceConnectTest, TestConnectRealTrickleOneStreamOneComponent) {
michael@0 1212 AddStream("first", 1);
michael@0 1213 AddStream("second", 1);
michael@0 1214 ASSERT_TRUE(Gather(false));
michael@0 1215 ConnectTrickle(TRICKLE_REAL);
michael@0 1216 ASSERT_TRUE_WAIT(p1_->ice_complete(), kDefaultTimeout);
michael@0 1217 ASSERT_TRUE_WAIT(p2_->ice_complete(), kDefaultTimeout);
michael@0 1218 WaitForGather(); // ICE can complete before we finish gathering.
michael@0 1219 }
michael@0 1220
michael@0 1221 TEST_F(IceConnectTest, TestSendReceive) {
michael@0 1222 AddStream("first", 1);
michael@0 1223 ASSERT_TRUE(Gather(true));
michael@0 1224 Connect();
michael@0 1225 SendReceive();
michael@0 1226 }
michael@0 1227
michael@0 1228 TEST_F(IceConnectTest, TestConnectTurn) {
michael@0 1229 if (g_turn_server.empty())
michael@0 1230 return;
michael@0 1231
michael@0 1232 AddStream("first", 1);
michael@0 1233 SetTurnServer(g_turn_server, kDefaultStunServerPort,
michael@0 1234 g_turn_user, g_turn_password);
michael@0 1235 ASSERT_TRUE(Gather(true));
michael@0 1236 Connect();
michael@0 1237 }
michael@0 1238
michael@0 1239 TEST_F(IceConnectTest, TestConnectTurnTcp) {
michael@0 1240 if (g_turn_server.empty())
michael@0 1241 return;
michael@0 1242
michael@0 1243 AddStream("first", 1);
michael@0 1244 SetTurnServer(g_turn_server, kDefaultStunServerPort,
michael@0 1245 g_turn_user, g_turn_password, kNrIceTransportTcp);
michael@0 1246 ASSERT_TRUE(Gather(true));
michael@0 1247 Connect();
michael@0 1248 }
michael@0 1249
michael@0 1250 TEST_F(IceConnectTest, TestConnectTurnOnly) {
michael@0 1251 if (g_turn_server.empty())
michael@0 1252 return;
michael@0 1253
michael@0 1254 AddStream("first", 1);
michael@0 1255 SetTurnServer(g_turn_server, kDefaultStunServerPort,
michael@0 1256 g_turn_user, g_turn_password);
michael@0 1257 ASSERT_TRUE(Gather(true));
michael@0 1258 SetCandidateFilter(IsRelayCandidate);
michael@0 1259 SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
michael@0 1260 NrIceCandidate::Type::ICE_RELAYED);
michael@0 1261 Connect();
michael@0 1262 }
michael@0 1263
michael@0 1264 TEST_F(IceConnectTest, TestConnectTurnTcpOnly) {
michael@0 1265 if (g_turn_server.empty())
michael@0 1266 return;
michael@0 1267
michael@0 1268 AddStream("first", 1);
michael@0 1269 SetTurnServer(g_turn_server, kDefaultStunServerPort,
michael@0 1270 g_turn_user, g_turn_password, kNrIceTransportTcp);
michael@0 1271 ASSERT_TRUE(Gather(true));
michael@0 1272 SetCandidateFilter(IsRelayCandidate);
michael@0 1273 SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
michael@0 1274 NrIceCandidate::Type::ICE_RELAYED,
michael@0 1275 kNrIceTransportTcp);
michael@0 1276 Connect();
michael@0 1277 }
michael@0 1278
michael@0 1279 TEST_F(IceConnectTest, TestSendReceiveTurnOnly) {
michael@0 1280 if (g_turn_server.empty())
michael@0 1281 return;
michael@0 1282
michael@0 1283 AddStream("first", 1);
michael@0 1284 SetTurnServer(g_turn_server, kDefaultStunServerPort,
michael@0 1285 g_turn_user, g_turn_password);
michael@0 1286 ASSERT_TRUE(Gather(true));
michael@0 1287 SetCandidateFilter(IsRelayCandidate);
michael@0 1288 SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
michael@0 1289 NrIceCandidate::Type::ICE_RELAYED);
michael@0 1290 Connect();
michael@0 1291 SendReceive();
michael@0 1292 }
michael@0 1293
michael@0 1294 TEST_F(IceConnectTest, TestSendReceiveTurnTcpOnly) {
michael@0 1295 if (g_turn_server.empty())
michael@0 1296 return;
michael@0 1297
michael@0 1298 AddStream("first", 1);
michael@0 1299 SetTurnServer(g_turn_server, kDefaultStunServerPort,
michael@0 1300 g_turn_user, g_turn_password, kNrIceTransportTcp);
michael@0 1301 ASSERT_TRUE(Gather(true));
michael@0 1302 SetCandidateFilter(IsRelayCandidate);
michael@0 1303 SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
michael@0 1304 NrIceCandidate::Type::ICE_RELAYED,
michael@0 1305 kNrIceTransportTcp);
michael@0 1306 Connect();
michael@0 1307 SendReceive();
michael@0 1308 }
michael@0 1309
michael@0 1310 TEST_F(IceConnectTest, TestSendReceiveTurnBothOnly) {
michael@0 1311 if (g_turn_server.empty())
michael@0 1312 return;
michael@0 1313
michael@0 1314 AddStream("first", 1);
michael@0 1315 std::vector<NrIceTurnServer> turn_servers;
michael@0 1316 std::vector<unsigned char> password_vec(g_turn_password.begin(),
michael@0 1317 g_turn_password.end());
michael@0 1318 turn_servers.push_back(*NrIceTurnServer::Create(
michael@0 1319 g_turn_server, kDefaultStunServerPort,
michael@0 1320 g_turn_user, password_vec, kNrIceTransportTcp));
michael@0 1321 turn_servers.push_back(*NrIceTurnServer::Create(
michael@0 1322 g_turn_server, kDefaultStunServerPort,
michael@0 1323 g_turn_user, password_vec, kNrIceTransportUdp));
michael@0 1324 SetTurnServers(turn_servers);
michael@0 1325 ASSERT_TRUE(Gather(true));
michael@0 1326 SetCandidateFilter(IsRelayCandidate);
michael@0 1327 // UDP is preferred.
michael@0 1328 SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
michael@0 1329 NrIceCandidate::Type::ICE_RELAYED,
michael@0 1330 kNrIceTransportUdp);
michael@0 1331 Connect();
michael@0 1332 SendReceive();
michael@0 1333 }
michael@0 1334
michael@0 1335 TEST_F(IceConnectTest, TestConnectShutdownOneSide) {
michael@0 1336 AddStream("first", 1);
michael@0 1337 ASSERT_TRUE(Gather(true));
michael@0 1338 ConnectThenDelete();
michael@0 1339 }
michael@0 1340
michael@0 1341 TEST_F(IceConnectTest, TestPollCandPairsBeforeConnect) {
michael@0 1342 AddStream("first", 1);
michael@0 1343 ASSERT_TRUE(Gather(true));
michael@0 1344
michael@0 1345 std::vector<NrIceCandidatePair> pairs;
michael@0 1346 nsresult res = p1_->GetCandidatePairs(0, &pairs);
michael@0 1347 // There should be no candidate pairs prior to calling Connect()
michael@0 1348 ASSERT_TRUE(NS_FAILED(res));
michael@0 1349 ASSERT_EQ(0U, pairs.size());
michael@0 1350
michael@0 1351 res = p2_->GetCandidatePairs(0, &pairs);
michael@0 1352 ASSERT_TRUE(NS_FAILED(res));
michael@0 1353 ASSERT_EQ(0U, pairs.size());
michael@0 1354 }
michael@0 1355
michael@0 1356 TEST_F(IceConnectTest, TestPollCandPairsAfterConnect) {
michael@0 1357 AddStream("first", 1);
michael@0 1358 ASSERT_TRUE(Gather(true));
michael@0 1359 Connect();
michael@0 1360
michael@0 1361 std::vector<NrIceCandidatePair> pairs;
michael@0 1362 nsresult r = p1_->GetCandidatePairs(0, &pairs);
michael@0 1363 ASSERT_EQ(NS_OK, r);
michael@0 1364 // How detailed of a check do we want to do here? If the turn server is
michael@0 1365 // functioning, we'll get at least two pairs, but this is probably not
michael@0 1366 // something we should assume.
michael@0 1367 ASSERT_NE(0U, pairs.size());
michael@0 1368 ASSERT_TRUE(p1_->CandidatePairsPriorityDescending(pairs));
michael@0 1369 ASSERT_TRUE(ContainsSucceededPair(pairs));
michael@0 1370 pairs.clear();
michael@0 1371
michael@0 1372 r = p2_->GetCandidatePairs(0, &pairs);
michael@0 1373 ASSERT_EQ(NS_OK, r);
michael@0 1374 ASSERT_NE(0U, pairs.size());
michael@0 1375 ASSERT_TRUE(p2_->CandidatePairsPriorityDescending(pairs));
michael@0 1376 ASSERT_TRUE(ContainsSucceededPair(pairs));
michael@0 1377 }
michael@0 1378
michael@0 1379 TEST_F(IceConnectTest, TestPollCandPairsDuringConnect) {
michael@0 1380 AddStream("first", 1);
michael@0 1381 ASSERT_TRUE(Gather(true));
michael@0 1382
michael@0 1383 p1_->Connect(p2_, TRICKLE_NONE, false);
michael@0 1384 p2_->Connect(p1_, TRICKLE_NONE, false);
michael@0 1385
michael@0 1386 std::vector<NrIceCandidatePair> pairs1;
michael@0 1387 std::vector<NrIceCandidatePair> pairs2;
michael@0 1388
michael@0 1389 p1_->StartChecks();
michael@0 1390 p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
michael@0 1391 p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
michael@0 1392
michael@0 1393 p2_->StartChecks();
michael@0 1394 p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
michael@0 1395 p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
michael@0 1396
michael@0 1397 WaitForComplete();
michael@0 1398 p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
michael@0 1399 p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
michael@0 1400 ASSERT_TRUE(ContainsSucceededPair(pairs1));
michael@0 1401 ASSERT_TRUE(ContainsSucceededPair(pairs2));
michael@0 1402 }
michael@0 1403
michael@0 1404 TEST_F(IceConnectTest, TestRLogRingBuffer) {
michael@0 1405 RLogRingBuffer::CreateInstance();
michael@0 1406 AddStream("first", 1);
michael@0 1407 ASSERT_TRUE(Gather(true));
michael@0 1408
michael@0 1409 p1_->Connect(p2_, TRICKLE_NONE, false);
michael@0 1410 p2_->Connect(p1_, TRICKLE_NONE, false);
michael@0 1411
michael@0 1412 std::vector<NrIceCandidatePair> pairs1;
michael@0 1413 std::vector<NrIceCandidatePair> pairs2;
michael@0 1414
michael@0 1415 p1_->StartChecks();
michael@0 1416 p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
michael@0 1417 p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
michael@0 1418
michael@0 1419 p2_->StartChecks();
michael@0 1420 p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
michael@0 1421 p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
michael@0 1422
michael@0 1423 WaitForComplete();
michael@0 1424 p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
michael@0 1425 p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
michael@0 1426 ASSERT_TRUE(ContainsSucceededPair(pairs1));
michael@0 1427 ASSERT_TRUE(ContainsSucceededPair(pairs2));
michael@0 1428
michael@0 1429 for (auto p = pairs1.begin(); p != pairs1.end(); ++p) {
michael@0 1430 std::deque<std::string> logs;
michael@0 1431 std::string substring("CAND-PAIR(");
michael@0 1432 substring += p->codeword;
michael@0 1433 RLogRingBuffer::GetInstance()->Filter(substring, 0, &logs);
michael@0 1434 ASSERT_NE(0U, logs.size());
michael@0 1435 }
michael@0 1436
michael@0 1437 for (auto p = pairs2.begin(); p != pairs2.end(); ++p) {
michael@0 1438 std::deque<std::string> logs;
michael@0 1439 std::string substring("CAND-PAIR(");
michael@0 1440 substring += p->codeword;
michael@0 1441 RLogRingBuffer::GetInstance()->Filter(substring, 0, &logs);
michael@0 1442 ASSERT_NE(0U, logs.size());
michael@0 1443 }
michael@0 1444
michael@0 1445 RLogRingBuffer::DestroyInstance();
michael@0 1446 }
michael@0 1447
michael@0 1448 TEST_F(PrioritizerTest, TestPrioritizer) {
michael@0 1449 SetPriorizer(::mozilla::CreateInterfacePrioritizer());
michael@0 1450
michael@0 1451 AddInterface("0", NR_INTERFACE_TYPE_VPN, 100); // unknown vpn
michael@0 1452 AddInterface("1", NR_INTERFACE_TYPE_VPN | NR_INTERFACE_TYPE_WIRED, 100); // wired vpn
michael@0 1453 AddInterface("2", NR_INTERFACE_TYPE_VPN | NR_INTERFACE_TYPE_WIFI, 100); // wifi vpn
michael@0 1454 AddInterface("3", NR_INTERFACE_TYPE_VPN | NR_INTERFACE_TYPE_MOBILE, 100); // wifi vpn
michael@0 1455 AddInterface("4", NR_INTERFACE_TYPE_WIRED, 1000); // wired, high speed
michael@0 1456 AddInterface("5", NR_INTERFACE_TYPE_WIRED, 10); // wired, low speed
michael@0 1457 AddInterface("6", NR_INTERFACE_TYPE_WIFI, 10); // wifi, low speed
michael@0 1458 AddInterface("7", NR_INTERFACE_TYPE_WIFI, 1000); // wifi, high speed
michael@0 1459 AddInterface("8", NR_INTERFACE_TYPE_MOBILE, 10); // mobile, low speed
michael@0 1460 AddInterface("9", NR_INTERFACE_TYPE_MOBILE, 1000); // mobile, high speed
michael@0 1461 AddInterface("10", NR_INTERFACE_TYPE_UNKNOWN, 10); // unknown, low speed
michael@0 1462 AddInterface("11", NR_INTERFACE_TYPE_UNKNOWN, 1000); // unknown, high speed
michael@0 1463
michael@0 1464 // expected preference "4" > "5" > "1" > "7" > "6" > "2" > "9" > "8" > "3" > "11" > "10" > "0"
michael@0 1465
michael@0 1466 HasLowerPreference("0", "10");
michael@0 1467 HasLowerPreference("10", "11");
michael@0 1468 HasLowerPreference("11", "3");
michael@0 1469 HasLowerPreference("3", "8");
michael@0 1470 HasLowerPreference("8", "9");
michael@0 1471 HasLowerPreference("9", "2");
michael@0 1472 HasLowerPreference("2", "6");
michael@0 1473 HasLowerPreference("6", "7");
michael@0 1474 HasLowerPreference("7", "1");
michael@0 1475 HasLowerPreference("1", "5");
michael@0 1476 HasLowerPreference("5", "4");
michael@0 1477 }
michael@0 1478
michael@0 1479 TEST_F(PacketFilterTest, TestSendNonStunPacket) {
michael@0 1480 const unsigned char data[] = "12345abcde";
michael@0 1481 TestOutgoing(data, sizeof(data), 123, 45, false);
michael@0 1482 }
michael@0 1483
michael@0 1484 TEST_F(PacketFilterTest, TestRecvNonStunPacket) {
michael@0 1485 const unsigned char data[] = "12345abcde";
michael@0 1486 TestIncoming(data, sizeof(data), 123, 45, false);
michael@0 1487 }
michael@0 1488
michael@0 1489 TEST_F(PacketFilterTest, TestSendStunPacket) {
michael@0 1490 nr_stun_message *msg;
michael@0 1491 ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
michael@0 1492 msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
michael@0 1493 ASSERT_EQ(0, nr_stun_encode_message(msg));
michael@0 1494 TestOutgoing(msg->buffer, msg->length, 123, 45, true);
michael@0 1495 ASSERT_EQ(0, nr_stun_message_destroy(&msg));
michael@0 1496 }
michael@0 1497
michael@0 1498 TEST_F(PacketFilterTest, TestRecvStunPacketWithoutAPendingId) {
michael@0 1499 nr_stun_message *msg;
michael@0 1500 ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
michael@0 1501
michael@0 1502 msg->header.id.octet[0] = 1;
michael@0 1503 msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
michael@0 1504 ASSERT_EQ(0, nr_stun_encode_message(msg));
michael@0 1505 TestOutgoing(msg->buffer, msg->length, 123, 45, true);
michael@0 1506
michael@0 1507 msg->header.id.octet[0] = 0;
michael@0 1508 msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
michael@0 1509 ASSERT_EQ(0, nr_stun_encode_message(msg));
michael@0 1510 TestIncoming(msg->buffer, msg->length, 123, 45, true);
michael@0 1511
michael@0 1512 ASSERT_EQ(0, nr_stun_message_destroy(&msg));
michael@0 1513 }
michael@0 1514
michael@0 1515 TEST_F(PacketFilterTest, TestRecvStunPacketWithoutAPendingAddress) {
michael@0 1516 nr_stun_message *msg;
michael@0 1517 ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
michael@0 1518
michael@0 1519 msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
michael@0 1520 ASSERT_EQ(0, nr_stun_encode_message(msg));
michael@0 1521 TestOutgoing(msg->buffer, msg->length, 123, 45, true);
michael@0 1522
michael@0 1523 msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
michael@0 1524 ASSERT_EQ(0, nr_stun_encode_message(msg));
michael@0 1525 TestIncoming(msg->buffer, msg->length, 123, 46, false);
michael@0 1526 TestIncoming(msg->buffer, msg->length, 124, 45, false);
michael@0 1527
michael@0 1528 ASSERT_EQ(0, nr_stun_message_destroy(&msg));
michael@0 1529 }
michael@0 1530
michael@0 1531 TEST_F(PacketFilterTest, TestRecvStunPacketWithPendingIdAndAddress) {
michael@0 1532 nr_stun_message *msg;
michael@0 1533 ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
michael@0 1534
michael@0 1535 msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
michael@0 1536 ASSERT_EQ(0, nr_stun_encode_message(msg));
michael@0 1537 TestOutgoing(msg->buffer, msg->length, 123, 45, true);
michael@0 1538
michael@0 1539 msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
michael@0 1540 ASSERT_EQ(0, nr_stun_encode_message(msg));
michael@0 1541 TestIncoming(msg->buffer, msg->length, 123, 45, true);
michael@0 1542
michael@0 1543 // Test whitelist by filtering non-stun packets.
michael@0 1544 const unsigned char data[] = "12345abcde";
michael@0 1545
michael@0 1546 // 123:45 is white-listed.
michael@0 1547 TestOutgoing(data, sizeof(data), 123, 45, true);
michael@0 1548 TestIncoming(data, sizeof(data), 123, 45, true);
michael@0 1549
michael@0 1550 // Indications pass as well.
michael@0 1551 msg->header.type = NR_STUN_MSG_BINDING_INDICATION;
michael@0 1552 ASSERT_EQ(0, nr_stun_encode_message(msg));
michael@0 1553 TestOutgoing(msg->buffer, msg->length, 123, 45, true);
michael@0 1554 TestIncoming(msg->buffer, msg->length, 123, 45, true);
michael@0 1555
michael@0 1556 // Packets from and to other address are still disallowed.
michael@0 1557 TestOutgoing(data, sizeof(data), 123, 46, false);
michael@0 1558 TestIncoming(data, sizeof(data), 123, 46, false);
michael@0 1559 TestOutgoing(data, sizeof(data), 124, 45, false);
michael@0 1560 TestIncoming(data, sizeof(data), 124, 45, false);
michael@0 1561
michael@0 1562 ASSERT_EQ(0, nr_stun_message_destroy(&msg));
michael@0 1563 }
michael@0 1564
michael@0 1565 TEST_F(PacketFilterTest, TestSendNonRequestStunPacket) {
michael@0 1566 nr_stun_message *msg;
michael@0 1567 ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
michael@0 1568
michael@0 1569 msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
michael@0 1570 ASSERT_EQ(0, nr_stun_encode_message(msg));
michael@0 1571 TestOutgoing(msg->buffer, msg->length, 123, 45, false);
michael@0 1572
michael@0 1573 // Send a packet so we allow the incoming request.
michael@0 1574 msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
michael@0 1575 ASSERT_EQ(0, nr_stun_encode_message(msg));
michael@0 1576 TestOutgoing(msg->buffer, msg->length, 123, 45, true);
michael@0 1577
michael@0 1578 // This packet makes us able to send a response.
michael@0 1579 msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
michael@0 1580 ASSERT_EQ(0, nr_stun_encode_message(msg));
michael@0 1581 TestIncoming(msg->buffer, msg->length, 123, 45, true);
michael@0 1582
michael@0 1583 msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
michael@0 1584 ASSERT_EQ(0, nr_stun_encode_message(msg));
michael@0 1585 TestOutgoing(msg->buffer, msg->length, 123, 45, true);
michael@0 1586
michael@0 1587 ASSERT_EQ(0, nr_stun_message_destroy(&msg));
michael@0 1588 }
michael@0 1589
michael@0 1590 static std::string get_environment(const char *name) {
michael@0 1591 char *value = getenv(name);
michael@0 1592
michael@0 1593 if (!value)
michael@0 1594 return "";
michael@0 1595
michael@0 1596 return value;
michael@0 1597 }
michael@0 1598
michael@0 1599 int main(int argc, char **argv)
michael@0 1600 {
michael@0 1601 #ifdef LINUX
michael@0 1602 // This test can cause intermittent oranges on the builders on Linux
michael@0 1603 CHECK_ENVIRONMENT_FLAG("MOZ_WEBRTC_TESTS")
michael@0 1604 #endif
michael@0 1605
michael@0 1606 g_turn_server = get_environment("TURN_SERVER_ADDRESS");
michael@0 1607 g_turn_user = get_environment("TURN_SERVER_USER");
michael@0 1608 g_turn_password = get_environment("TURN_SERVER_PASSWORD");
michael@0 1609
michael@0 1610 if (g_turn_server.empty() ||
michael@0 1611 g_turn_user.empty(),
michael@0 1612 g_turn_password.empty()) {
michael@0 1613 printf(
michael@0 1614 "Set TURN_SERVER_ADDRESS, TURN_SERVER_USER, and TURN_SERVER_PASSWORD\n"
michael@0 1615 "environment variables to run this test\n");
michael@0 1616 g_turn_server="";
michael@0 1617 }
michael@0 1618
michael@0 1619 std::string tmp = get_environment("STUN_SERVER_ADDRESS");
michael@0 1620 if (tmp != "")
michael@0 1621 g_stun_server_address = tmp;
michael@0 1622
michael@0 1623
michael@0 1624 tmp = get_environment("STUN_SERVER_HOSTNAME");
michael@0 1625 if (tmp != "")
michael@0 1626 g_stun_server_hostname = tmp;
michael@0 1627
michael@0 1628 test_utils = new MtransportTestUtils();
michael@0 1629 NSS_NoDB_Init(nullptr);
michael@0 1630 NSS_SetDomesticPolicy();
michael@0 1631
michael@0 1632 // Start the tests
michael@0 1633 ::testing::InitGoogleTest(&argc, argv);
michael@0 1634
michael@0 1635 ::testing::TestEventListeners& listeners =
michael@0 1636 ::testing::UnitTest::GetInstance()->listeners();
michael@0 1637 // Adds a listener to the end. Google Test takes the ownership.
michael@0 1638
michael@0 1639 listeners.Append(new test::RingbufferDumper(test_utils));
michael@0 1640 test_utils->sts_target()->Dispatch(
michael@0 1641 WrapRunnableNM(&TestStunServer::GetInstance), NS_DISPATCH_SYNC);
michael@0 1642
michael@0 1643 int rv = RUN_ALL_TESTS();
michael@0 1644
michael@0 1645 test_utils->sts_target()->Dispatch(
michael@0 1646 WrapRunnableNM(&TestStunServer::ShutdownInstance), NS_DISPATCH_SYNC);
michael@0 1647
michael@0 1648 delete test_utils;
michael@0 1649 return rv;
michael@0 1650 }

mercurial