1 /*
2 * Copyright 2009 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "p2p/base/stun_port.h"
12
13 #include <memory>
14
15 #include "api/test/mock_async_dns_resolver.h"
16 #include "p2p/base/basic_packet_socket_factory.h"
17 #include "p2p/base/mock_dns_resolving_packet_socket_factory.h"
18 #include "p2p/base/test_stun_server.h"
19 #include "rtc_base/gunit.h"
20 #include "rtc_base/helpers.h"
21 #include "rtc_base/socket_address.h"
22 #include "rtc_base/ssl_adapter.h"
23 #include "rtc_base/virtual_socket_server.h"
24 #include "test/gmock.h"
25 #include "test/scoped_key_value_config.h"
26
27 namespace {
28
29 using cricket::ServerAddresses;
30 using rtc::SocketAddress;
31 using ::testing::_;
32 using ::testing::DoAll;
33 using ::testing::InvokeArgument;
34 using ::testing::Return;
35 using ::testing::ReturnPointee;
36 using ::testing::SetArgPointee;
37
38 static const SocketAddress kLocalAddr("127.0.0.1", 0);
39 static const SocketAddress kIPv6LocalAddr("::1", 0);
40 static const SocketAddress kStunAddr1("127.0.0.1", 5000);
41 static const SocketAddress kStunAddr2("127.0.0.1", 4000);
42 static const SocketAddress kStunAddr3("127.0.0.1", 3000);
43 static const SocketAddress kIPv6StunAddr1("::1", 5000);
44 static const SocketAddress kBadAddr("0.0.0.1", 5000);
45 static const SocketAddress kValidHostnameAddr("valid-hostname", 5000);
46 static const SocketAddress kBadHostnameAddr("not-a-real-hostname", 5000);
47 // STUN timeout (with all retries) is cricket::STUN_TOTAL_TIMEOUT.
48 // Add some margin of error for slow bots.
49 static const int kTimeoutMs = cricket::STUN_TOTAL_TIMEOUT;
50 // stun prio = 100 (srflx) << 24 | 30 (IPv4) << 8 | 256 - 1 (component)
51 static const uint32_t kStunCandidatePriority =
52 (100 << 24) | (30 << 8) | (256 - 1);
53 // stun prio = 100 (srflx) << 24 | 60 (loopback IPv6) << 8 | 256 - 1 (component)
54 static const uint32_t kIPv6StunCandidatePriority =
55 (100 << 24) | (60 << 8) | (256 - 1);
56 static const int kInfiniteLifetime = -1;
57 static const int kHighCostPortKeepaliveLifetimeMs = 2 * 60 * 1000;
58
59 constexpr uint64_t kTiebreakerDefault = 44444;
60
61 class FakeMdnsResponder : public webrtc::MdnsResponderInterface {
62 public:
CreateNameForAddress(const rtc::IPAddress & addr,NameCreatedCallback callback)63 void CreateNameForAddress(const rtc::IPAddress& addr,
64 NameCreatedCallback callback) override {
65 callback(addr, std::string("unittest-mdns-host-name.local"));
66 }
67
RemoveNameForAddress(const rtc::IPAddress & addr,NameRemovedCallback callback)68 void RemoveNameForAddress(const rtc::IPAddress& addr,
69 NameRemovedCallback callback) override {}
70 };
71
72 class FakeMdnsResponderProvider : public rtc::MdnsResponderProvider {
73 public:
FakeMdnsResponderProvider()74 FakeMdnsResponderProvider() : mdns_responder_(new FakeMdnsResponder()) {}
75
GetMdnsResponder() const76 webrtc::MdnsResponderInterface* GetMdnsResponder() const override {
77 return mdns_responder_.get();
78 }
79
80 private:
81 std::unique_ptr<webrtc::MdnsResponderInterface> mdns_responder_;
82 };
83
84 // Base class for tests connecting a StunPort to a fake STUN server
85 // (cricket::StunServer).
86 class StunPortTestBase : public ::testing::Test, public sigslot::has_slots<> {
87 public:
StunPortTestBase()88 StunPortTestBase()
89 : StunPortTestBase(
90 rtc::Network("unittest", "unittest", kLocalAddr.ipaddr(), 32),
91 kLocalAddr.ipaddr()) {}
92
StunPortTestBase(rtc::Network network,const rtc::IPAddress address)93 StunPortTestBase(rtc::Network network, const rtc::IPAddress address)
94 : ss_(new rtc::VirtualSocketServer()),
95 thread_(ss_.get()),
96 network_(network),
97 socket_factory_(ss_.get()),
98 stun_server_1_(cricket::TestStunServer::Create(ss_.get(), kStunAddr1)),
99 stun_server_2_(cricket::TestStunServer::Create(ss_.get(), kStunAddr2)),
100 mdns_responder_provider_(new FakeMdnsResponderProvider()),
101 done_(false),
102 error_(false),
103 stun_keepalive_delay_(1),
104 stun_keepalive_lifetime_(-1) {
105 network_.AddIP(address);
106 }
107
socket_factory()108 virtual rtc::PacketSocketFactory* socket_factory() {
109 return &socket_factory_;
110 }
111
ss() const112 rtc::VirtualSocketServer* ss() const { return ss_.get(); }
port() const113 cricket::UDPPort* port() const { return stun_port_.get(); }
socket() const114 rtc::AsyncPacketSocket* socket() const { return socket_.get(); }
done() const115 bool done() const { return done_; }
error() const116 bool error() const { return error_; }
117
HasPendingRequest(int msg_type)118 bool HasPendingRequest(int msg_type) {
119 return stun_port_->request_manager().HasRequestForTest(msg_type);
120 }
121
SetNetworkType(rtc::AdapterType adapter_type)122 void SetNetworkType(rtc::AdapterType adapter_type) {
123 network_.set_type(adapter_type);
124 }
125
CreateStunPort(const rtc::SocketAddress & server_addr,const webrtc::FieldTrialsView * field_trials=nullptr)126 void CreateStunPort(const rtc::SocketAddress& server_addr,
127 const webrtc::FieldTrialsView* field_trials = nullptr) {
128 ServerAddresses stun_servers;
129 stun_servers.insert(server_addr);
130 CreateStunPort(stun_servers, field_trials);
131 }
132
CreateStunPort(const ServerAddresses & stun_servers,const webrtc::FieldTrialsView * field_trials=nullptr)133 void CreateStunPort(const ServerAddresses& stun_servers,
134 const webrtc::FieldTrialsView* field_trials = nullptr) {
135 stun_port_ = cricket::StunPort::Create(
136 rtc::Thread::Current(), socket_factory(), &network_, 0, 0,
137 rtc::CreateRandomString(16), rtc::CreateRandomString(22), stun_servers,
138 absl::nullopt, field_trials);
139 stun_port_->SetIceTiebreaker(kTiebreakerDefault);
140 stun_port_->set_stun_keepalive_delay(stun_keepalive_delay_);
141 // If `stun_keepalive_lifetime_` is negative, let the stun port
142 // choose its lifetime from the network type.
143 if (stun_keepalive_lifetime_ >= 0) {
144 stun_port_->set_stun_keepalive_lifetime(stun_keepalive_lifetime_);
145 }
146 stun_port_->SignalPortComplete.connect(this,
147 &StunPortTestBase::OnPortComplete);
148 stun_port_->SignalPortError.connect(this, &StunPortTestBase::OnPortError);
149 stun_port_->SignalCandidateError.connect(
150 this, &StunPortTestBase::OnCandidateError);
151 }
152
CreateSharedUdpPort(const rtc::SocketAddress & server_addr,rtc::AsyncPacketSocket * socket,const webrtc::FieldTrialsView * field_trials=nullptr)153 void CreateSharedUdpPort(
154 const rtc::SocketAddress& server_addr,
155 rtc::AsyncPacketSocket* socket,
156 const webrtc::FieldTrialsView* field_trials = nullptr) {
157 if (socket) {
158 socket_.reset(socket);
159 } else {
160 socket_.reset(socket_factory()->CreateUdpSocket(
161 rtc::SocketAddress(kLocalAddr.ipaddr(), 0), 0, 0));
162 }
163 ASSERT_TRUE(socket_ != NULL);
164 socket_->SignalReadPacket.connect(this, &StunPortTestBase::OnReadPacket);
165 stun_port_ = cricket::UDPPort::Create(
166 rtc::Thread::Current(), socket_factory(), &network_, socket_.get(),
167 rtc::CreateRandomString(16), rtc::CreateRandomString(22), false,
168 absl::nullopt, field_trials);
169 ASSERT_TRUE(stun_port_ != NULL);
170 stun_port_->SetIceTiebreaker(kTiebreakerDefault);
171 ServerAddresses stun_servers;
172 stun_servers.insert(server_addr);
173 stun_port_->set_server_addresses(stun_servers);
174 stun_port_->SignalPortComplete.connect(this,
175 &StunPortTestBase::OnPortComplete);
176 stun_port_->SignalPortError.connect(this, &StunPortTestBase::OnPortError);
177 }
178
PrepareAddress()179 void PrepareAddress() { stun_port_->PrepareAddress(); }
180
OnReadPacket(rtc::AsyncPacketSocket * socket,const char * data,size_t size,const rtc::SocketAddress & remote_addr,const int64_t &)181 void OnReadPacket(rtc::AsyncPacketSocket* socket,
182 const char* data,
183 size_t size,
184 const rtc::SocketAddress& remote_addr,
185 const int64_t& /* packet_time_us */) {
186 stun_port_->HandleIncomingPacket(socket, data, size, remote_addr,
187 /* packet_time_us */ -1);
188 }
189
SendData(const char * data,size_t len)190 void SendData(const char* data, size_t len) {
191 stun_port_->HandleIncomingPacket(socket_.get(), data, len,
192 rtc::SocketAddress("22.22.22.22", 0),
193 /* packet_time_us */ -1);
194 }
195
EnableMdnsObfuscation()196 void EnableMdnsObfuscation() {
197 network_.set_mdns_responder_provider(mdns_responder_provider_.get());
198 }
199
200 protected:
SetUpTestSuite()201 static void SetUpTestSuite() {
202 // Ensure the RNG is inited.
203 rtc::InitRandom(NULL, 0);
204 }
205
OnPortComplete(cricket::Port * port)206 void OnPortComplete(cricket::Port* port) {
207 ASSERT_FALSE(done_);
208 done_ = true;
209 error_ = false;
210 }
OnPortError(cricket::Port * port)211 void OnPortError(cricket::Port* port) {
212 done_ = true;
213 error_ = true;
214 }
OnCandidateError(cricket::Port * port,const cricket::IceCandidateErrorEvent & event)215 void OnCandidateError(cricket::Port* port,
216 const cricket::IceCandidateErrorEvent& event) {
217 error_event_ = event;
218 }
SetKeepaliveDelay(int delay)219 void SetKeepaliveDelay(int delay) { stun_keepalive_delay_ = delay; }
220
SetKeepaliveLifetime(int lifetime)221 void SetKeepaliveLifetime(int lifetime) {
222 stun_keepalive_lifetime_ = lifetime;
223 }
224
stun_server_1()225 cricket::TestStunServer* stun_server_1() { return stun_server_1_.get(); }
stun_server_2()226 cricket::TestStunServer* stun_server_2() { return stun_server_2_.get(); }
227
228 private:
229 std::unique_ptr<rtc::VirtualSocketServer> ss_;
230 rtc::AutoSocketServerThread thread_;
231 rtc::Network network_;
232 rtc::BasicPacketSocketFactory socket_factory_;
233 std::unique_ptr<cricket::UDPPort> stun_port_;
234 std::unique_ptr<cricket::TestStunServer> stun_server_1_;
235 std::unique_ptr<cricket::TestStunServer> stun_server_2_;
236 std::unique_ptr<rtc::AsyncPacketSocket> socket_;
237 std::unique_ptr<rtc::MdnsResponderProvider> mdns_responder_provider_;
238 bool done_;
239 bool error_;
240 int stun_keepalive_delay_;
241 int stun_keepalive_lifetime_;
242
243 protected:
244 cricket::IceCandidateErrorEvent error_event_;
245 };
246
247 class StunPortTestWithRealClock : public StunPortTestBase {};
248
249 class FakeClockBase {
250 public:
251 rtc::ScopedFakeClock fake_clock;
252 };
253
254 class StunPortTest : public FakeClockBase, public StunPortTestBase {};
255
256 // Test that we can create a STUN port.
TEST_F(StunPortTest,TestCreateStunPort)257 TEST_F(StunPortTest, TestCreateStunPort) {
258 CreateStunPort(kStunAddr1);
259 EXPECT_EQ("stun", port()->Type());
260 EXPECT_EQ(0U, port()->Candidates().size());
261 }
262
263 // Test that we can create a UDP port.
TEST_F(StunPortTest,TestCreateUdpPort)264 TEST_F(StunPortTest, TestCreateUdpPort) {
265 CreateSharedUdpPort(kStunAddr1, nullptr);
266 EXPECT_EQ("local", port()->Type());
267 EXPECT_EQ(0U, port()->Candidates().size());
268 }
269
270 // Test that we can get an address from a STUN server.
TEST_F(StunPortTest,TestPrepareAddress)271 TEST_F(StunPortTest, TestPrepareAddress) {
272 CreateStunPort(kStunAddr1);
273 PrepareAddress();
274 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
275 ASSERT_EQ(1U, port()->Candidates().size());
276 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
277 std::string expected_server_url = "stun:127.0.0.1:5000";
278 EXPECT_EQ(port()->Candidates()[0].url(), expected_server_url);
279 }
280
281 // Test that we fail properly if we can't get an address.
TEST_F(StunPortTest,TestPrepareAddressFail)282 TEST_F(StunPortTest, TestPrepareAddressFail) {
283 CreateStunPort(kBadAddr);
284 PrepareAddress();
285 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
286 EXPECT_TRUE(error());
287 EXPECT_EQ(0U, port()->Candidates().size());
288 EXPECT_EQ_SIMULATED_WAIT(error_event_.error_code,
289 cricket::SERVER_NOT_REACHABLE_ERROR, kTimeoutMs,
290 fake_clock);
291 ASSERT_NE(error_event_.error_text.find('.'), std::string::npos);
292 ASSERT_NE(error_event_.address.find(kLocalAddr.HostAsSensitiveURIString()),
293 std::string::npos);
294 std::string server_url = "stun:" + kBadAddr.ToString();
295 ASSERT_EQ(error_event_.url, server_url);
296 }
297
298 class StunPortWithMockDnsResolverTest : public StunPortTest {
299 public:
StunPortWithMockDnsResolverTest()300 StunPortWithMockDnsResolverTest() : StunPortTest(), socket_factory_(ss()) {}
301
socket_factory()302 rtc::PacketSocketFactory* socket_factory() override {
303 return &socket_factory_;
304 }
305
SetDnsResolverExpectations(rtc::MockDnsResolvingPacketSocketFactory::Expectations expectations)306 void SetDnsResolverExpectations(
307 rtc::MockDnsResolvingPacketSocketFactory::Expectations expectations) {
308 socket_factory_.SetExpectations(expectations);
309 }
310
311 private:
312 rtc::MockDnsResolvingPacketSocketFactory socket_factory_;
313 };
314
315 // Test that we can get an address from a STUN server specified by a hostname.
TEST_F(StunPortWithMockDnsResolverTest,TestPrepareAddressHostname)316 TEST_F(StunPortWithMockDnsResolverTest, TestPrepareAddressHostname) {
317 SetDnsResolverExpectations(
318 [](webrtc::MockAsyncDnsResolver* resolver,
319 webrtc::MockAsyncDnsResolverResult* resolver_result) {
320 EXPECT_CALL(*resolver, Start(kValidHostnameAddr, _))
321 .WillOnce(InvokeArgument<1>());
322 EXPECT_CALL(*resolver, result)
323 .WillRepeatedly(ReturnPointee(resolver_result));
324 EXPECT_CALL(*resolver_result, GetError).WillOnce(Return(0));
325 EXPECT_CALL(*resolver_result, GetResolvedAddress(AF_INET, _))
326 .WillOnce(DoAll(SetArgPointee<1>(SocketAddress("127.0.0.1", 5000)),
327 Return(true)));
328 });
329 CreateStunPort(kValidHostnameAddr);
330 PrepareAddress();
331 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
332 ASSERT_EQ(1U, port()->Candidates().size());
333 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
334 EXPECT_EQ(kStunCandidatePriority, port()->Candidates()[0].priority());
335 }
336
337 // Test that we handle hostname lookup failures properly.
TEST_F(StunPortTestWithRealClock,TestPrepareAddressHostnameFail)338 TEST_F(StunPortTestWithRealClock, TestPrepareAddressHostnameFail) {
339 CreateStunPort(kBadHostnameAddr);
340 PrepareAddress();
341 EXPECT_TRUE_WAIT(done(), kTimeoutMs);
342 EXPECT_TRUE(error());
343 EXPECT_EQ(0U, port()->Candidates().size());
344 EXPECT_EQ_WAIT(error_event_.error_code, cricket::SERVER_NOT_REACHABLE_ERROR,
345 kTimeoutMs);
346 }
347
348 // This test verifies keepalive response messages don't result in
349 // additional candidate generation.
TEST_F(StunPortTest,TestKeepAliveResponse)350 TEST_F(StunPortTest, TestKeepAliveResponse) {
351 SetKeepaliveDelay(500); // 500ms of keepalive delay.
352 CreateStunPort(kStunAddr1);
353 PrepareAddress();
354 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
355 ASSERT_EQ(1U, port()->Candidates().size());
356 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
357 SIMULATED_WAIT(false, 1000, fake_clock);
358 EXPECT_EQ(1U, port()->Candidates().size());
359 }
360
361 // Test that a local candidate can be generated using a shared socket.
TEST_F(StunPortTest,TestSharedSocketPrepareAddress)362 TEST_F(StunPortTest, TestSharedSocketPrepareAddress) {
363 CreateSharedUdpPort(kStunAddr1, nullptr);
364 PrepareAddress();
365 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
366 ASSERT_EQ(1U, port()->Candidates().size());
367 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
368 }
369
370 // Test that we still get a local candidate with invalid stun server hostname.
371 // Also verifing that UDPPort can receive packets when stun address can't be
372 // resolved.
TEST_F(StunPortTestWithRealClock,TestSharedSocketPrepareAddressInvalidHostname)373 TEST_F(StunPortTestWithRealClock,
374 TestSharedSocketPrepareAddressInvalidHostname) {
375 CreateSharedUdpPort(kBadHostnameAddr, nullptr);
376 PrepareAddress();
377 EXPECT_TRUE_WAIT(done(), kTimeoutMs);
378 ASSERT_EQ(1U, port()->Candidates().size());
379 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
380
381 // Send data to port after it's ready. This is to make sure, UDP port can
382 // handle data with unresolved stun server address.
383 std::string data = "some random data, sending to cricket::Port.";
384 SendData(data.c_str(), data.length());
385 // No crash is success.
386 }
387
388 // Test that a stun candidate (srflx candidate) is discarded whose address is
389 // equal to that of a local candidate if mDNS obfuscation is not enabled.
TEST_F(StunPortTest,TestStunCandidateDiscardedWithMdnsObfuscationNotEnabled)390 TEST_F(StunPortTest, TestStunCandidateDiscardedWithMdnsObfuscationNotEnabled) {
391 CreateSharedUdpPort(kStunAddr1, nullptr);
392 PrepareAddress();
393 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
394 ASSERT_EQ(1U, port()->Candidates().size());
395 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
396 EXPECT_EQ(port()->Candidates()[0].type(), cricket::LOCAL_PORT_TYPE);
397 }
398
399 // Test that a stun candidate (srflx candidate) is generated whose address is
400 // equal to that of a local candidate if mDNS obfuscation is enabled.
TEST_F(StunPortTest,TestStunCandidateGeneratedWithMdnsObfuscationEnabled)401 TEST_F(StunPortTest, TestStunCandidateGeneratedWithMdnsObfuscationEnabled) {
402 EnableMdnsObfuscation();
403 CreateSharedUdpPort(kStunAddr1, nullptr);
404 PrepareAddress();
405 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
406 ASSERT_EQ(2U, port()->Candidates().size());
407
408 // The addresses of the candidates are both equal to kLocalAddr.
409 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
410 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[1].address()));
411
412 // One of the generated candidates is a local candidate and the other is a
413 // stun candidate.
414 EXPECT_NE(port()->Candidates()[0].type(), port()->Candidates()[1].type());
415 if (port()->Candidates()[0].type() == cricket::LOCAL_PORT_TYPE) {
416 EXPECT_EQ(port()->Candidates()[1].type(), cricket::STUN_PORT_TYPE);
417 } else {
418 EXPECT_EQ(port()->Candidates()[0].type(), cricket::STUN_PORT_TYPE);
419 EXPECT_EQ(port()->Candidates()[1].type(), cricket::LOCAL_PORT_TYPE);
420 }
421 }
422
423 // Test that the same address is added only once if two STUN servers are in
424 // use.
TEST_F(StunPortTest,TestNoDuplicatedAddressWithTwoStunServers)425 TEST_F(StunPortTest, TestNoDuplicatedAddressWithTwoStunServers) {
426 ServerAddresses stun_servers;
427 stun_servers.insert(kStunAddr1);
428 stun_servers.insert(kStunAddr2);
429 CreateStunPort(stun_servers);
430 EXPECT_EQ("stun", port()->Type());
431 PrepareAddress();
432 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
433 EXPECT_EQ(1U, port()->Candidates().size());
434 EXPECT_EQ(port()->Candidates()[0].relay_protocol(), "");
435 }
436
437 // Test that candidates can be allocated for multiple STUN servers, one of
438 // which is not reachable.
TEST_F(StunPortTest,TestMultipleStunServersWithBadServer)439 TEST_F(StunPortTest, TestMultipleStunServersWithBadServer) {
440 ServerAddresses stun_servers;
441 stun_servers.insert(kStunAddr1);
442 stun_servers.insert(kBadAddr);
443 CreateStunPort(stun_servers);
444 EXPECT_EQ("stun", port()->Type());
445 PrepareAddress();
446 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
447 EXPECT_EQ(1U, port()->Candidates().size());
448 std::string server_url = "stun:" + kBadAddr.ToString();
449 ASSERT_EQ_SIMULATED_WAIT(error_event_.url, server_url, kTimeoutMs,
450 fake_clock);
451 }
452
453 // Test that two candidates are allocated if the two STUN servers return
454 // different mapped addresses.
TEST_F(StunPortTest,TestTwoCandidatesWithTwoStunServersAcrossNat)455 TEST_F(StunPortTest, TestTwoCandidatesWithTwoStunServersAcrossNat) {
456 const SocketAddress kStunMappedAddr1("77.77.77.77", 0);
457 const SocketAddress kStunMappedAddr2("88.77.77.77", 0);
458 stun_server_1()->set_fake_stun_addr(kStunMappedAddr1);
459 stun_server_2()->set_fake_stun_addr(kStunMappedAddr2);
460
461 ServerAddresses stun_servers;
462 stun_servers.insert(kStunAddr1);
463 stun_servers.insert(kStunAddr2);
464 CreateStunPort(stun_servers);
465 EXPECT_EQ("stun", port()->Type());
466 PrepareAddress();
467 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
468 EXPECT_EQ(2U, port()->Candidates().size());
469 EXPECT_EQ(port()->Candidates()[0].relay_protocol(), "");
470 EXPECT_EQ(port()->Candidates()[1].relay_protocol(), "");
471 }
472
473 // Test that the stun_keepalive_lifetime is set correctly based on the network
474 // type on a STUN port. Also test that it will be updated if the network type
475 // changes.
TEST_F(StunPortTest,TestStunPortGetStunKeepaliveLifetime)476 TEST_F(StunPortTest, TestStunPortGetStunKeepaliveLifetime) {
477 // Lifetime for the default (unknown) network type is `kInfiniteLifetime`.
478 CreateStunPort(kStunAddr1);
479 EXPECT_EQ(kInfiniteLifetime, port()->stun_keepalive_lifetime());
480 // Lifetime for the cellular network is `kHighCostPortKeepaliveLifetimeMs`
481 SetNetworkType(rtc::ADAPTER_TYPE_CELLULAR);
482 EXPECT_EQ(kHighCostPortKeepaliveLifetimeMs,
483 port()->stun_keepalive_lifetime());
484
485 // Lifetime for the wifi network is `kInfiniteLifetime`.
486 SetNetworkType(rtc::ADAPTER_TYPE_WIFI);
487 CreateStunPort(kStunAddr2);
488 EXPECT_EQ(kInfiniteLifetime, port()->stun_keepalive_lifetime());
489 }
490
491 // Test that the stun_keepalive_lifetime is set correctly based on the network
492 // type on a shared STUN port (UDPPort). Also test that it will be updated
493 // if the network type changes.
TEST_F(StunPortTest,TestUdpPortGetStunKeepaliveLifetime)494 TEST_F(StunPortTest, TestUdpPortGetStunKeepaliveLifetime) {
495 // Lifetime for the default (unknown) network type is `kInfiniteLifetime`.
496 CreateSharedUdpPort(kStunAddr1, nullptr);
497 EXPECT_EQ(kInfiniteLifetime, port()->stun_keepalive_lifetime());
498 // Lifetime for the cellular network is `kHighCostPortKeepaliveLifetimeMs`.
499 SetNetworkType(rtc::ADAPTER_TYPE_CELLULAR);
500 EXPECT_EQ(kHighCostPortKeepaliveLifetimeMs,
501 port()->stun_keepalive_lifetime());
502
503 // Lifetime for the wifi network type is `kInfiniteLifetime`.
504 SetNetworkType(rtc::ADAPTER_TYPE_WIFI);
505 CreateSharedUdpPort(kStunAddr2, nullptr);
506 EXPECT_EQ(kInfiniteLifetime, port()->stun_keepalive_lifetime());
507 }
508
509 // Test that STUN binding requests will be stopped shortly if the keep-alive
510 // lifetime is short.
TEST_F(StunPortTest,TestStunBindingRequestShortLifetime)511 TEST_F(StunPortTest, TestStunBindingRequestShortLifetime) {
512 SetKeepaliveDelay(101);
513 SetKeepaliveLifetime(100);
514 CreateStunPort(kStunAddr1);
515 PrepareAddress();
516 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
517 EXPECT_TRUE_SIMULATED_WAIT(!HasPendingRequest(cricket::STUN_BINDING_REQUEST),
518 2000, fake_clock);
519 }
520
521 // Test that by default, the STUN binding requests will last for a long time.
TEST_F(StunPortTest,TestStunBindingRequestLongLifetime)522 TEST_F(StunPortTest, TestStunBindingRequestLongLifetime) {
523 SetKeepaliveDelay(101);
524 CreateStunPort(kStunAddr1);
525 PrepareAddress();
526 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
527 EXPECT_TRUE_SIMULATED_WAIT(HasPendingRequest(cricket::STUN_BINDING_REQUEST),
528 1000, fake_clock);
529 }
530
531 class MockAsyncPacketSocket : public rtc::AsyncPacketSocket {
532 public:
533 ~MockAsyncPacketSocket() = default;
534
535 MOCK_METHOD(SocketAddress, GetLocalAddress, (), (const, override));
536 MOCK_METHOD(SocketAddress, GetRemoteAddress, (), (const, override));
537 MOCK_METHOD(int,
538 Send,
539 (const void* pv, size_t cb, const rtc::PacketOptions& options),
540 (override));
541
542 MOCK_METHOD(int,
543 SendTo,
544 (const void* pv,
545 size_t cb,
546 const SocketAddress& addr,
547 const rtc::PacketOptions& options),
548 (override));
549 MOCK_METHOD(int, Close, (), (override));
550 MOCK_METHOD(State, GetState, (), (const, override));
551 MOCK_METHOD(int,
552 GetOption,
553 (rtc::Socket::Option opt, int* value),
554 (override));
555 MOCK_METHOD(int, SetOption, (rtc::Socket::Option opt, int value), (override));
556 MOCK_METHOD(int, GetError, (), (const, override));
557 MOCK_METHOD(void, SetError, (int error), (override));
558 };
559
560 // Test that outbound packets inherit the dscp value assigned to the socket.
TEST_F(StunPortTest,TestStunPacketsHaveDscpPacketOption)561 TEST_F(StunPortTest, TestStunPacketsHaveDscpPacketOption) {
562 MockAsyncPacketSocket* socket = new MockAsyncPacketSocket();
563 CreateSharedUdpPort(kStunAddr1, socket);
564 EXPECT_CALL(*socket, GetLocalAddress()).WillRepeatedly(Return(kLocalAddr));
565 EXPECT_CALL(*socket, GetState())
566 .WillRepeatedly(Return(rtc::AsyncPacketSocket::STATE_BOUND));
567 EXPECT_CALL(*socket, SetOption(_, _)).WillRepeatedly(Return(0));
568
569 // If DSCP is not set on the socket, stun packets should have no value.
570 EXPECT_CALL(*socket,
571 SendTo(_, _, _,
572 ::testing::Field(&rtc::PacketOptions::dscp,
573 ::testing::Eq(rtc::DSCP_NO_CHANGE))))
574 .WillOnce(Return(100));
575 PrepareAddress();
576
577 // Once it is set transport wide, they should inherit that value.
578 port()->SetOption(rtc::Socket::OPT_DSCP, rtc::DSCP_AF41);
579 EXPECT_CALL(*socket, SendTo(_, _, _,
580 ::testing::Field(&rtc::PacketOptions::dscp,
581 ::testing::Eq(rtc::DSCP_AF41))))
582 .WillRepeatedly(Return(100));
583 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
584 }
585
586 class StunIPv6PortTestBase : public StunPortTestBase {
587 public:
StunIPv6PortTestBase()588 StunIPv6PortTestBase()
589 : StunPortTestBase(rtc::Network("unittestipv6",
590 "unittestipv6",
591 kIPv6LocalAddr.ipaddr(),
592 128),
593 kIPv6LocalAddr.ipaddr()) {
594 stun_server_ipv6_1_.reset(
595 cricket::TestStunServer::Create(ss(), kIPv6StunAddr1));
596 }
597
598 protected:
599 std::unique_ptr<cricket::TestStunServer> stun_server_ipv6_1_;
600 };
601
602 class StunIPv6PortTestWithRealClock : public StunIPv6PortTestBase {};
603
604 class StunIPv6PortTest : public FakeClockBase, public StunIPv6PortTestBase {};
605
606 // Test that we can get an address from a STUN server.
TEST_F(StunIPv6PortTest,TestPrepareAddress)607 TEST_F(StunIPv6PortTest, TestPrepareAddress) {
608 CreateStunPort(kIPv6StunAddr1);
609 PrepareAddress();
610 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
611 ASSERT_EQ(1U, port()->Candidates().size());
612 EXPECT_TRUE(kIPv6LocalAddr.EqualIPs(port()->Candidates()[0].address()));
613 std::string expected_server_url = "stun:::1:5000";
614 EXPECT_EQ(port()->Candidates()[0].url(), expected_server_url);
615 }
616
617 // Test that we fail properly if we can't get an address.
TEST_F(StunIPv6PortTest,TestPrepareAddressFail)618 TEST_F(StunIPv6PortTest, TestPrepareAddressFail) {
619 CreateStunPort(kBadAddr);
620 PrepareAddress();
621 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
622 EXPECT_TRUE(error());
623 EXPECT_EQ(0U, port()->Candidates().size());
624 EXPECT_EQ_SIMULATED_WAIT(error_event_.error_code,
625 cricket::SERVER_NOT_REACHABLE_ERROR, kTimeoutMs,
626 fake_clock);
627 ASSERT_NE(error_event_.error_text.find('.'), std::string::npos);
628 ASSERT_NE(
629 error_event_.address.find(kIPv6LocalAddr.HostAsSensitiveURIString()),
630 std::string::npos);
631 std::string server_url = "stun:" + kBadAddr.ToString();
632 ASSERT_EQ(error_event_.url, server_url);
633 }
634
635 // Test that we handle hostname lookup failures properly with a real clock.
TEST_F(StunIPv6PortTestWithRealClock,TestPrepareAddressHostnameFail)636 TEST_F(StunIPv6PortTestWithRealClock, TestPrepareAddressHostnameFail) {
637 CreateStunPort(kBadHostnameAddr);
638 PrepareAddress();
639 EXPECT_TRUE_WAIT(done(), kTimeoutMs);
640 EXPECT_TRUE(error());
641 EXPECT_EQ(0U, port()->Candidates().size());
642 EXPECT_EQ_WAIT(error_event_.error_code, cricket::SERVER_NOT_REACHABLE_ERROR,
643 kTimeoutMs);
644 }
645
646 class StunIPv6PortTestWithMockDnsResolver : public StunIPv6PortTest {
647 public:
StunIPv6PortTestWithMockDnsResolver()648 StunIPv6PortTestWithMockDnsResolver()
649 : StunIPv6PortTest(), socket_factory_(ss()) {}
650
socket_factory()651 rtc::PacketSocketFactory* socket_factory() override {
652 return &socket_factory_;
653 }
654
SetDnsResolverExpectations(rtc::MockDnsResolvingPacketSocketFactory::Expectations expectations)655 void SetDnsResolverExpectations(
656 rtc::MockDnsResolvingPacketSocketFactory::Expectations expectations) {
657 socket_factory_.SetExpectations(expectations);
658 }
659
660 private:
661 rtc::MockDnsResolvingPacketSocketFactory socket_factory_;
662 };
663
664 // Test that we can get an address from a STUN server specified by a hostname.
TEST_F(StunIPv6PortTestWithMockDnsResolver,TestPrepareAddressHostname)665 TEST_F(StunIPv6PortTestWithMockDnsResolver, TestPrepareAddressHostname) {
666 SetDnsResolverExpectations(
667 [](webrtc::MockAsyncDnsResolver* resolver,
668 webrtc::MockAsyncDnsResolverResult* resolver_result) {
669 // Expect to call Resolver::Start without family arg.
670 EXPECT_CALL(*resolver, Start(kValidHostnameAddr, _))
671 .WillOnce(InvokeArgument<1>());
672 EXPECT_CALL(*resolver, result)
673 .WillRepeatedly(ReturnPointee(resolver_result));
674 EXPECT_CALL(*resolver_result, GetError).WillOnce(Return(0));
675 EXPECT_CALL(*resolver_result, GetResolvedAddress(AF_INET6, _))
676 .WillOnce(DoAll(SetArgPointee<1>(SocketAddress("::1", 5000)),
677 Return(true)));
678 });
679 CreateStunPort(kValidHostnameAddr);
680 PrepareAddress();
681 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
682 ASSERT_EQ(1U, port()->Candidates().size());
683 EXPECT_TRUE(kIPv6LocalAddr.EqualIPs(port()->Candidates()[0].address()));
684 EXPECT_EQ(kIPv6StunCandidatePriority, port()->Candidates()[0].priority());
685 }
686
TEST_F(StunIPv6PortTestWithMockDnsResolver,TestPrepareAddressHostnameFamilyFieldTrialDisabled)687 TEST_F(StunIPv6PortTestWithMockDnsResolver,
688 TestPrepareAddressHostnameFamilyFieldTrialDisabled) {
689 webrtc::test::ScopedKeyValueConfig field_trials(
690 "WebRTC-IPv6NetworkResolutionFixes/Disabled/");
691 SetDnsResolverExpectations(
692 [](webrtc::MockAsyncDnsResolver* resolver,
693 webrtc::MockAsyncDnsResolverResult* resolver_result) {
694 // Expect to call Resolver::Start without family arg.
695 EXPECT_CALL(*resolver, Start(kValidHostnameAddr, _))
696 .WillOnce(InvokeArgument<1>());
697 EXPECT_CALL(*resolver, result)
698 .WillRepeatedly(ReturnPointee(resolver_result));
699 EXPECT_CALL(*resolver_result, GetError).WillOnce(Return(0));
700 EXPECT_CALL(*resolver_result, GetResolvedAddress(AF_INET6, _))
701 .WillOnce(DoAll(SetArgPointee<1>(SocketAddress("::1", 5000)),
702 Return(true)));
703 });
704 CreateStunPort(kValidHostnameAddr, &field_trials);
705 PrepareAddress();
706 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
707 ASSERT_EQ(1U, port()->Candidates().size());
708 EXPECT_TRUE(kIPv6LocalAddr.EqualIPs(port()->Candidates()[0].address()));
709 EXPECT_EQ(kIPv6StunCandidatePriority, port()->Candidates()[0].priority());
710 }
711
TEST_F(StunIPv6PortTestWithMockDnsResolver,TestPrepareAddressHostnameFamilyFieldTrialParamDisabled)712 TEST_F(StunIPv6PortTestWithMockDnsResolver,
713 TestPrepareAddressHostnameFamilyFieldTrialParamDisabled) {
714 webrtc::test::ScopedKeyValueConfig field_trials(
715 "WebRTC-IPv6NetworkResolutionFixes/"
716 "Enabled,ResolveStunHostnameForFamily:false/");
717 SetDnsResolverExpectations(
718 [](webrtc::MockAsyncDnsResolver* resolver,
719 webrtc::MockAsyncDnsResolverResult* resolver_result) {
720 // Expect to call Resolver::Start without family arg.
721 EXPECT_CALL(*resolver, Start(kValidHostnameAddr, _))
722 .WillOnce(InvokeArgument<1>());
723 EXPECT_CALL(*resolver, result)
724 .WillRepeatedly(ReturnPointee(resolver_result));
725 EXPECT_CALL(*resolver_result, GetError).WillOnce(Return(0));
726 EXPECT_CALL(*resolver_result, GetResolvedAddress(AF_INET6, _))
727 .WillOnce(DoAll(SetArgPointee<1>(SocketAddress("::1", 5000)),
728 Return(true)));
729 });
730 CreateStunPort(kValidHostnameAddr, &field_trials);
731 PrepareAddress();
732 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
733 ASSERT_EQ(1U, port()->Candidates().size());
734 EXPECT_TRUE(kIPv6LocalAddr.EqualIPs(port()->Candidates()[0].address()));
735 EXPECT_EQ(kIPv6StunCandidatePriority, port()->Candidates()[0].priority());
736 }
737
TEST_F(StunIPv6PortTestWithMockDnsResolver,TestPrepareAddressHostnameFamilyFieldTrialEnabled)738 TEST_F(StunIPv6PortTestWithMockDnsResolver,
739 TestPrepareAddressHostnameFamilyFieldTrialEnabled) {
740 webrtc::test::ScopedKeyValueConfig field_trials(
741 "WebRTC-IPv6NetworkResolutionFixes/"
742 "Enabled,ResolveStunHostnameForFamily:true/");
743 SetDnsResolverExpectations(
744 [](webrtc::MockAsyncDnsResolver* resolver,
745 webrtc::MockAsyncDnsResolverResult* resolver_result) {
746 // Expect to call Resolver::Start _with_ family arg.
747 EXPECT_CALL(*resolver,
748 Start(kValidHostnameAddr, /*family=*/AF_INET6, _))
749 .WillOnce(InvokeArgument<2>());
750 EXPECT_CALL(*resolver, result)
751 .WillRepeatedly(ReturnPointee(resolver_result));
752 EXPECT_CALL(*resolver_result, GetError).WillOnce(Return(0));
753 EXPECT_CALL(*resolver_result, GetResolvedAddress(AF_INET6, _))
754 .WillOnce(DoAll(SetArgPointee<1>(SocketAddress("::1", 5000)),
755 Return(true)));
756 });
757 CreateStunPort(kValidHostnameAddr, &field_trials);
758 PrepareAddress();
759 EXPECT_TRUE_SIMULATED_WAIT(done(), kTimeoutMs, fake_clock);
760 ASSERT_EQ(1U, port()->Candidates().size());
761 EXPECT_TRUE(kIPv6LocalAddr.EqualIPs(port()->Candidates()[0].address()));
762 EXPECT_EQ(kIPv6StunCandidatePriority, port()->Candidates()[0].priority());
763 }
764
765 } // namespace
766