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
24 #include "mozilla/Scoped.h"
25 #include "nsThreadUtils.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"
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
;
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
) {
90 static std::string
IsLoopbackCandidate(const std::string
& candidate
) {
91 if (candidate
.find("127.0.0.") != std::string::npos
) {
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
;
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
) {
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
{
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
;
159 class SchedulableTrickleCandidate
{
161 SchedulableTrickleCandidate(IceTestPeer
*peer
,
163 const std::string
&candidate
) :
166 candidate_(candidate
),
167 timer_handle_(nullptr) {
170 ~SchedulableTrickleCandidate() {
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
),
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();
192 std::string
& Candidate() {
196 const std::string
& Candidate() const {
200 size_t Stream() const {
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
;
219 std::string candidate_
;
222 DISALLOW_COPY_ASSIGN(SchedulableTrickleCandidate
);
225 class IceTestPeer
: public sigslot::has_slots
<> {
228 IceTestPeer(const std::string
& name
, bool offerer
, bool set_priorities
,
229 bool allow_loopback
= false) :
231 ice_ctx_(NrIceCtx::Create(name
, offerer
, set_priorities
, allow_loopback
)),
234 gathering_complete_(false),
236 ice_complete_(false),
237 ice_reached_checking_(false),
241 dns_resolver_(new NrIceResolver()),
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
),
249 simulate_ice_lite_(false) {
250 ice_ctx_
->SignalGatheringStateChange
.connect(
252 &IceTestPeer::GatheringStateChange
);
253 ice_ctx_
->SignalConnectionStateChange
.connect(
255 &IceTestPeer::ConnectionStateChange
);
259 test_utils
->sts_target()->Dispatch(WrapRunnable(this,
260 &IceTestPeer::Shutdown
),
263 // Give the ICE destruction callback time to fire before
264 // we destroy the resolver.
268 void AddStream(int components
) {
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
);
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
) {
286 // Happens when MOZ_DISABLE_NONLOCAL_CONNECTIONS is set
290 std::vector
<NrIceStunServer
> stun_servers
;
291 ScopedDeletePtr
<NrIceStunServer
> server(NrIceStunServer::Create(addr
,
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()) {
325 PRStatus status
= PR_StringToNetAddr(g_stun_server_address
.c_str(),
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())));
344 test_utils
->sts_target()->Dispatch(
345 WrapRunnableRet(ice_ctx_
, &NrIceCtx::StartGathering
, &res
),
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");
360 std::vector
<std::string
> GetCandidates(size_t stream
) {
361 std::vector
<std::string
> v
;
364 test_utils
->sts_target(),
365 WrapRunnableRet(this, &IceTestPeer::GetCandidates_s
, stream
, &v
));
370 std::string
FilterCandidate(const std::string
& candidate
) {
371 if (candidate_filter_
) {
372 return candidate_filter_(candidate
);
377 std::vector
<std::string
> GetCandidates_s(size_t stream
) {
378 std::vector
<std::string
> candidates
;
380 if (stream
>= streams_
.size())
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
);
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
,
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
));
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
));
455 res
= ice_ctx_
->StartChecks();
456 ASSERT_TRUE(NS_SUCCEEDED(res
));
460 void Connect(IceTestPeer
*remote
, TrickleMode trickle_mode
,
462 test_utils
->sts_target()->Dispatch(
464 this, &IceTestPeer::Connect_s
, remote
, trickle_mode
, start
),
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
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
) {
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
) {
510 if (which
.find("Remote") != std::string::npos
) {
511 addr
= cand
.cand_addr
.host
;
512 port
= cand
.cand_addr
.port
;
515 addr
= cand
.local_addr
.host
;
516 port
= cand
.local_addr
.port
;
519 case NrIceCandidate::ICE_HOST
:
522 case NrIceCandidate::ICE_SERVER_REFLEXIVE
:
525 case NrIceCandidate::ICE_PEER_REFLEXIVE
:
528 case NrIceCandidate::ICE_RELAYED
:
530 if (which
.find("Local") != std::string::npos
) {
531 type
+= "(" + cand
.local_addr
.transport
+ ")";
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
;
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
);
583 void DumpAndCheckActiveCandidates() {
584 test_utils
->sts_target()->Dispatch(
585 WrapRunnable(this, &IceTestPeer::DumpAndCheckActiveCandidates_s
),
590 test_utils
->sts_target()->Dispatch(
591 WrapRunnable(ice_ctx_
, &NrIceCtx::destroy_peer_ctx
),
596 for (auto s
= controlled_trickle_candidates_
.begin();
597 s
!= controlled_trickle_candidates_
.end();
599 for (auto cand
= s
->second
.begin(); cand
!= s
->second
.end(); ++cand
) {
611 test_utils
->sts_target()->Dispatch(
612 WrapRunnableRet(ice_ctx_
, &NrIceCtx::StartChecks
, &res
),
614 ASSERT_TRUE(NS_SUCCEEDED(res
));
618 void GatheringStateChange(NrIceCtx
* ctx
,
619 NrIceCtx::GatheringState state
) {
621 if (state
!= NrIceCtx::ICE_CTX_GATHER_COMPLETE
) {
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()) {
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
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(
661 ASSERT_TRUE(NS_SUCCEEDED(res
));
666 nsresult
GetCandidatePairs(size_t stream_index
,
667 std::vector
<NrIceCandidatePair
>* 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
;
676 test_utils
->sts_target()->Dispatch(
677 WrapRunnableRet(streams_
[stream_index
],
678 &NrIceMediaStream::GetCandidatePairs
,
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
>&
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
]);
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
]);
735 priority
= pairs
[p
].priority
;
740 void UpdateAndValidateCandidatePairs(size_t stream_index
,
741 std::vector
<NrIceCandidatePair
>*
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(),
764 std::inserter(added_pairs
, added_pairs
.begin()),
765 IceCandidatePairCompare());
767 std::set_difference(old_pairs
.begin(),
769 (*new_pairs
).begin(),
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 "
790 void StreamReady(NrIceMediaStream
*stream
) {
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
) {
804 case NrIceCtx::ICE_CTX_INIT
:
806 case NrIceCtx::ICE_CTX_CHECKING
:
807 std::cerr
<< "ICE checking " << name_
<< std::endl
;
808 ice_reached_checking_
= true;
810 case NrIceCtx::ICE_CTX_OPEN
:
811 std::cerr
<< "ICE completed " << name_
<< std::endl
;
812 ice_complete_
= true;
814 case NrIceCtx::ICE_CTX_FAILED
:
819 void PacketReceived(NrIceMediaStream
*stream
, int component
, const unsigned char *data
,
821 std::cerr
<< "Received " << len
<< " bytes" << std::endl
;
825 void SendPacket(int stream
, int component
, const unsigned char *data
,
827 ASSERT_TRUE(NS_SUCCEEDED(streams_
[stream
]->SendPacket(component
, data
, len
)));
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
) {
855 test_utils
->sts_target()->Dispatch(
856 WrapRunnableRet(ice_ctx_
,
857 &NrIceCtx::SetControlling
,
861 ASSERT_TRUE(NS_SUCCEEDED(res
));
864 void SetTiebreaker(uint64_t tiebreaker
) {
865 test_utils
->sts_target()->Dispatch(
867 &IceTestPeer::SetTiebreaker_s
,
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
);
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_
;
892 bool ice_reached_checking_
;
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_
;
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
{
918 test_utils
->sts_target()->Dispatch(WrapRunnable(TestStunServer::GetInstance(),
919 &TestStunServer::Reset
),
926 test_utils
->sts_target()->Dispatch(WrapRunnable(this,
927 &IceGatherTest::TearDown_s
),
932 NrIceCtx::internal_DeinitializeGlobal();
937 peer_
= new IceTestPeer("P1", true, false);
942 void Gather(unsigned int waitTime
= kDefaultTimeout
) {
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
) {
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
)) {
978 mozilla::ScopedDeletePtr
<IceTestPeer
> peer_
;
981 class IceConnectTest
: public ::testing::Test
{
983 IceConnectTest() : initted_(false) {}
987 target_
= do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID
, &rv
);
988 ASSERT_TRUE(NS_SUCCEEDED(rv
));
995 test_utils
->sts_target()->Dispatch(WrapRunnable(this,
996 &IceConnectTest::TearDown_s
),
1001 NrIceCtx::internal_DeinitializeGlobal();
1004 void AddStream(const std::string
& name
, int components
) {
1006 p1_
->AddStream(components
);
1007 p2_
->AddStream(components
);
1010 void Init(bool set_priorities
, bool allow_loopback
) {
1012 p1_
= new IceTestPeer("P1", true, set_priorities
, allow_loopback
);
1013 p2_
= new IceTestPeer("P2", false, set_priorities
, allow_loopback
);
1018 bool Gather(unsigned int waitTime
= kDefaultTimeout
) {
1020 p1_
->SetStunServer(g_stun_server_address
, kDefaultStunServerPort
);
1021 p2_
->SetStunServer(g_stun_server_address
, kDefaultStunServerPort
);
1026 EXPECT_TRUE_WAIT(p1_
->gathering_complete(), waitTime
);
1027 if (!p1_
->gathering_complete())
1029 EXPECT_TRUE_WAIT(p2_
->gathering_complete(), waitTime
);
1030 if (!p2_
->gathering_complete())
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
);
1052 p2_
->SetCandidateFilter(filter
);
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
1061 p2_
->Connect(p1_
, TRICKLE_NONE
);
1062 p1_
->Connect(p2_
, TRICKLE_NONE
);
1064 ASSERT_TRUE_WAIT(p1_
->ready_ct() == 1 && p2_
->ready_ct() == 1,
1066 ASSERT_TRUE_WAIT(p1_
->ice_complete() && p2_
->ice_complete(),
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(),
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() {
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
),
1151 // Wait to see if we crash
1152 PR_Sleep(PR_MillisecondsToInterval(kDefaultTimeout
));
1155 void SendReceive() {
1157 test_utils
->sts_target()->Dispatch(
1158 WrapRunnable(p1_
.get(),
1159 &IceTestPeer::SendPacket
, 0, 1,
1160 reinterpret_cast<const unsigned char *>("TEST"), 4),
1162 ASSERT_EQ(1u, p1_
->sent());
1163 ASSERT_TRUE_WAIT(p2_
->received() == 1, 1000);
1168 nsCOMPtr
<nsIEventTarget
> target_
;
1169 mozilla::ScopedDeletePtr
<IceTestPeer
> p1_
;
1170 mozilla::ScopedDeletePtr
<IceTestPeer
> p2_
;
1173 class PrioritizerTest
: public ::testing::Test
{
1176 prioritizer_(nullptr) {}
1178 ~PrioritizerTest() {
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
));
1198 strncpy(local_addr
.addr
.ifname
, ifname
.c_str(), MAXIFNAME
);
1200 r
= nr_interface_prioritizer_add_interface(prioritizer_
, &local_addr
);
1202 r
= nr_interface_prioritizer_sort_preference(prioritizer_
);
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
;
1210 int r
= nr_interface_prioritizer_get_priority(prioritizer_
, key1
.c_str(), &pref1
);
1212 r
= nr_interface_prioritizer_get_priority(prioritizer_
, key2
.c_str(), &pref2
);
1214 ASSERT_LE(pref1
, pref2
);
1218 nr_interface_prioritizer
*prioritizer_
;
1221 class PacketFilterTest
: public ::testing::Test
{
1223 PacketFilterTest(): filter_(nullptr) {}
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_
));
1235 test_utils
->sts_target()->Dispatch(WrapRunnable(this,
1236 &PacketFilterTest::TearDown_s
),
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
);
1250 nsresult rv
= filter_
->FilterPacket(&addr
, data
, len
,
1251 nsIUDPSocketFilter::SF_INCOMING
,
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
);
1263 nsresult rv
= filter_
->FilterPacket(&addr
, data
, len
,
1264 nsIUDPSocketFilter::SF_OUTGOING
,
1266 ASSERT_EQ(NS_OK
, rv
);
1267 ASSERT_EQ(expected_result
, result
);
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_
;
1283 TEST_F(IceGatherTest
, TestGatherFakeStunServerHostnameNoResolver
) {
1284 if (g_stun_server_hostname
.empty()) {
1289 peer_
->SetStunServer(g_stun_server_hostname
, kDefaultStunServerPort
);
1293 TEST_F(IceGatherTest
, TestGatherFakeStunServerIpAddress
) {
1294 if (g_stun_server_address
.empty()) {
1299 peer_
->SetStunServer(g_stun_server_address
, kDefaultStunServerPort
);
1300 peer_
->SetFakeResolver();
1304 TEST_F(IceGatherTest
, TestGatherFakeStunServerHostname
) {
1305 if (g_stun_server_hostname
.empty()) {
1310 peer_
->SetStunServer(g_stun_server_hostname
, kDefaultStunServerPort
);
1311 peer_
->SetFakeResolver();
1315 TEST_F(IceGatherTest
, TestGatherFakeStunBogusHostname
) {
1317 peer_
->SetStunServer(kBogusStunServerHostname
, kDefaultStunServerPort
);
1318 peer_
->SetFakeResolver();
1322 TEST_F(IceGatherTest
, TestGatherDNSStunServerIpAddress
) {
1323 if (g_stun_server_address
.empty()) {
1328 peer_
->SetStunServer(g_stun_server_address
, kDefaultStunServerPort
);
1329 peer_
->SetDNSResolver();
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()) {
1340 peer_
->SetStunServer(g_stun_server_hostname
, kDefaultStunServerPort
);
1341 peer_
->SetDNSResolver();
1345 TEST_F(IceGatherTest
, TestGatherDNSStunBogusHostname
) {
1347 peer_
->SetStunServer(kBogusStunServerHostname
, kDefaultStunServerPort
);
1348 peer_
->SetDNSResolver();
1352 TEST_F(IceGatherTest
, TestGatherTurn
) {
1354 if (g_turn_server
.empty())
1356 peer_
->SetTurnServer(g_turn_server
, kDefaultStunServerPort
,
1357 g_turn_user
, g_turn_password
, kNrIceTransportUdp
);
1361 TEST_F(IceGatherTest
, TestGatherTurnTcp
) {
1363 if (g_turn_server
.empty())
1365 peer_
->SetTurnServer(g_turn_server
, kDefaultStunServerPort
,
1366 g_turn_user
, g_turn_password
, kNrIceTransportTcp
);
1370 TEST_F(IceGatherTest
, TestGatherDisableComponent
) {
1371 if (g_stun_server_hostname
.empty()) {
1376 peer_
->SetStunServer(g_stun_server_hostname
, kDefaultStunServerPort
);
1377 peer_
->AddStream(2);
1378 peer_
->DisableComponent(1, 2);
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
) {
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);
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
) {
1406 peer_
->ParseCandidate(0, kBogusIceCandidate
);
1409 TEST_F(IceGatherTest
, VerifyTestStunServer
) {
1410 UseFakeStunServerWithResponse("192.0.2.133", 3333);
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);
1437 ASSERT_FALSE(StreamHasMatchingCandidate(0, "192.0.2.1"));
1438 TestStunServer::GetInstance()->SetActive(true);
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
) {
1450 AddStream("first", 1);
1451 ASSERT_TRUE(Gather());
1455 TEST_F(IceConnectTest
, TestConnect
) {
1456 AddStream("first", 1);
1457 ASSERT_TRUE(Gather());
1461 TEST_F(IceConnectTest
, TestLoopbackOnlySortOf
) {
1463 AddStream("first", 1);
1464 ASSERT_TRUE(Gather());
1465 SetCandidateFilter(IsLoopbackCandidate
);
1466 SetExpectedCandidateAddr("127.0.0.1");
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
);
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
);
1491 TEST_F(IceConnectTest
, TestConnectIceLiteOfferer
) {
1492 AddStream("first", 1);
1493 ASSERT_TRUE(Gather());
1494 p1_
->SimulateIceLite();
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
);
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
);
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();
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());
1543 TEST_F(IceConnectTest
, TestConnectTwoComponentsDisableSecond
) {
1544 AddStream("first", 2);
1545 ASSERT_TRUE(Gather());
1546 p1_
->DisableComponent(0, 2);
1547 p2_
->DisableComponent(0, 2);
1552 TEST_F(IceConnectTest
, TestConnectP2ThenP1
) {
1553 AddStream("first", 1);
1554 ASSERT_TRUE(Gather());
1561 TEST_F(IceConnectTest
, TestConnectP2ThenP1Trickle
) {
1562 AddStream("first", 1);
1563 ASSERT_TRUE(Gather());
1566 ConnectP1(TRICKLE_SIMULATE
);
1567 SimulateTrickleP1(0);
1571 TEST_F(IceConnectTest
, TestConnectP2ThenP1TrickleTwoComponents
) {
1572 AddStream("first", 1);
1573 AddStream("second", 2);
1574 ASSERT_TRUE(Gather());
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
1582 SimulateTrickleP1(1);
1586 TEST_F(IceConnectTest
, TestConnectAutoPrioritize
) {
1588 AddStream("first", 1);
1589 ASSERT_TRUE(Gather());
1593 TEST_F(IceConnectTest
, TestConnectTrickleOneStreamOneComponent
) {
1594 AddStream("first", 1);
1595 ASSERT_TRUE(Gather());
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());
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());
1633 TEST_F(IceConnectTest
, TestConnectTurn
) {
1634 if (g_turn_server
.empty())
1637 AddStream("first", 1);
1638 SetTurnServer(g_turn_server
, kDefaultStunServerPort
,
1639 g_turn_user
, g_turn_password
);
1640 ASSERT_TRUE(Gather());
1644 TEST_F(IceConnectTest
, TestConnectTurnWithDelay
) {
1645 if (g_turn_server
.empty())
1648 AddStream("first", 1);
1649 SetTurnServer(g_turn_server
, kDefaultStunServerPort
,
1650 g_turn_user
, g_turn_password
);
1651 SetCandidateFilter(SabotageHostCandidateAndDropReflexive
);
1655 ConnectTrickle(TRICKLE_REAL
);
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
,
1677 for (auto i
= candidates
.begin(); i
!= candidates
.end(); ++i
) {
1678 if ((*i
)->IsRelay()) {
1686 TEST_F(IceConnectTest
, TestConnectTurnWithNormalTrickleDelay
) {
1687 if (g_turn_server
.empty())
1690 AddStream("first", 1);
1691 SetTurnServer(g_turn_server
, kDefaultStunServerPort
,
1692 g_turn_user
, g_turn_password
);
1693 ASSERT_TRUE(Gather());
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())
1707 AddStream("first", 1);
1708 SetTurnServer(g_turn_server
, kDefaultStunServerPort
,
1709 g_turn_user
, g_turn_password
);
1710 ASSERT_TRUE(Gather());
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())
1724 AddStream("first", 1);
1725 SetTurnServer(g_turn_server
, kDefaultStunServerPort
,
1726 g_turn_user
, g_turn_password
);
1727 SetCandidateFilter(SabotageHostCandidateAndDropReflexive
);
1728 ASSERT_TRUE(Gather());
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())
1743 AddStream("first", 1);
1744 SetTurnServer(g_turn_server
, kDefaultStunServerPort
,
1745 g_turn_user
, g_turn_password
, kNrIceTransportTcp
);
1746 ASSERT_TRUE(Gather());
1750 TEST_F(IceConnectTest
, TestConnectTurnOnly
) {
1751 if (g_turn_server
.empty())
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
);
1764 TEST_F(IceConnectTest
, TestConnectTurnTcpOnly
) {
1765 if (g_turn_server
.empty())
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
);
1779 TEST_F(IceConnectTest
, TestSendReceiveTurnOnly
) {
1780 if (g_turn_server
.empty())
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
);
1794 TEST_F(IceConnectTest
, TestSendReceiveTurnTcpOnly
) {
1795 if (g_turn_server
.empty())
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
);
1810 TEST_F(IceConnectTest
, TestSendReceiveTurnBothOnly
) {
1811 if (g_turn_server
.empty())
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
);
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());
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
));
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
;
1890 p1_
->UpdateAndValidateCandidatePairs(0, &pairs1
);
1891 p2_
->UpdateAndValidateCandidatePairs(0, &pairs2
);
1894 p1_
->UpdateAndValidateCandidatePairs(0, &pairs1
);
1895 p2_
->UpdateAndValidateCandidatePairs(0, &pairs2
);
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
;
1915 p1_
->UpdateAndValidateCandidatePairs(0, &pairs1
);
1916 p2_
->UpdateAndValidateCandidatePairs(0, &pairs2
);
1919 p1_
->UpdateAndValidateCandidatePairs(0, &pairs1
);
1920 p2_
->UpdateAndValidateCandidatePairs(0, &pairs2
);
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
);
2096 int main(int argc
, char **argv
)
2099 // This test can cause intermittent oranges on the builders on Linux
2100 CHECK_ENVIRONMENT_FLAG("MOZ_WEBRTC_TESTS")
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()) {
2111 "Set TURN_SERVER_ADDRESS, TURN_SERVER_USER, and TURN_SERVER_PASSWORD\n"
2112 "environment variables to run this test\n");
2116 std::string tmp
= get_environment("STUN_SERVER_ADDRESS");
2118 g_stun_server_address
= tmp
;
2121 tmp
= get_environment("STUN_SERVER_HOSTNAME");
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
= "";
2136 test_utils
= new MtransportTestUtils();
2137 NSS_NoDB_Init(nullptr);
2138 NSS_SetDomesticPolicy();
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
);