Bumping manifests a=b2g-bump
[gecko.git] / media / mtransport / test / ice_unittest.cpp
blob271784bc52806c7353b754866bf1ecf3edf06162
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/. */
7 // Original author: ekr@rtfm.com
9 #include <algorithm>
10 #include <deque>
11 #include <iostream>
12 #include <limits>
13 #include <map>
14 #include <string>
15 #include <vector>
17 #include "sigslot.h"
19 #include "logging.h"
20 #include "nspr.h"
21 #include "nss.h"
22 #include "ssl.h"
24 #include "mozilla/Scoped.h"
25 #include "nsThreadUtils.h"
26 #include "nsXPCOM.h"
28 #include "nricectx.h"
29 #include "nricemediastream.h"
30 #include "nriceresolverfake.h"
31 #include "nriceresolver.h"
32 #include "nrinterfaceprioritizer.h"
33 #include "mtransport_test_utils.h"
34 #include "gtest_ringbuffer_dumper.h"
35 #include "rlogringbuffer.h"
36 #include "runnable_utils.h"
37 #include "stunserver.h"
38 // TODO(bcampen@mozilla.com): Big fat hack since the build system doesn't give
39 // us a clean way to add object files to a single executable.
40 #include "stunserver.cpp"
41 #include "stun_udp_socket_filter.h"
42 #include "mozilla/net/DNS.h"
44 #include "ice_ctx.h"
45 #include "ice_peer_ctx.h"
46 #include "ice_media_stream.h"
48 #define GTEST_HAS_RTTI 0
49 #include "gtest/gtest.h"
50 #include "gtest_utils.h"
52 using namespace mozilla;
53 MtransportTestUtils *test_utils;
55 bool stream_added = false;
57 static unsigned int kDefaultTimeout = 7000;
59 const std::string kDefaultStunServerAddress((char *)"23.21.150.121");
60 const std::string kDefaultStunServerHostname(
61 (char *)"stun.services.mozilla.com");
62 const std::string kBogusStunServerHostname(
63 (char *)"stun-server-nonexistent.invalid");
64 const uint16_t kDefaultStunServerPort=3478;
65 const std::string kBogusIceCandidate(
66 (char *)"candidate:0 2 UDP 2113601790 192.168.178.20 50769 typ");
68 const std::string kUnreachableHostIceCandidate(
69 (char *)"candidate:0 1 UDP 2113601790 192.168.178.20 50769 typ host");
71 std::string g_stun_server_address(kDefaultStunServerAddress);
72 std::string g_stun_server_hostname(kDefaultStunServerHostname);
73 std::string g_turn_server;
74 std::string g_turn_user;
75 std::string g_turn_password;
77 namespace {
79 enum TrickleMode { TRICKLE_NONE, TRICKLE_SIMULATE, TRICKLE_REAL };
81 typedef std::string (*CandidateFilter)(const std::string& candidate);
83 static std::string IsRelayCandidate(const std::string& candidate) {
84 if (candidate.find("typ relay") != std::string::npos) {
85 return candidate;
87 return std::string();
90 static std::string IsLoopbackCandidate(const std::string& candidate) {
91 if (candidate.find("127.0.0.") != std::string::npos) {
92 return candidate;
94 return std::string();
97 static std::string SabotageHostCandidateAndDropReflexive(
98 const std::string& candidate) {
99 if (candidate.find("typ srflx") != std::string::npos) {
100 return std::string();
103 if (candidate.find("typ host") != std::string::npos) {
104 return kUnreachableHostIceCandidate;
107 return candidate;
110 bool ContainsSucceededPair(const std::vector<NrIceCandidatePair>& pairs) {
111 for (size_t i = 0; i < pairs.size(); ++i) {
112 if (pairs[i].state == NrIceCandidatePair::STATE_SUCCEEDED) {
113 return true;
116 return false;
119 // Note: Does not correspond to any notion of prioritization; this is just
120 // so we can use stl containers/algorithms that need a comparator
121 bool operator<(const NrIceCandidate& lhs,
122 const NrIceCandidate& rhs) {
123 if (lhs.cand_addr.host == rhs.cand_addr.host) {
124 if (lhs.cand_addr.port == rhs.cand_addr.port) {
125 if (lhs.cand_addr.transport == rhs.cand_addr.transport) {
126 return lhs.type < rhs.type;
128 return lhs.cand_addr.transport < rhs.cand_addr.transport;
130 return lhs.cand_addr.port < rhs.cand_addr.port;
132 return lhs.cand_addr.host < rhs.cand_addr.host;
135 bool operator==(const NrIceCandidate& lhs,
136 const NrIceCandidate& rhs) {
137 return !((lhs < rhs) || (rhs < lhs));
140 class IceCandidatePairCompare {
141 public:
142 bool operator()(const NrIceCandidatePair& lhs,
143 const NrIceCandidatePair& rhs) const {
144 if (lhs.priority == rhs.priority) {
145 if (lhs.local == rhs.local) {
146 if (lhs.remote == rhs.remote) {
147 return lhs.codeword < rhs.codeword;
149 return lhs.remote < rhs.remote;
151 return lhs.local < rhs.local;
153 return lhs.priority < rhs.priority;
157 class IceTestPeer;
159 class SchedulableTrickleCandidate {
160 public:
161 SchedulableTrickleCandidate(IceTestPeer *peer,
162 size_t stream,
163 const std::string &candidate) :
164 peer_(peer),
165 stream_(stream),
166 candidate_(candidate),
167 timer_handle_(nullptr) {
170 ~SchedulableTrickleCandidate() {
171 if (timer_handle_)
172 NR_async_timer_cancel(timer_handle_);
175 void Schedule(unsigned int ms) {
176 test_utils->sts_target()->Dispatch(
177 WrapRunnable(this, &SchedulableTrickleCandidate::Schedule_s, ms),
178 NS_DISPATCH_SYNC);
181 void Schedule_s(unsigned int ms) {
182 MOZ_ASSERT(!timer_handle_);
183 NR_ASYNC_TIMER_SET(ms, Trickle_cb, this, &timer_handle_);
186 static void Trickle_cb(NR_SOCKET s, int how, void *cb_arg) {
187 static_cast<SchedulableTrickleCandidate*>(cb_arg)->Trickle();
190 void Trickle();
192 std::string& Candidate() {
193 return candidate_;
196 const std::string& Candidate() const {
197 return candidate_;
200 size_t Stream() const {
201 return stream_;
204 bool IsHost() const {
205 return candidate_.find("typ host") != std::string::npos;
208 bool IsReflexive() const {
209 return candidate_.find("typ srflx") != std::string::npos;
212 bool IsRelay() const {
213 return candidate_.find("typ relay") != std::string::npos;
216 private:
217 IceTestPeer *peer_;
218 size_t stream_;
219 std::string candidate_;
220 void *timer_handle_;
222 DISALLOW_COPY_ASSIGN(SchedulableTrickleCandidate);
225 class IceTestPeer : public sigslot::has_slots<> {
226 public:
228 IceTestPeer(const std::string& name, bool offerer, bool set_priorities,
229 bool allow_loopback = false) :
230 name_(name),
231 ice_ctx_(NrIceCtx::Create(name, offerer, set_priorities, allow_loopback)),
232 streams_(),
233 candidates_(),
234 gathering_complete_(false),
235 ready_ct_(0),
236 ice_complete_(false),
237 ice_reached_checking_(false),
238 received_(0),
239 sent_(0),
240 fake_resolver_(),
241 dns_resolver_(new NrIceResolver()),
242 remote_(nullptr),
243 candidate_filter_(nullptr),
244 expected_local_type_(NrIceCandidate::ICE_HOST),
245 expected_local_transport_(kNrIceTransportUdp),
246 expected_remote_type_(NrIceCandidate::ICE_HOST),
247 trickle_mode_(TRICKLE_NONE),
248 trickled_(0),
249 simulate_ice_lite_(false) {
250 ice_ctx_->SignalGatheringStateChange.connect(
251 this,
252 &IceTestPeer::GatheringStateChange);
253 ice_ctx_->SignalConnectionStateChange.connect(
254 this,
255 &IceTestPeer::ConnectionStateChange);
258 ~IceTestPeer() {
259 test_utils->sts_target()->Dispatch(WrapRunnable(this,
260 &IceTestPeer::Shutdown),
261 NS_DISPATCH_SYNC);
263 // Give the ICE destruction callback time to fire before
264 // we destroy the resolver.
265 PR_Sleep(1000);
268 void AddStream(int components) {
269 char name[100];
270 snprintf(name, sizeof(name), "%s:stream%d", name_.c_str(),
271 (int)streams_.size());
273 mozilla::RefPtr<NrIceMediaStream> stream =
274 ice_ctx_->CreateStream(static_cast<char *>(name), components);
276 ASSERT_TRUE(stream);
277 streams_.push_back(stream);
278 stream->SignalCandidate.connect(this, &IceTestPeer::CandidateInitialized);
279 stream->SignalReady.connect(this, &IceTestPeer::StreamReady);
280 stream->SignalFailed.connect(this, &IceTestPeer::StreamFailed);
281 stream->SignalPacketReceived.connect(this, &IceTestPeer::PacketReceived);
284 void SetStunServer(const std::string addr, uint16_t port) {
285 if (addr.empty()) {
286 // Happens when MOZ_DISABLE_NONLOCAL_CONNECTIONS is set
287 return;
290 std::vector<NrIceStunServer> stun_servers;
291 ScopedDeletePtr<NrIceStunServer> server(NrIceStunServer::Create(addr,
292 port));
293 stun_servers.push_back(*server);
294 ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetStunServers(stun_servers)));
297 void SetTurnServer(const std::string addr, uint16_t port,
298 const std::string username,
299 const std::string password,
300 const char* transport) {
301 std::vector<unsigned char> password_vec(password.begin(), password.end());
302 SetTurnServer(addr, port, username, password_vec, transport);
306 void SetTurnServer(const std::string addr, uint16_t port,
307 const std::string username,
308 const std::vector<unsigned char> password,
309 const char* transport) {
310 std::vector<NrIceTurnServer> turn_servers;
311 ScopedDeletePtr<NrIceTurnServer> server(NrIceTurnServer::Create(
312 addr, port, username, password, transport));
313 turn_servers.push_back(*server);
314 ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetTurnServers(turn_servers)));
317 void SetTurnServers(const std::vector<NrIceTurnServer> servers) {
318 ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetTurnServers(servers)));
321 void SetFakeResolver() {
322 ASSERT_TRUE(NS_SUCCEEDED(dns_resolver_->Init()));
323 if (!g_stun_server_address.empty() && !g_stun_server_hostname.empty()) {
324 PRNetAddr addr;
325 PRStatus status = PR_StringToNetAddr(g_stun_server_address.c_str(),
326 &addr);
327 addr.inet.port = kDefaultStunServerPort;
328 ASSERT_EQ(PR_SUCCESS, status);
329 fake_resolver_.SetAddr(g_stun_server_hostname, addr);
331 ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetResolver(
332 fake_resolver_.AllocateResolver())));
335 void SetDNSResolver() {
336 ASSERT_TRUE(NS_SUCCEEDED(dns_resolver_->Init()));
337 ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetResolver(
338 dns_resolver_->AllocateResolver())));
341 void Gather() {
342 nsresult res;
344 test_utils->sts_target()->Dispatch(
345 WrapRunnableRet(ice_ctx_, &NrIceCtx::StartGathering, &res),
346 NS_DISPATCH_SYNC);
348 ASSERT_TRUE(NS_SUCCEEDED(res));
351 // Get various pieces of state
352 std::vector<std::string> GetGlobalAttributes() {
353 std::vector<std::string> attrs(ice_ctx_->GetGlobalAttributes());
354 if (simulate_ice_lite_) {
355 attrs.push_back("ice-lite");
357 return attrs;
360 std::vector<std::string> GetCandidates(size_t stream) {
361 std::vector<std::string> v;
363 RUN_ON_THREAD(
364 test_utils->sts_target(),
365 WrapRunnableRet(this, &IceTestPeer::GetCandidates_s, stream, &v));
367 return v;
370 std::string FilterCandidate(const std::string& candidate) {
371 if (candidate_filter_) {
372 return candidate_filter_(candidate);
374 return candidate;
377 std::vector<std::string> GetCandidates_s(size_t stream) {
378 std::vector<std::string> candidates;
380 if (stream >= streams_.size())
381 return candidates;
383 std::vector<std::string> candidates_in =
384 streams_[stream]->GetCandidates();
387 for (size_t i=0; i < candidates_in.size(); i++) {
388 std::string candidate(FilterCandidate(candidates_in[i]));
389 if (!candidate.empty()) {
390 std::cerr << "Returning candidate: " << candidate << std::endl;
391 candidates.push_back(candidate);
395 return candidates;
398 void SetExpectedTypes(NrIceCandidate::Type local,
399 NrIceCandidate::Type remote,
400 std::string local_transport = kNrIceTransportUdp) {
401 expected_local_type_ = local;
402 expected_local_transport_ = local_transport;
403 expected_remote_type_ = remote;
406 void SetExpectedCandidateAddr(const std::string& addr) {
407 expected_local_addr_ = addr;
408 expected_remote_addr_ = addr;
411 bool gathering_complete() { return gathering_complete_; }
412 int ready_ct() { return ready_ct_; }
413 bool is_ready(size_t stream) {
414 return streams_[stream]->state() == NrIceMediaStream::ICE_OPEN;
416 bool ice_complete() { return ice_complete_; }
417 bool ice_reached_checking() { return ice_reached_checking_; }
418 size_t received() { return received_; }
419 size_t sent() { return sent_; }
421 // Start connecting to another peer
422 void Connect_s(IceTestPeer *remote, TrickleMode trickle_mode,
423 bool start = true) {
424 nsresult res;
426 remote_ = remote;
428 trickle_mode_ = trickle_mode;
429 res = ice_ctx_->ParseGlobalAttributes(remote->GetGlobalAttributes());
430 ASSERT_TRUE(NS_SUCCEEDED(res));
432 if (trickle_mode == TRICKLE_NONE ||
433 trickle_mode == TRICKLE_REAL) {
434 for (size_t i=0; i<streams_.size(); ++i) {
435 std::vector<std::string> candidates =
436 remote->GetCandidates(i);
438 for (size_t j=0; j<candidates.size(); ++j) {
439 std::cerr << "Candidate: " + candidates[j] << std::endl;
441 res = streams_[i]->ParseAttributes(candidates);
442 ASSERT_TRUE(NS_SUCCEEDED(res));
444 } else {
445 // Parse empty attributes and then trickle them out later
446 for (size_t i=0; i<streams_.size(); ++i) {
447 std::vector<std::string> empty_attrs;
448 res = streams_[i]->ParseAttributes(empty_attrs);
449 ASSERT_TRUE(NS_SUCCEEDED(res));
453 if (start) {
454 // Now start checks
455 res = ice_ctx_->StartChecks();
456 ASSERT_TRUE(NS_SUCCEEDED(res));
460 void Connect(IceTestPeer *remote, TrickleMode trickle_mode,
461 bool start = true) {
462 test_utils->sts_target()->Dispatch(
463 WrapRunnable(
464 this, &IceTestPeer::Connect_s, remote, trickle_mode, start),
465 NS_DISPATCH_SYNC);
468 void SimulateTrickle(size_t stream) {
469 std::cerr << "Doing trickle for stream " << stream << std::endl;
470 // If we are in trickle deferred mode, now trickle in the candidates
471 // for |stream|
473 ASSERT_GT(remote_->streams_.size(), stream);
475 std::vector<SchedulableTrickleCandidate*>& candidates =
476 ControlTrickle(stream);
478 for (auto i = candidates.begin(); i != candidates.end(); ++i) {
479 (*i)->Schedule(0);
483 // Allows test case to completely control when/if candidates are trickled
484 // (test could also do things like insert extra trickle candidates, or
485 // change existing ones, or insert duplicates, really anything is fair game)
486 std::vector<SchedulableTrickleCandidate*>& ControlTrickle(size_t stream) {
487 std::cerr << "Doing controlled trickle for stream " << stream << std::endl;
489 std::vector<std::string> candidates =
490 remote_->GetCandidates(stream);
492 for (size_t j=0; j<candidates.size(); j++) {
493 controlled_trickle_candidates_[stream].push_back(
494 new SchedulableTrickleCandidate(this, stream, candidates[j]));
497 return controlled_trickle_candidates_[stream];
500 nsresult TrickleCandidate_s(const std::string &candidate, size_t stream) {
501 return streams_[stream]->ParseTrickleCandidate(candidate);
504 void DumpCandidate(std::string which, const NrIceCandidate& cand) {
505 std::string type;
507 std::string addr;
508 int port;
510 if (which.find("Remote") != std::string::npos) {
511 addr = cand.cand_addr.host;
512 port = cand.cand_addr.port;
514 else {
515 addr = cand.local_addr.host;
516 port = cand.local_addr.port;
518 switch(cand.type) {
519 case NrIceCandidate::ICE_HOST:
520 type = "host";
521 break;
522 case NrIceCandidate::ICE_SERVER_REFLEXIVE:
523 type = "srflx";
524 break;
525 case NrIceCandidate::ICE_PEER_REFLEXIVE:
526 type = "prflx";
527 break;
528 case NrIceCandidate::ICE_RELAYED:
529 type = "relay";
530 if (which.find("Local") != std::string::npos) {
531 type += "(" + cand.local_addr.transport + ")";
533 break;
534 default:
535 FAIL();
539 std::cerr << which
540 << " --> "
541 << type
542 << " "
543 << addr
544 << ":"
545 << port
546 << " codeword="
547 << cand.codeword
548 << std::endl;
551 void DumpAndCheckActiveCandidates_s() {
552 std::cerr << "Active candidates:" << std::endl;
553 for (size_t i=0; i < streams_.size(); ++i) {
554 for (size_t j=0; j < streams_[i]->components(); ++j) {
555 std::cerr << "Stream " << i << " component " << j+1 << std::endl;
557 NrIceCandidate *local;
558 NrIceCandidate *remote;
560 nsresult res = streams_[i]->GetActivePair(j+1, &local, &remote);
561 if (res == NS_ERROR_NOT_AVAILABLE) {
562 std::cerr << "Component unpaired or disabled." << std::endl;
563 } else {
564 ASSERT_TRUE(NS_SUCCEEDED(res));
565 DumpCandidate("Local ", *local);
566 ASSERT_EQ(expected_local_type_, local->type);
567 ASSERT_EQ(expected_local_transport_, local->local_addr.transport);
568 DumpCandidate("Remote ", *remote);
569 ASSERT_EQ(expected_remote_type_, remote->type);
570 if (!expected_local_addr_.empty()) {
571 ASSERT_EQ(expected_local_addr_, local->cand_addr.host);
573 if (!expected_remote_addr_.empty()) {
574 ASSERT_EQ(expected_remote_addr_, remote->cand_addr.host);
576 delete local;
577 delete remote;
583 void DumpAndCheckActiveCandidates() {
584 test_utils->sts_target()->Dispatch(
585 WrapRunnable(this, &IceTestPeer::DumpAndCheckActiveCandidates_s),
586 NS_DISPATCH_SYNC);
589 void Close() {
590 test_utils->sts_target()->Dispatch(
591 WrapRunnable(ice_ctx_, &NrIceCtx::destroy_peer_ctx),
592 NS_DISPATCH_SYNC);
595 void Shutdown() {
596 for (auto s = controlled_trickle_candidates_.begin();
597 s != controlled_trickle_candidates_.end();
598 ++s) {
599 for (auto cand = s->second.begin(); cand != s->second.end(); ++cand) {
600 delete *cand;
604 ice_ctx_ = nullptr;
607 void StartChecks() {
608 nsresult res;
610 // Now start checks
611 test_utils->sts_target()->Dispatch(
612 WrapRunnableRet(ice_ctx_, &NrIceCtx::StartChecks, &res),
613 NS_DISPATCH_SYNC);
614 ASSERT_TRUE(NS_SUCCEEDED(res));
617 // Handle events
618 void GatheringStateChange(NrIceCtx* ctx,
619 NrIceCtx::GatheringState state) {
620 (void)ctx;
621 if (state != NrIceCtx::ICE_CTX_GATHER_COMPLETE) {
622 return;
625 std::cerr << "Gathering complete for " << name_ << std::endl;
626 gathering_complete_ = true;
628 std::cerr << "CANDIDATES:" << std::endl;
629 for (size_t i=0; i<streams_.size(); ++i) {
630 std::cerr << "Stream " << name_ << std::endl;
631 std::vector<std::string> candidates =
632 streams_[i]->GetCandidates();
634 for(size_t j=0; j<candidates.size(); ++j) {
635 std::cerr << candidates[j] << std::endl;
638 std::cerr << std::endl;
642 void CandidateInitialized(NrIceMediaStream *stream, const std::string &raw_candidate) {
643 std::string candidate(FilterCandidate(raw_candidate));
644 if (candidate.empty()) {
645 return;
647 std::cerr << "Candidate initialized: " << candidate << std::endl;
648 candidates_[stream->name()].push_back(candidate);
650 // If we are connected, then try to trickle to the
651 // other side.
652 if (remote_ && remote_->remote_) {
653 std::vector<mozilla::RefPtr<NrIceMediaStream> >::iterator it =
654 std::find(streams_.begin(), streams_.end(), stream);
655 ASSERT_NE(streams_.end(), it);
656 size_t index = it - streams_.begin();
658 ASSERT_GT(remote_->streams_.size(), index);
659 nsresult res = remote_->streams_[index]->ParseTrickleCandidate(
660 candidate);
661 ASSERT_TRUE(NS_SUCCEEDED(res));
662 ++trickled_;
666 nsresult GetCandidatePairs(size_t stream_index,
667 std::vector<NrIceCandidatePair>* pairs) {
668 MOZ_ASSERT(pairs);
669 if (stream_index >= streams_.size()) {
670 // Is there a better error for "no such index"?
671 ADD_FAILURE() << "No such media stream index: " << stream_index;
672 return NS_ERROR_INVALID_ARG;
675 nsresult res;
676 test_utils->sts_target()->Dispatch(
677 WrapRunnableRet(streams_[stream_index],
678 &NrIceMediaStream::GetCandidatePairs,
679 pairs,
680 &res),
681 NS_DISPATCH_SYNC);
682 return res;
685 void DumpCandidatePair(const NrIceCandidatePair& pair) {
686 std::cerr << std::endl;
687 DumpCandidate("Local", pair.local);
688 DumpCandidate("Remote", pair.remote);
689 std::cerr << "state = " << pair.state
690 << " priority = " << pair.priority
691 << " nominated = " << pair.nominated
692 << " selected = " << pair.selected
693 << " codeword = " << pair.codeword << std::endl;
696 void DumpCandidatePairs(NrIceMediaStream *stream) {
697 std::vector<NrIceCandidatePair> pairs;
698 nsresult res = stream->GetCandidatePairs(&pairs);
699 ASSERT_TRUE(NS_SUCCEEDED(res));
701 std::cerr << "Begin list of candidate pairs [" << std::endl;
703 for (std::vector<NrIceCandidatePair>::iterator p = pairs.begin();
704 p != pairs.end(); ++p) {
705 DumpCandidatePair(*p);
707 std::cerr << "]" << std::endl;
710 void DumpCandidatePairs() {
711 std::cerr << "Dumping candidate pairs for all streams [" << std::endl;
712 for (size_t s = 0; s < streams_.size(); ++s) {
713 DumpCandidatePairs(streams_[s]);
715 std::cerr << "]" << std::endl;
718 bool CandidatePairsPriorityDescending(const std::vector<NrIceCandidatePair>&
719 pairs) {
720 // Verify that priority is descending
721 uint64_t priority = std::numeric_limits<uint64_t>::max();
723 for (size_t p = 0; p < pairs.size(); ++p) {
724 if (priority < pairs[p].priority) {
725 std::cerr << "Priority increased in subsequent pairs:" << std::endl;
726 DumpCandidatePair(pairs[p-1]);
727 DumpCandidatePair(pairs[p]);
728 return false;
729 } else if (priority == pairs[p].priority) {
730 std::cerr << "Duplicate priority in subseqent pairs:" << std::endl;
731 DumpCandidatePair(pairs[p-1]);
732 DumpCandidatePair(pairs[p]);
733 return false;
735 priority = pairs[p].priority;
737 return true;
740 void UpdateAndValidateCandidatePairs(size_t stream_index,
741 std::vector<NrIceCandidatePair>*
742 new_pairs) {
743 std::vector<NrIceCandidatePair> old_pairs = *new_pairs;
744 GetCandidatePairs(stream_index, new_pairs);
745 ASSERT_TRUE(CandidatePairsPriorityDescending(*new_pairs)) << "New list of "
746 "candidate pairs is either not sorted in priority order, or has "
747 "duplicate priorities.";
748 ASSERT_TRUE(CandidatePairsPriorityDescending(old_pairs)) << "Old list of "
749 "candidate pairs is either not sorted in priority order, or has "
750 "duplicate priorities. This indicates some bug in the test case.";
751 std::vector<NrIceCandidatePair> added_pairs;
752 std::vector<NrIceCandidatePair> removed_pairs;
754 // set_difference computes the set of elements that are present in the
755 // first set, but not the second
756 // NrIceCandidatePair::operator< compares based on the priority, local
757 // candidate, and remote candidate in that order. This means this will
758 // catch cases where the priority has remained the same, but one of the
759 // candidates has changed.
760 std::set_difference((*new_pairs).begin(),
761 (*new_pairs).end(),
762 old_pairs.begin(),
763 old_pairs.end(),
764 std::inserter(added_pairs, added_pairs.begin()),
765 IceCandidatePairCompare());
767 std::set_difference(old_pairs.begin(),
768 old_pairs.end(),
769 (*new_pairs).begin(),
770 (*new_pairs).end(),
771 std::inserter(removed_pairs, removed_pairs.begin()),
772 IceCandidatePairCompare());
774 for (std::vector<NrIceCandidatePair>::iterator a = added_pairs.begin();
775 a != added_pairs.end(); ++a) {
776 std::cerr << "Found new candidate pair." << std::endl;
777 DumpCandidatePair(*a);
780 for (std::vector<NrIceCandidatePair>::iterator r = removed_pairs.begin();
781 r != removed_pairs.end(); ++r) {
782 std::cerr << "Pre-existing candidate pair is now missing:" << std::endl;
783 DumpCandidatePair(*r);
786 ASSERT_TRUE(removed_pairs.empty()) << "At least one candidate pair has "
787 "gone missing.";
790 void StreamReady(NrIceMediaStream *stream) {
791 ++ready_ct_;
792 std::cerr << "Stream ready " << stream->name() << " ct=" << ready_ct_ << std::endl;
793 DumpCandidatePairs(stream);
795 void StreamFailed(NrIceMediaStream *stream) {
796 std::cerr << "Stream failed " << stream->name() << " ct=" << ready_ct_ << std::endl;
797 DumpCandidatePairs(stream);
800 void ConnectionStateChange(NrIceCtx* ctx,
801 NrIceCtx::ConnectionState state) {
802 (void)ctx;
803 switch (state) {
804 case NrIceCtx::ICE_CTX_INIT:
805 break;
806 case NrIceCtx::ICE_CTX_CHECKING:
807 std::cerr << "ICE checking " << name_ << std::endl;
808 ice_reached_checking_ = true;
809 break;
810 case NrIceCtx::ICE_CTX_OPEN:
811 std::cerr << "ICE completed " << name_ << std::endl;
812 ice_complete_ = true;
813 break;
814 case NrIceCtx::ICE_CTX_FAILED:
815 break;
819 void PacketReceived(NrIceMediaStream *stream, int component, const unsigned char *data,
820 int len) {
821 std::cerr << "Received " << len << " bytes" << std::endl;
822 ++received_;
825 void SendPacket(int stream, int component, const unsigned char *data,
826 int len) {
827 ASSERT_TRUE(NS_SUCCEEDED(streams_[stream]->SendPacket(component, data, len)));
829 ++sent_;
830 std::cerr << "Sent " << len << " bytes" << std::endl;
833 void SetCandidateFilter(CandidateFilter filter) {
834 candidate_filter_ = filter;
837 // Allow us to parse candidates directly on the current thread.
838 void ParseCandidate(size_t i, const std::string& candidate) {
839 std::vector<std::string> attributes;
841 attributes.push_back(candidate);
842 streams_[i]->ParseAttributes(attributes);
845 void DisableComponent(size_t stream, int component_id) {
846 ASSERT_LT(stream, streams_.size());
847 nsresult res = streams_[stream]->DisableComponent(component_id);
848 ASSERT_TRUE(NS_SUCCEEDED(res));
851 int trickled() { return trickled_; }
853 void SetControlling(NrIceCtx::Controlling controlling) {
854 nsresult res;
855 test_utils->sts_target()->Dispatch(
856 WrapRunnableRet(ice_ctx_,
857 &NrIceCtx::SetControlling,
858 controlling,
859 &res),
860 NS_DISPATCH_SYNC);
861 ASSERT_TRUE(NS_SUCCEEDED(res));
864 void SetTiebreaker(uint64_t tiebreaker) {
865 test_utils->sts_target()->Dispatch(
866 WrapRunnable(this,
867 &IceTestPeer::SetTiebreaker_s,
868 tiebreaker),
869 NS_DISPATCH_SYNC);
872 void SetTiebreaker_s(uint64_t tiebreaker) {
873 ice_ctx_->peer()->tiebreaker = tiebreaker;
876 void SimulateIceLite() {
877 simulate_ice_lite_ = true;
878 SetControlling(NrIceCtx::ICE_CONTROLLED);
881 private:
882 std::string name_;
883 nsRefPtr<NrIceCtx> ice_ctx_;
884 std::vector<mozilla::RefPtr<NrIceMediaStream> > streams_;
885 std::map<std::string, std::vector<std::string> > candidates_;
886 // Maps from stream id to list of remote trickle candidates
887 std::map<size_t, std::vector<SchedulableTrickleCandidate*> >
888 controlled_trickle_candidates_;
889 bool gathering_complete_;
890 int ready_ct_;
891 bool ice_complete_;
892 bool ice_reached_checking_;
893 size_t received_;
894 size_t sent_;
895 NrIceResolverFake fake_resolver_;
896 nsRefPtr<NrIceResolver> dns_resolver_;
897 IceTestPeer *remote_;
898 CandidateFilter candidate_filter_;
899 NrIceCandidate::Type expected_local_type_;
900 std::string expected_local_transport_;
901 NrIceCandidate::Type expected_remote_type_;
902 std::string expected_local_addr_;
903 std::string expected_remote_addr_;
904 TrickleMode trickle_mode_;
905 int trickled_;
906 bool simulate_ice_lite_;
909 void SchedulableTrickleCandidate::Trickle() {
910 timer_handle_ = nullptr;
911 nsresult res = peer_->TrickleCandidate_s(candidate_, stream_);
912 ASSERT_TRUE(NS_SUCCEEDED(res));
915 class IceGatherTest : public ::testing::Test {
916 public:
917 void SetUp() {
918 test_utils->sts_target()->Dispatch(WrapRunnable(TestStunServer::GetInstance(),
919 &TestStunServer::Reset),
920 NS_DISPATCH_SYNC);
923 void TearDown() {
924 peer_ = nullptr;
926 test_utils->sts_target()->Dispatch(WrapRunnable(this,
927 &IceGatherTest::TearDown_s),
928 NS_DISPATCH_SYNC);
931 void TearDown_s() {
932 NrIceCtx::internal_DeinitializeGlobal();
935 void EnsurePeer() {
936 if (!peer_) {
937 peer_ = new IceTestPeer("P1", true, false);
938 peer_->AddStream(1);
942 void Gather(unsigned int waitTime = kDefaultTimeout) {
943 EnsurePeer();
944 peer_->Gather();
946 if (waitTime) {
947 WaitForGather(waitTime);
951 void WaitForGather(unsigned int waitTime = kDefaultTimeout) {
952 ASSERT_TRUE_WAIT(peer_->gathering_complete(), waitTime);
955 void UseFakeStunServerWithResponse(const std::string& fake_addr,
956 uint16_t fake_port) {
957 EnsurePeer();
958 TestStunServer::GetInstance()->SetResponseAddr(fake_addr, fake_port);
959 // Sets an additional stun server
960 peer_->SetStunServer(TestStunServer::GetInstance()->addr(),
961 TestStunServer::GetInstance()->port());
964 // NB: Only does substring matching, watch out for stuff like "1.2.3.4"
965 // matching "21.2.3.47". " 1.2.3.4 " should not have false positives.
966 bool StreamHasMatchingCandidate(unsigned int stream,
967 const std::string& match) {
968 std::vector<std::string> candidates = peer_->GetCandidates(stream);
969 for (size_t c = 0; c < candidates.size(); ++c) {
970 if (std::string::npos != candidates[c].find(match)) {
971 return true;
974 return false;
977 protected:
978 mozilla::ScopedDeletePtr<IceTestPeer> peer_;
981 class IceConnectTest : public ::testing::Test {
982 public:
983 IceConnectTest() : initted_(false) {}
985 void SetUp() {
986 nsresult rv;
987 target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
988 ASSERT_TRUE(NS_SUCCEEDED(rv));
991 void TearDown() {
992 p1_ = nullptr;
993 p2_ = nullptr;
995 test_utils->sts_target()->Dispatch(WrapRunnable(this,
996 &IceConnectTest::TearDown_s),
997 NS_DISPATCH_SYNC);
1000 void TearDown_s() {
1001 NrIceCtx::internal_DeinitializeGlobal();
1004 void AddStream(const std::string& name, int components) {
1005 Init(false, false);
1006 p1_->AddStream(components);
1007 p2_->AddStream(components);
1010 void Init(bool set_priorities, bool allow_loopback) {
1011 if (!initted_) {
1012 p1_ = new IceTestPeer("P1", true, set_priorities, allow_loopback);
1013 p2_ = new IceTestPeer("P2", false, set_priorities, allow_loopback);
1015 initted_ = true;
1018 bool Gather(unsigned int waitTime = kDefaultTimeout) {
1019 Init(false, false);
1020 p1_->SetStunServer(g_stun_server_address, kDefaultStunServerPort);
1021 p2_->SetStunServer(g_stun_server_address, kDefaultStunServerPort);
1022 p1_->Gather();
1023 p2_->Gather();
1025 if (waitTime) {
1026 EXPECT_TRUE_WAIT(p1_->gathering_complete(), waitTime);
1027 if (!p1_->gathering_complete())
1028 return false;
1029 EXPECT_TRUE_WAIT(p2_->gathering_complete(), waitTime);
1030 if (!p2_->gathering_complete())
1031 return false;
1033 return true;
1036 void SetTurnServer(const std::string addr, uint16_t port,
1037 const std::string username,
1038 const std::string password,
1039 const char* transport = kNrIceTransportUdp) {
1040 p1_->SetTurnServer(addr, port, username, password, transport);
1041 p2_->SetTurnServer(addr, port, username, password, transport);
1044 void SetTurnServers(const std::vector<NrIceTurnServer>& servers) {
1045 p1_->SetTurnServers(servers);
1046 p2_->SetTurnServers(servers);
1049 void SetCandidateFilter(CandidateFilter filter, bool both=true) {
1050 p1_->SetCandidateFilter(filter);
1051 if (both) {
1052 p2_->SetCandidateFilter(filter);
1056 void Connect() {
1057 // IceTestPeer::Connect grabs attributes from the first arg, and gives them
1058 // to |this|, meaning that p2_->Connect(p1_, ...) simulates p1 sending an
1059 // offer to p2. Order matters here because it determines which peer is
1060 // controlling.
1061 p2_->Connect(p1_, TRICKLE_NONE);
1062 p1_->Connect(p2_, TRICKLE_NONE);
1064 ASSERT_TRUE_WAIT(p1_->ready_ct() == 1 && p2_->ready_ct() == 1,
1065 kDefaultTimeout);
1066 ASSERT_TRUE_WAIT(p1_->ice_complete() && p2_->ice_complete(),
1067 kDefaultTimeout);
1068 AssertCheckingReached();
1070 p1_->DumpAndCheckActiveCandidates();
1071 p2_->DumpAndCheckActiveCandidates();
1074 void SetExpectedTypes(NrIceCandidate::Type local, NrIceCandidate::Type remote,
1075 std::string transport = kNrIceTransportUdp) {
1076 p1_->SetExpectedTypes(local, remote, transport);
1077 p2_->SetExpectedTypes(local, remote, transport);
1080 void SetExpectedTypes(NrIceCandidate::Type local1, NrIceCandidate::Type remote1,
1081 NrIceCandidate::Type local2, NrIceCandidate::Type remote2) {
1082 p1_->SetExpectedTypes(local1, remote1);
1083 p2_->SetExpectedTypes(local2, remote2);
1086 void SetExpectedCandidateAddr(const std::string& addr) {
1087 p1_->SetExpectedCandidateAddr(addr);
1088 p2_->SetExpectedCandidateAddr(addr);
1091 void ConnectP1(TrickleMode mode = TRICKLE_NONE) {
1092 p1_->Connect(p2_, mode);
1095 void ConnectP2(TrickleMode mode = TRICKLE_NONE) {
1096 p2_->Connect(p1_, mode);
1099 void WaitForComplete(int expected_streams = 1) {
1100 ASSERT_TRUE_WAIT(p1_->ready_ct() == expected_streams &&
1101 p2_->ready_ct() == expected_streams, kDefaultTimeout);
1102 ASSERT_TRUE_WAIT(p1_->ice_complete() && p2_->ice_complete(),
1103 kDefaultTimeout);
1106 void AssertCheckingReached() {
1107 ASSERT_TRUE(p1_->ice_reached_checking());
1108 ASSERT_TRUE(p2_->ice_reached_checking());
1111 void WaitForGather() {
1112 ASSERT_TRUE_WAIT(p1_->gathering_complete(), kDefaultTimeout);
1113 ASSERT_TRUE_WAIT(p2_->gathering_complete(), kDefaultTimeout);
1116 void ConnectTrickle(TrickleMode trickle = TRICKLE_SIMULATE) {
1117 p2_->Connect(p1_, trickle);
1118 p1_->Connect(p2_, trickle);
1121 void SimulateTrickle(size_t stream) {
1122 p1_->SimulateTrickle(stream);
1123 p2_->SimulateTrickle(stream);
1124 ASSERT_TRUE_WAIT(p1_->is_ready(stream), kDefaultTimeout);
1125 ASSERT_TRUE_WAIT(p2_->is_ready(stream), kDefaultTimeout);
1128 void SimulateTrickleP1(size_t stream) {
1129 p1_->SimulateTrickle(stream);
1132 void SimulateTrickleP2(size_t stream) {
1133 p2_->SimulateTrickle(stream);
1136 void VerifyConnected() {
1139 void CloseP1() {
1140 p1_->Close();
1143 void ConnectThenDelete() {
1144 p2_->Connect(p1_, TRICKLE_NONE, false);
1145 p1_->Connect(p2_, TRICKLE_NONE, true);
1146 test_utils->sts_target()->Dispatch(WrapRunnable(this,
1147 &IceConnectTest::CloseP1),
1148 NS_DISPATCH_SYNC);
1149 p2_->StartChecks();
1151 // Wait to see if we crash
1152 PR_Sleep(PR_MillisecondsToInterval(kDefaultTimeout));
1155 void SendReceive() {
1156 // p1_->Send(2);
1157 test_utils->sts_target()->Dispatch(
1158 WrapRunnable(p1_.get(),
1159 &IceTestPeer::SendPacket, 0, 1,
1160 reinterpret_cast<const unsigned char *>("TEST"), 4),
1161 NS_DISPATCH_SYNC);
1162 ASSERT_EQ(1u, p1_->sent());
1163 ASSERT_TRUE_WAIT(p2_->received() == 1, 1000);
1166 protected:
1167 bool initted_;
1168 nsCOMPtr<nsIEventTarget> target_;
1169 mozilla::ScopedDeletePtr<IceTestPeer> p1_;
1170 mozilla::ScopedDeletePtr<IceTestPeer> p2_;
1173 class PrioritizerTest : public ::testing::Test {
1174 public:
1175 PrioritizerTest():
1176 prioritizer_(nullptr) {}
1178 ~PrioritizerTest() {
1179 if (prioritizer_) {
1180 nr_interface_prioritizer_destroy(&prioritizer_);
1184 void SetPriorizer(nr_interface_prioritizer *prioritizer) {
1185 prioritizer_ = prioritizer;
1188 void AddInterface(const std::string& num, int type, int estimated_speed) {
1189 std::string str_addr = "10.0.0." + num;
1190 std::string ifname = "eth" + num;
1191 nr_local_addr local_addr;
1192 local_addr.interface.type = type;
1193 local_addr.interface.estimated_speed = estimated_speed;
1195 int r = nr_ip4_str_port_to_transport_addr(str_addr.c_str(), 0,
1196 IPPROTO_UDP, &(local_addr.addr));
1197 ASSERT_EQ(0, r);
1198 strncpy(local_addr.addr.ifname, ifname.c_str(), MAXIFNAME);
1200 r = nr_interface_prioritizer_add_interface(prioritizer_, &local_addr);
1201 ASSERT_EQ(0, r);
1202 r = nr_interface_prioritizer_sort_preference(prioritizer_);
1203 ASSERT_EQ(0, r);
1206 void HasLowerPreference(const std::string& num1, const std::string& num2) {
1207 std::string key1 = "eth" + num1 + ":10.0.0." + num1;
1208 std::string key2 = "eth" + num2 + ":10.0.0." + num2;
1209 UCHAR pref1, pref2;
1210 int r = nr_interface_prioritizer_get_priority(prioritizer_, key1.c_str(), &pref1);
1211 ASSERT_EQ(0, r);
1212 r = nr_interface_prioritizer_get_priority(prioritizer_, key2.c_str(), &pref2);
1213 ASSERT_EQ(0, r);
1214 ASSERT_LE(pref1, pref2);
1217 private:
1218 nr_interface_prioritizer *prioritizer_;
1221 class PacketFilterTest : public ::testing::Test {
1222 public:
1223 PacketFilterTest(): filter_(nullptr) {}
1225 void SetUp() {
1226 // Set up enough of the ICE ctx to allow the packet filter to work
1227 ice_ctx_ = NrIceCtx::Create("test", true);
1229 nsCOMPtr<nsIUDPSocketFilterHandler> handler =
1230 do_GetService(NS_STUN_UDP_SOCKET_FILTER_HANDLER_CONTRACTID);
1231 handler->NewFilter(getter_AddRefs(filter_));
1234 void TearDown() {
1235 test_utils->sts_target()->Dispatch(WrapRunnable(this,
1236 &PacketFilterTest::TearDown_s),
1237 NS_DISPATCH_SYNC);
1240 void TearDown_s() {
1241 ice_ctx_ = nullptr;
1244 void TestIncoming(const uint8_t* data, uint32_t len,
1245 uint8_t from_addr, int from_port,
1246 bool expected_result) {
1247 mozilla::net::NetAddr addr;
1248 MakeNetAddr(&addr, from_addr, from_port);
1249 bool result;
1250 nsresult rv = filter_->FilterPacket(&addr, data, len,
1251 nsIUDPSocketFilter::SF_INCOMING,
1252 &result);
1253 ASSERT_EQ(NS_OK, rv);
1254 ASSERT_EQ(expected_result, result);
1257 void TestOutgoing(const uint8_t* data, uint32_t len,
1258 uint8_t to_addr, int to_port,
1259 bool expected_result) {
1260 mozilla::net::NetAddr addr;
1261 MakeNetAddr(&addr, to_addr, to_port);
1262 bool result;
1263 nsresult rv = filter_->FilterPacket(&addr, data, len,
1264 nsIUDPSocketFilter::SF_OUTGOING,
1265 &result);
1266 ASSERT_EQ(NS_OK, rv);
1267 ASSERT_EQ(expected_result, result);
1270 private:
1271 void MakeNetAddr(mozilla::net::NetAddr* net_addr,
1272 uint8_t last_digit, uint16_t port) {
1273 net_addr->inet.family = AF_INET;
1274 net_addr->inet.ip = 192 << 24 | 168 << 16 | 1 << 8 | last_digit;
1275 net_addr->inet.port = port;
1278 nsCOMPtr<nsIUDPSocketFilter> filter_;
1279 RefPtr<NrIceCtx> ice_ctx_;
1281 } // end namespace
1283 TEST_F(IceGatherTest, TestGatherFakeStunServerHostnameNoResolver) {
1284 if (g_stun_server_hostname.empty()) {
1285 return;
1288 EnsurePeer();
1289 peer_->SetStunServer(g_stun_server_hostname, kDefaultStunServerPort);
1290 Gather();
1293 TEST_F(IceGatherTest, TestGatherFakeStunServerIpAddress) {
1294 if (g_stun_server_address.empty()) {
1295 return;
1298 EnsurePeer();
1299 peer_->SetStunServer(g_stun_server_address, kDefaultStunServerPort);
1300 peer_->SetFakeResolver();
1301 Gather();
1304 TEST_F(IceGatherTest, TestGatherFakeStunServerHostname) {
1305 if (g_stun_server_hostname.empty()) {
1306 return;
1309 EnsurePeer();
1310 peer_->SetStunServer(g_stun_server_hostname, kDefaultStunServerPort);
1311 peer_->SetFakeResolver();
1312 Gather();
1315 TEST_F(IceGatherTest, TestGatherFakeStunBogusHostname) {
1316 EnsurePeer();
1317 peer_->SetStunServer(kBogusStunServerHostname, kDefaultStunServerPort);
1318 peer_->SetFakeResolver();
1319 Gather();
1322 TEST_F(IceGatherTest, TestGatherDNSStunServerIpAddress) {
1323 if (g_stun_server_address.empty()) {
1324 return;
1327 EnsurePeer();
1328 peer_->SetStunServer(g_stun_server_address, kDefaultStunServerPort);
1329 peer_->SetDNSResolver();
1330 Gather();
1331 // TODO(jib@mozilla.com): ensure we get server reflexive candidates Bug 848094
1334 TEST_F(IceGatherTest, TestGatherDNSStunServerHostname) {
1335 if (g_stun_server_hostname.empty()) {
1336 return;
1339 EnsurePeer();
1340 peer_->SetStunServer(g_stun_server_hostname, kDefaultStunServerPort);
1341 peer_->SetDNSResolver();
1342 Gather();
1345 TEST_F(IceGatherTest, TestGatherDNSStunBogusHostname) {
1346 EnsurePeer();
1347 peer_->SetStunServer(kBogusStunServerHostname, kDefaultStunServerPort);
1348 peer_->SetDNSResolver();
1349 Gather();
1352 TEST_F(IceGatherTest, TestGatherTurn) {
1353 EnsurePeer();
1354 if (g_turn_server.empty())
1355 return;
1356 peer_->SetTurnServer(g_turn_server, kDefaultStunServerPort,
1357 g_turn_user, g_turn_password, kNrIceTransportUdp);
1358 Gather();
1361 TEST_F(IceGatherTest, TestGatherTurnTcp) {
1362 EnsurePeer();
1363 if (g_turn_server.empty())
1364 return;
1365 peer_->SetTurnServer(g_turn_server, kDefaultStunServerPort,
1366 g_turn_user, g_turn_password, kNrIceTransportTcp);
1367 Gather();
1370 TEST_F(IceGatherTest, TestGatherDisableComponent) {
1371 if (g_stun_server_hostname.empty()) {
1372 return;
1375 EnsurePeer();
1376 peer_->SetStunServer(g_stun_server_hostname, kDefaultStunServerPort);
1377 peer_->AddStream(2);
1378 peer_->DisableComponent(1, 2);
1379 Gather();
1380 std::vector<std::string> candidates =
1381 peer_->GetCandidates(1);
1383 for (size_t i=0; i<candidates.size(); ++i) {
1384 size_t sp1 = candidates[i].find(' ');
1385 ASSERT_EQ(0, candidates[i].compare(sp1+1, 1, "1", 1));
1389 TEST_F(IceGatherTest, TestGatherVerifyNoLoopback) {
1390 Gather();
1391 ASSERT_FALSE(StreamHasMatchingCandidate(0, "127.0.0.1"));
1394 TEST_F(IceGatherTest, TestGatherAllowLoopback) {
1395 // Set up peer with loopback allowed.
1396 peer_ = new IceTestPeer("P1", true, false, true);
1397 peer_->AddStream(1);
1398 Gather();
1399 ASSERT_TRUE(StreamHasMatchingCandidate(0, "127.0.0.1"));
1402 // Verify that a bogus candidate doesn't cause crashes on the
1403 // main thread. See bug 856433.
1404 TEST_F(IceGatherTest, TestBogusCandidate) {
1405 Gather();
1406 peer_->ParseCandidate(0, kBogusIceCandidate);
1409 TEST_F(IceGatherTest, VerifyTestStunServer) {
1410 UseFakeStunServerWithResponse("192.0.2.133", 3333);
1411 Gather();
1412 ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.2.133 3333 "));
1415 TEST_F(IceGatherTest, TestStunServerReturnsWildcardAddr) {
1416 UseFakeStunServerWithResponse("0.0.0.0", 3333);
1417 Gather(kDefaultTimeout * 3);
1418 ASSERT_FALSE(StreamHasMatchingCandidate(0, " 0.0.0.0 "));
1421 TEST_F(IceGatherTest, TestStunServerReturnsPort0) {
1422 UseFakeStunServerWithResponse("192.0.2.133", 0);
1423 Gather(kDefaultTimeout * 3);
1424 ASSERT_FALSE(StreamHasMatchingCandidate(0, " 192.0.2.133 0 "));
1427 TEST_F(IceGatherTest, TestStunServerReturnsLoopbackAddr) {
1428 UseFakeStunServerWithResponse("127.0.0.133", 3333);
1429 Gather(kDefaultTimeout * 3);
1430 ASSERT_FALSE(StreamHasMatchingCandidate(0, " 127.0.0.133 "));
1433 TEST_F(IceGatherTest, TestStunServerTrickle) {
1434 UseFakeStunServerWithResponse("192.0.2.1", 3333);
1435 TestStunServer::GetInstance()->SetActive(false);
1436 Gather(0);
1437 ASSERT_FALSE(StreamHasMatchingCandidate(0, "192.0.2.1"));
1438 TestStunServer::GetInstance()->SetActive(true);
1439 WaitForGather();
1440 ASSERT_TRUE(StreamHasMatchingCandidate(0, "192.0.2.1"));
1443 TEST_F(IceConnectTest, TestGather) {
1444 AddStream("first", 1);
1445 ASSERT_TRUE(Gather());
1448 TEST_F(IceConnectTest, TestGatherAutoPrioritize) {
1449 Init(false, false);
1450 AddStream("first", 1);
1451 ASSERT_TRUE(Gather());
1455 TEST_F(IceConnectTest, TestConnect) {
1456 AddStream("first", 1);
1457 ASSERT_TRUE(Gather());
1458 Connect();
1461 TEST_F(IceConnectTest, TestLoopbackOnlySortOf) {
1462 Init(false, true);
1463 AddStream("first", 1);
1464 ASSERT_TRUE(Gather());
1465 SetCandidateFilter(IsLoopbackCandidate);
1466 SetExpectedCandidateAddr("127.0.0.1");
1467 Connect();
1471 TEST_F(IceConnectTest, TestConnectBothControllingP1Wins) {
1472 AddStream("first", 1);
1473 p1_->SetTiebreaker(1);
1474 p2_->SetTiebreaker(0);
1475 ASSERT_TRUE(Gather());
1476 p1_->SetControlling(NrIceCtx::ICE_CONTROLLING);
1477 p2_->SetControlling(NrIceCtx::ICE_CONTROLLING);
1478 Connect();
1481 TEST_F(IceConnectTest, TestConnectBothControllingP2Wins) {
1482 AddStream("first", 1);
1483 p1_->SetTiebreaker(0);
1484 p2_->SetTiebreaker(1);
1485 ASSERT_TRUE(Gather());
1486 p1_->SetControlling(NrIceCtx::ICE_CONTROLLING);
1487 p2_->SetControlling(NrIceCtx::ICE_CONTROLLING);
1488 Connect();
1491 TEST_F(IceConnectTest, TestConnectIceLiteOfferer) {
1492 AddStream("first", 1);
1493 ASSERT_TRUE(Gather());
1494 p1_->SimulateIceLite();
1495 Connect();
1498 TEST_F(IceConnectTest, TestTrickleBothControllingP1Wins) {
1499 AddStream("first", 1);
1500 p1_->SetTiebreaker(1);
1501 p2_->SetTiebreaker(0);
1502 ASSERT_TRUE(Gather());
1503 p1_->SetControlling(NrIceCtx::ICE_CONTROLLING);
1504 p2_->SetControlling(NrIceCtx::ICE_CONTROLLING);
1505 ConnectTrickle();
1506 SimulateTrickle(0);
1507 ASSERT_TRUE_WAIT(p1_->ice_complete(), 1000);
1508 ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
1509 AssertCheckingReached();
1512 TEST_F(IceConnectTest, TestTrickleBothControllingP2Wins) {
1513 AddStream("first", 1);
1514 p1_->SetTiebreaker(0);
1515 p2_->SetTiebreaker(1);
1516 ASSERT_TRUE(Gather());
1517 p1_->SetControlling(NrIceCtx::ICE_CONTROLLING);
1518 p2_->SetControlling(NrIceCtx::ICE_CONTROLLING);
1519 ConnectTrickle();
1520 SimulateTrickle(0);
1521 ASSERT_TRUE_WAIT(p1_->ice_complete(), 1000);
1522 ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
1523 AssertCheckingReached();
1526 TEST_F(IceConnectTest, TestTrickleIceLiteOfferer) {
1527 AddStream("first", 1);
1528 ASSERT_TRUE(Gather());
1529 p1_->SimulateIceLite();
1530 ConnectTrickle();
1531 SimulateTrickle(0);
1532 ASSERT_TRUE_WAIT(p1_->ice_complete(), 1000);
1533 ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
1534 AssertCheckingReached();
1537 TEST_F(IceConnectTest, TestConnectTwoComponents) {
1538 AddStream("first", 2);
1539 ASSERT_TRUE(Gather());
1540 Connect();
1543 TEST_F(IceConnectTest, TestConnectTwoComponentsDisableSecond) {
1544 AddStream("first", 2);
1545 ASSERT_TRUE(Gather());
1546 p1_->DisableComponent(0, 2);
1547 p2_->DisableComponent(0, 2);
1548 Connect();
1552 TEST_F(IceConnectTest, TestConnectP2ThenP1) {
1553 AddStream("first", 1);
1554 ASSERT_TRUE(Gather());
1555 ConnectP2();
1556 PR_Sleep(1000);
1557 ConnectP1();
1558 WaitForComplete();
1561 TEST_F(IceConnectTest, TestConnectP2ThenP1Trickle) {
1562 AddStream("first", 1);
1563 ASSERT_TRUE(Gather());
1564 ConnectP2();
1565 PR_Sleep(1000);
1566 ConnectP1(TRICKLE_SIMULATE);
1567 SimulateTrickleP1(0);
1568 WaitForComplete();
1571 TEST_F(IceConnectTest, TestConnectP2ThenP1TrickleTwoComponents) {
1572 AddStream("first", 1);
1573 AddStream("second", 2);
1574 ASSERT_TRUE(Gather());
1575 ConnectP2();
1576 PR_Sleep(1000);
1577 ConnectP1(TRICKLE_SIMULATE);
1578 SimulateTrickleP1(0);
1579 std::cerr << "Sleeping between trickle streams" << std::endl;
1580 PR_Sleep(1000); // Give this some time to settle but not complete
1581 // all of ICE.
1582 SimulateTrickleP1(1);
1583 WaitForComplete(2);
1586 TEST_F(IceConnectTest, TestConnectAutoPrioritize) {
1587 Init(false, false);
1588 AddStream("first", 1);
1589 ASSERT_TRUE(Gather());
1590 Connect();
1593 TEST_F(IceConnectTest, TestConnectTrickleOneStreamOneComponent) {
1594 AddStream("first", 1);
1595 ASSERT_TRUE(Gather());
1596 ConnectTrickle();
1597 SimulateTrickle(0);
1598 ASSERT_TRUE_WAIT(p1_->ice_complete(), 1000);
1599 ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
1600 AssertCheckingReached();
1603 TEST_F(IceConnectTest, TestConnectTrickleTwoStreamsOneComponent) {
1604 AddStream("first", 1);
1605 AddStream("second", 1);
1606 ASSERT_TRUE(Gather());
1607 ConnectTrickle();
1608 SimulateTrickle(0);
1609 SimulateTrickle(1);
1610 ASSERT_TRUE_WAIT(p1_->ice_complete(), 1000);
1611 ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
1612 AssertCheckingReached();
1615 TEST_F(IceConnectTest, TestConnectRealTrickleOneStreamOneComponent) {
1616 AddStream("first", 1);
1617 AddStream("second", 1);
1618 ASSERT_TRUE(Gather(0));
1619 ConnectTrickle(TRICKLE_REAL);
1620 ASSERT_TRUE_WAIT(p1_->ice_complete(), kDefaultTimeout);
1621 ASSERT_TRUE_WAIT(p2_->ice_complete(), kDefaultTimeout);
1622 WaitForGather(); // ICE can complete before we finish gathering.
1623 AssertCheckingReached();
1626 TEST_F(IceConnectTest, TestSendReceive) {
1627 AddStream("first", 1);
1628 ASSERT_TRUE(Gather());
1629 Connect();
1630 SendReceive();
1633 TEST_F(IceConnectTest, TestConnectTurn) {
1634 if (g_turn_server.empty())
1635 return;
1637 AddStream("first", 1);
1638 SetTurnServer(g_turn_server, kDefaultStunServerPort,
1639 g_turn_user, g_turn_password);
1640 ASSERT_TRUE(Gather());
1641 Connect();
1644 TEST_F(IceConnectTest, TestConnectTurnWithDelay) {
1645 if (g_turn_server.empty())
1646 return;
1648 AddStream("first", 1);
1649 SetTurnServer(g_turn_server, kDefaultStunServerPort,
1650 g_turn_user, g_turn_password);
1651 SetCandidateFilter(SabotageHostCandidateAndDropReflexive);
1652 p1_->Gather();
1653 PR_Sleep(500);
1654 p2_->Gather();
1655 ConnectTrickle(TRICKLE_REAL);
1656 WaitForGather();
1657 WaitForComplete();
1660 void RealisticTrickleDelay(
1661 std::vector<SchedulableTrickleCandidate*>& candidates) {
1662 for (size_t i = 0; i < candidates.size(); ++i) {
1663 SchedulableTrickleCandidate* cand = candidates[i];
1664 if (cand->IsHost()) {
1665 cand->Schedule(i*10);
1666 } else if (cand->IsReflexive()) {
1667 cand->Schedule(i*10 + 100);
1668 } else if (cand->IsRelay()) {
1669 cand->Schedule(i*10 + 200);
1674 void DelayRelayCandidates(
1675 std::vector<SchedulableTrickleCandidate*>& candidates,
1676 unsigned int ms) {
1677 for (auto i = candidates.begin(); i != candidates.end(); ++i) {
1678 if ((*i)->IsRelay()) {
1679 (*i)->Schedule(ms);
1680 } else {
1681 (*i)->Schedule(0);
1686 TEST_F(IceConnectTest, TestConnectTurnWithNormalTrickleDelay) {
1687 if (g_turn_server.empty())
1688 return;
1690 AddStream("first", 1);
1691 SetTurnServer(g_turn_server, kDefaultStunServerPort,
1692 g_turn_user, g_turn_password);
1693 ASSERT_TRUE(Gather());
1694 ConnectTrickle();
1695 RealisticTrickleDelay(p1_->ControlTrickle(0));
1696 RealisticTrickleDelay(p2_->ControlTrickle(0));
1698 ASSERT_TRUE_WAIT(p1_->ice_complete(), kDefaultTimeout);
1699 ASSERT_TRUE_WAIT(p2_->ice_complete(), kDefaultTimeout);
1700 AssertCheckingReached();
1703 TEST_F(IceConnectTest, TestConnectTurnWithNormalTrickleDelayOneSided) {
1704 if (g_turn_server.empty())
1705 return;
1707 AddStream("first", 1);
1708 SetTurnServer(g_turn_server, kDefaultStunServerPort,
1709 g_turn_user, g_turn_password);
1710 ASSERT_TRUE(Gather());
1711 ConnectTrickle();
1712 RealisticTrickleDelay(p1_->ControlTrickle(0));
1713 p2_->SimulateTrickle(0);
1715 ASSERT_TRUE_WAIT(p1_->ice_complete(), kDefaultTimeout);
1716 ASSERT_TRUE_WAIT(p2_->ice_complete(), kDefaultTimeout);
1717 AssertCheckingReached();
1720 TEST_F(IceConnectTest, TestConnectTurnWithLargeTrickleDelay) {
1721 if (g_turn_server.empty())
1722 return;
1724 AddStream("first", 1);
1725 SetTurnServer(g_turn_server, kDefaultStunServerPort,
1726 g_turn_user, g_turn_password);
1727 SetCandidateFilter(SabotageHostCandidateAndDropReflexive);
1728 ASSERT_TRUE(Gather());
1729 ConnectTrickle();
1730 // Trickle host candidates immediately, but delay relay candidates
1731 DelayRelayCandidates(p1_->ControlTrickle(0), 3700);
1732 DelayRelayCandidates(p2_->ControlTrickle(0), 3700);
1734 ASSERT_TRUE_WAIT(p1_->ice_complete(), kDefaultTimeout);
1735 ASSERT_TRUE_WAIT(p2_->ice_complete(), kDefaultTimeout);
1736 AssertCheckingReached();
1739 TEST_F(IceConnectTest, TestConnectTurnTcp) {
1740 if (g_turn_server.empty())
1741 return;
1743 AddStream("first", 1);
1744 SetTurnServer(g_turn_server, kDefaultStunServerPort,
1745 g_turn_user, g_turn_password, kNrIceTransportTcp);
1746 ASSERT_TRUE(Gather());
1747 Connect();
1750 TEST_F(IceConnectTest, TestConnectTurnOnly) {
1751 if (g_turn_server.empty())
1752 return;
1754 AddStream("first", 1);
1755 SetTurnServer(g_turn_server, kDefaultStunServerPort,
1756 g_turn_user, g_turn_password);
1757 ASSERT_TRUE(Gather());
1758 SetCandidateFilter(IsRelayCandidate);
1759 SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
1760 NrIceCandidate::Type::ICE_RELAYED);
1761 Connect();
1764 TEST_F(IceConnectTest, TestConnectTurnTcpOnly) {
1765 if (g_turn_server.empty())
1766 return;
1768 AddStream("first", 1);
1769 SetTurnServer(g_turn_server, kDefaultStunServerPort,
1770 g_turn_user, g_turn_password, kNrIceTransportTcp);
1771 ASSERT_TRUE(Gather());
1772 SetCandidateFilter(IsRelayCandidate);
1773 SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
1774 NrIceCandidate::Type::ICE_RELAYED,
1775 kNrIceTransportTcp);
1776 Connect();
1779 TEST_F(IceConnectTest, TestSendReceiveTurnOnly) {
1780 if (g_turn_server.empty())
1781 return;
1783 AddStream("first", 1);
1784 SetTurnServer(g_turn_server, kDefaultStunServerPort,
1785 g_turn_user, g_turn_password);
1786 ASSERT_TRUE(Gather());
1787 SetCandidateFilter(IsRelayCandidate);
1788 SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
1789 NrIceCandidate::Type::ICE_RELAYED);
1790 Connect();
1791 SendReceive();
1794 TEST_F(IceConnectTest, TestSendReceiveTurnTcpOnly) {
1795 if (g_turn_server.empty())
1796 return;
1798 AddStream("first", 1);
1799 SetTurnServer(g_turn_server, kDefaultStunServerPort,
1800 g_turn_user, g_turn_password, kNrIceTransportTcp);
1801 ASSERT_TRUE(Gather());
1802 SetCandidateFilter(IsRelayCandidate);
1803 SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
1804 NrIceCandidate::Type::ICE_RELAYED,
1805 kNrIceTransportTcp);
1806 Connect();
1807 SendReceive();
1810 TEST_F(IceConnectTest, TestSendReceiveTurnBothOnly) {
1811 if (g_turn_server.empty())
1812 return;
1814 AddStream("first", 1);
1815 std::vector<NrIceTurnServer> turn_servers;
1816 std::vector<unsigned char> password_vec(g_turn_password.begin(),
1817 g_turn_password.end());
1818 turn_servers.push_back(*NrIceTurnServer::Create(
1819 g_turn_server, kDefaultStunServerPort,
1820 g_turn_user, password_vec, kNrIceTransportTcp));
1821 turn_servers.push_back(*NrIceTurnServer::Create(
1822 g_turn_server, kDefaultStunServerPort,
1823 g_turn_user, password_vec, kNrIceTransportUdp));
1824 SetTurnServers(turn_servers);
1825 ASSERT_TRUE(Gather());
1826 SetCandidateFilter(IsRelayCandidate);
1827 // UDP is preferred.
1828 SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
1829 NrIceCandidate::Type::ICE_RELAYED,
1830 kNrIceTransportUdp);
1831 Connect();
1832 SendReceive();
1835 TEST_F(IceConnectTest, TestConnectShutdownOneSide) {
1836 AddStream("first", 1);
1837 ASSERT_TRUE(Gather());
1838 ConnectThenDelete();
1841 TEST_F(IceConnectTest, TestPollCandPairsBeforeConnect) {
1842 AddStream("first", 1);
1843 ASSERT_TRUE(Gather());
1845 std::vector<NrIceCandidatePair> pairs;
1846 nsresult res = p1_->GetCandidatePairs(0, &pairs);
1847 // There should be no candidate pairs prior to calling Connect()
1848 ASSERT_TRUE(NS_FAILED(res));
1849 ASSERT_EQ(0U, pairs.size());
1851 res = p2_->GetCandidatePairs(0, &pairs);
1852 ASSERT_TRUE(NS_FAILED(res));
1853 ASSERT_EQ(0U, pairs.size());
1856 TEST_F(IceConnectTest, TestPollCandPairsAfterConnect) {
1857 AddStream("first", 1);
1858 ASSERT_TRUE(Gather());
1859 Connect();
1861 std::vector<NrIceCandidatePair> pairs;
1862 nsresult r = p1_->GetCandidatePairs(0, &pairs);
1863 ASSERT_EQ(NS_OK, r);
1864 // How detailed of a check do we want to do here? If the turn server is
1865 // functioning, we'll get at least two pairs, but this is probably not
1866 // something we should assume.
1867 ASSERT_NE(0U, pairs.size());
1868 ASSERT_TRUE(p1_->CandidatePairsPriorityDescending(pairs));
1869 ASSERT_TRUE(ContainsSucceededPair(pairs));
1870 pairs.clear();
1872 r = p2_->GetCandidatePairs(0, &pairs);
1873 ASSERT_EQ(NS_OK, r);
1874 ASSERT_NE(0U, pairs.size());
1875 ASSERT_TRUE(p2_->CandidatePairsPriorityDescending(pairs));
1876 ASSERT_TRUE(ContainsSucceededPair(pairs));
1879 TEST_F(IceConnectTest, TestPollCandPairsDuringConnect) {
1880 AddStream("first", 1);
1881 ASSERT_TRUE(Gather());
1883 p2_->Connect(p1_, TRICKLE_NONE, false);
1884 p1_->Connect(p2_, TRICKLE_NONE, false);
1886 std::vector<NrIceCandidatePair> pairs1;
1887 std::vector<NrIceCandidatePair> pairs2;
1889 p1_->StartChecks();
1890 p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
1891 p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
1893 p2_->StartChecks();
1894 p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
1895 p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
1897 WaitForComplete();
1898 p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
1899 p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
1900 ASSERT_TRUE(ContainsSucceededPair(pairs1));
1901 ASSERT_TRUE(ContainsSucceededPair(pairs2));
1904 TEST_F(IceConnectTest, TestRLogRingBuffer) {
1905 AddStream("first", 1);
1906 ASSERT_TRUE(Gather());
1908 p2_->Connect(p1_, TRICKLE_NONE, false);
1909 p1_->Connect(p2_, TRICKLE_NONE, false);
1911 std::vector<NrIceCandidatePair> pairs1;
1912 std::vector<NrIceCandidatePair> pairs2;
1914 p1_->StartChecks();
1915 p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
1916 p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
1918 p2_->StartChecks();
1919 p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
1920 p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
1922 WaitForComplete();
1923 p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
1924 p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
1925 ASSERT_TRUE(ContainsSucceededPair(pairs1));
1926 ASSERT_TRUE(ContainsSucceededPair(pairs2));
1928 for (auto p = pairs1.begin(); p != pairs1.end(); ++p) {
1929 std::deque<std::string> logs;
1930 std::string substring("CAND-PAIR(");
1931 substring += p->codeword;
1932 RLogRingBuffer::GetInstance()->Filter(substring, 0, &logs);
1933 ASSERT_NE(0U, logs.size());
1936 for (auto p = pairs2.begin(); p != pairs2.end(); ++p) {
1937 std::deque<std::string> logs;
1938 std::string substring("CAND-PAIR(");
1939 substring += p->codeword;
1940 RLogRingBuffer::GetInstance()->Filter(substring, 0, &logs);
1941 ASSERT_NE(0U, logs.size());
1945 TEST_F(PrioritizerTest, TestPrioritizer) {
1946 SetPriorizer(::mozilla::CreateInterfacePrioritizer());
1948 AddInterface("0", NR_INTERFACE_TYPE_VPN, 100); // unknown vpn
1949 AddInterface("1", NR_INTERFACE_TYPE_VPN | NR_INTERFACE_TYPE_WIRED, 100); // wired vpn
1950 AddInterface("2", NR_INTERFACE_TYPE_VPN | NR_INTERFACE_TYPE_WIFI, 100); // wifi vpn
1951 AddInterface("3", NR_INTERFACE_TYPE_VPN | NR_INTERFACE_TYPE_MOBILE, 100); // wifi vpn
1952 AddInterface("4", NR_INTERFACE_TYPE_WIRED, 1000); // wired, high speed
1953 AddInterface("5", NR_INTERFACE_TYPE_WIRED, 10); // wired, low speed
1954 AddInterface("6", NR_INTERFACE_TYPE_WIFI, 10); // wifi, low speed
1955 AddInterface("7", NR_INTERFACE_TYPE_WIFI, 1000); // wifi, high speed
1956 AddInterface("8", NR_INTERFACE_TYPE_MOBILE, 10); // mobile, low speed
1957 AddInterface("9", NR_INTERFACE_TYPE_MOBILE, 1000); // mobile, high speed
1958 AddInterface("10", NR_INTERFACE_TYPE_UNKNOWN, 10); // unknown, low speed
1959 AddInterface("11", NR_INTERFACE_TYPE_UNKNOWN, 1000); // unknown, high speed
1961 // expected preference "4" > "5" > "1" > "7" > "6" > "2" > "9" > "8" > "3" > "11" > "10" > "0"
1963 HasLowerPreference("0", "10");
1964 HasLowerPreference("10", "11");
1965 HasLowerPreference("11", "3");
1966 HasLowerPreference("3", "8");
1967 HasLowerPreference("8", "9");
1968 HasLowerPreference("9", "2");
1969 HasLowerPreference("2", "6");
1970 HasLowerPreference("6", "7");
1971 HasLowerPreference("7", "1");
1972 HasLowerPreference("1", "5");
1973 HasLowerPreference("5", "4");
1976 TEST_F(PacketFilterTest, TestSendNonStunPacket) {
1977 const unsigned char data[] = "12345abcde";
1978 TestOutgoing(data, sizeof(data), 123, 45, false);
1981 TEST_F(PacketFilterTest, TestRecvNonStunPacket) {
1982 const unsigned char data[] = "12345abcde";
1983 TestIncoming(data, sizeof(data), 123, 45, false);
1986 TEST_F(PacketFilterTest, TestSendStunPacket) {
1987 nr_stun_message *msg;
1988 ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
1989 msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
1990 ASSERT_EQ(0, nr_stun_encode_message(msg));
1991 TestOutgoing(msg->buffer, msg->length, 123, 45, true);
1992 ASSERT_EQ(0, nr_stun_message_destroy(&msg));
1995 TEST_F(PacketFilterTest, TestRecvStunPacketWithoutAPendingId) {
1996 nr_stun_message *msg;
1997 ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
1999 msg->header.id.octet[0] = 1;
2000 msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
2001 ASSERT_EQ(0, nr_stun_encode_message(msg));
2002 TestOutgoing(msg->buffer, msg->length, 123, 45, true);
2004 msg->header.id.octet[0] = 0;
2005 msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
2006 ASSERT_EQ(0, nr_stun_encode_message(msg));
2007 TestIncoming(msg->buffer, msg->length, 123, 45, true);
2009 ASSERT_EQ(0, nr_stun_message_destroy(&msg));
2012 TEST_F(PacketFilterTest, TestRecvStunPacketWithoutAPendingAddress) {
2013 nr_stun_message *msg;
2014 ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
2016 msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
2017 ASSERT_EQ(0, nr_stun_encode_message(msg));
2018 TestOutgoing(msg->buffer, msg->length, 123, 45, true);
2020 msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
2021 ASSERT_EQ(0, nr_stun_encode_message(msg));
2022 TestIncoming(msg->buffer, msg->length, 123, 46, false);
2023 TestIncoming(msg->buffer, msg->length, 124, 45, false);
2025 ASSERT_EQ(0, nr_stun_message_destroy(&msg));
2028 TEST_F(PacketFilterTest, TestRecvStunPacketWithPendingIdAndAddress) {
2029 nr_stun_message *msg;
2030 ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
2032 msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
2033 ASSERT_EQ(0, nr_stun_encode_message(msg));
2034 TestOutgoing(msg->buffer, msg->length, 123, 45, true);
2036 msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
2037 ASSERT_EQ(0, nr_stun_encode_message(msg));
2038 TestIncoming(msg->buffer, msg->length, 123, 45, true);
2040 // Test whitelist by filtering non-stun packets.
2041 const unsigned char data[] = "12345abcde";
2043 // 123:45 is white-listed.
2044 TestOutgoing(data, sizeof(data), 123, 45, true);
2045 TestIncoming(data, sizeof(data), 123, 45, true);
2047 // Indications pass as well.
2048 msg->header.type = NR_STUN_MSG_BINDING_INDICATION;
2049 ASSERT_EQ(0, nr_stun_encode_message(msg));
2050 TestOutgoing(msg->buffer, msg->length, 123, 45, true);
2051 TestIncoming(msg->buffer, msg->length, 123, 45, true);
2053 // Packets from and to other address are still disallowed.
2054 TestOutgoing(data, sizeof(data), 123, 46, false);
2055 TestIncoming(data, sizeof(data), 123, 46, false);
2056 TestOutgoing(data, sizeof(data), 124, 45, false);
2057 TestIncoming(data, sizeof(data), 124, 45, false);
2059 ASSERT_EQ(0, nr_stun_message_destroy(&msg));
2062 TEST_F(PacketFilterTest, TestSendNonRequestStunPacket) {
2063 nr_stun_message *msg;
2064 ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
2066 msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
2067 ASSERT_EQ(0, nr_stun_encode_message(msg));
2068 TestOutgoing(msg->buffer, msg->length, 123, 45, false);
2070 // Send a packet so we allow the incoming request.
2071 msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
2072 ASSERT_EQ(0, nr_stun_encode_message(msg));
2073 TestOutgoing(msg->buffer, msg->length, 123, 45, true);
2075 // This packet makes us able to send a response.
2076 msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
2077 ASSERT_EQ(0, nr_stun_encode_message(msg));
2078 TestIncoming(msg->buffer, msg->length, 123, 45, true);
2080 msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
2081 ASSERT_EQ(0, nr_stun_encode_message(msg));
2082 TestOutgoing(msg->buffer, msg->length, 123, 45, true);
2084 ASSERT_EQ(0, nr_stun_message_destroy(&msg));
2087 static std::string get_environment(const char *name) {
2088 char *value = getenv(name);
2090 if (!value)
2091 return "";
2093 return value;
2096 int main(int argc, char **argv)
2098 #ifdef LINUX
2099 // This test can cause intermittent oranges on the builders on Linux
2100 CHECK_ENVIRONMENT_FLAG("MOZ_WEBRTC_TESTS")
2101 #endif
2103 g_turn_server = get_environment("TURN_SERVER_ADDRESS");
2104 g_turn_user = get_environment("TURN_SERVER_USER");
2105 g_turn_password = get_environment("TURN_SERVER_PASSWORD");
2107 if (g_turn_server.empty() ||
2108 g_turn_user.empty(),
2109 g_turn_password.empty()) {
2110 printf(
2111 "Set TURN_SERVER_ADDRESS, TURN_SERVER_USER, and TURN_SERVER_PASSWORD\n"
2112 "environment variables to run this test\n");
2113 g_turn_server="";
2116 std::string tmp = get_environment("STUN_SERVER_ADDRESS");
2117 if (tmp != "")
2118 g_stun_server_address = tmp;
2121 tmp = get_environment("STUN_SERVER_HOSTNAME");
2122 if (tmp != "")
2123 g_stun_server_hostname = tmp;
2125 tmp = get_environment("MOZ_DISABLE_NONLOCAL_CONNECTIONS");
2127 if ((tmp != "" && tmp != "0") || getenv("MOZ_UPLOAD_DIR")) {
2128 // We're assuming that MOZ_UPLOAD_DIR is only set on tbpl;
2129 // MOZ_DISABLE_NONLOCAL_CONNECTIONS probably should be set when running the
2130 // cpp unit-tests, but is not presently.
2131 g_stun_server_address = "";
2132 g_stun_server_hostname = "";
2133 g_turn_server = "";
2136 test_utils = new MtransportTestUtils();
2137 NSS_NoDB_Init(nullptr);
2138 NSS_SetDomesticPolicy();
2140 // Start the tests
2141 ::testing::InitGoogleTest(&argc, argv);
2143 ::testing::TestEventListeners& listeners =
2144 ::testing::UnitTest::GetInstance()->listeners();
2145 // Adds a listener to the end. Google Test takes the ownership.
2147 listeners.Append(new test::RingbufferDumper(test_utils));
2148 test_utils->sts_target()->Dispatch(
2149 WrapRunnableNM(&TestStunServer::GetInstance), NS_DISPATCH_SYNC);
2151 int rv = RUN_ALL_TESTS();
2153 test_utils->sts_target()->Dispatch(
2154 WrapRunnableNM(&TestStunServer::ShutdownInstance), NS_DISPATCH_SYNC);
2156 delete test_utils;
2157 return rv;