xref: /aosp_15_r20/external/webrtc/p2p/base/stun_port_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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