diff options
author | Sameer Vijaykar <samvi@google.com> | 2022-12-02 17:07:07 +0100 |
---|---|---|
committer | WebRTC LUCI CQ <webrtc-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-12-05 13:34:57 +0000 |
commit | def85594ea34dec2c1cd8fd58835430c224899c7 (patch) | |
tree | 7efef7ec6b8f7d088d8c993f878ae562a3e9d8b4 | |
parent | a422e93d7b1d05b13dc3d1f1bc95e49785e9c55d (diff) | |
download | webrtc-def85594ea34dec2c1cd8fd58835430c224899c7.tar.gz |
Resolve TURN hostname specific to network family behind field trial.
Already implemented for STUN hostname resolution, but TURN port resolves hostnames separately. Reusing the field trial key reserved in bugs.webrtc.org/14334 but with a new parameter so as to not affect ongoing rollouts.
Bug: webrtc:14319, webrtc:14131
Change-Id: Idf771fb2f0de7849f8b701be8ee05a98b8d242f3
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/285981
Reviewed-by: Jonas Oreland <jonaso@webrtc.org>
Commit-Queue: Sameer Vijaykar <samvi@google.com>
Cr-Commit-Position: refs/heads/main@{#38811}
-rw-r--r-- | p2p/BUILD.gn | 2 | ||||
-rw-r--r-- | p2p/base/mock_dns_resolving_packet_socket_factory.h | 53 | ||||
-rw-r--r-- | p2p/base/stun_port_unittest.cc | 43 | ||||
-rw-r--r-- | p2p/base/turn_port.cc | 31 | ||||
-rw-r--r-- | p2p/base/turn_port_unittest.cc | 228 |
5 files changed, 274 insertions, 83 deletions
diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn index d46955f659..ee18dd5c77 100644 --- a/p2p/BUILD.gn +++ b/p2p/BUILD.gn @@ -205,6 +205,7 @@ if (rtc_include_tests) { "base/fake_packet_transport.h", "base/mock_active_ice_controller.h", "base/mock_async_resolver.h", + "base/mock_dns_resolving_packet_socket_factory.h", "base/mock_ice_agent.h", "base/mock_ice_controller.h", "base/mock_ice_transport.h", @@ -220,6 +221,7 @@ if (rtc_include_tests) { ":rtc_p2p", "../api:dtls_transport_interface", "../api:libjingle_peerconnection_api", + "../api:mock_async_dns_resolver", "../api:packet_socket_factory", "../api:sequence_checker", "../api:turn_customizer", diff --git a/p2p/base/mock_dns_resolving_packet_socket_factory.h b/p2p/base/mock_dns_resolving_packet_socket_factory.h new file mode 100644 index 0000000000..8f18e9b0e1 --- /dev/null +++ b/p2p/base/mock_dns_resolving_packet_socket_factory.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef P2P_BASE_MOCK_DNS_RESOLVING_PACKET_SOCKET_FACTORY_H_ +#define P2P_BASE_MOCK_DNS_RESOLVING_PACKET_SOCKET_FACTORY_H_ + +#include <functional> +#include <memory> + +#include "api/test/mock_async_dns_resolver.h" +#include "p2p/base/basic_packet_socket_factory.h" + +namespace rtc { + +// A PacketSocketFactory implementation for tests that uses a mock DnsResolver +// and allows setting expectations on the resolver and results. +class MockDnsResolvingPacketSocketFactory : public BasicPacketSocketFactory { + public: + using Expectations = std::function<void(webrtc::MockAsyncDnsResolver*, + webrtc::MockAsyncDnsResolverResult*)>; + + explicit MockDnsResolvingPacketSocketFactory(SocketFactory* socket_factory) + : BasicPacketSocketFactory(socket_factory) {} + + std::unique_ptr<webrtc::AsyncDnsResolverInterface> CreateAsyncDnsResolver() + override { + std::unique_ptr<webrtc::MockAsyncDnsResolver> resolver = + std::make_unique<webrtc::MockAsyncDnsResolver>(); + if (expectations_) { + expectations_(resolver.get(), &resolver_result_); + } + return resolver; + } + + void SetExpectations(Expectations expectations) { + expectations_ = expectations; + } + + private: + webrtc::MockAsyncDnsResolverResult resolver_result_; + Expectations expectations_; +}; + +} // namespace rtc + +#endif // P2P_BASE_MOCK_DNS_RESOLVING_PACKET_SOCKET_FACTORY_H_ diff --git a/p2p/base/stun_port_unittest.cc b/p2p/base/stun_port_unittest.cc index 59841adeef..3d56636a9b 100644 --- a/p2p/base/stun_port_unittest.cc +++ b/p2p/base/stun_port_unittest.cc @@ -14,6 +14,7 @@ #include "api/test/mock_async_dns_resolver.h" #include "p2p/base/basic_packet_socket_factory.h" +#include "p2p/base/mock_dns_resolving_packet_socket_factory.h" #include "p2p/base/test_stun_server.h" #include "rtc_base/gunit.h" #include "rtc_base/helpers.h" @@ -34,10 +35,6 @@ using ::testing::Return; using ::testing::ReturnPointee; using ::testing::SetArgPointee; -using DnsResolverExpectations = - std::function<void(webrtc::MockAsyncDnsResolver*, - webrtc::MockAsyncDnsResolverResult*)>; - static const SocketAddress kLocalAddr("127.0.0.1", 0); static const SocketAddress kIPv6LocalAddr("::1", 0); static const SocketAddress kStunAddr1("127.0.0.1", 5000); @@ -61,34 +58,6 @@ static const int kHighCostPortKeepaliveLifetimeMs = 2 * 60 * 1000; constexpr uint64_t kTiebreakerDefault = 44444; -// A PacketSocketFactory implementation that uses a mock DnsResolver and allows -// setting expectations on the resolver and results. -class MockDnsResolverPacketSocketFactory - : public rtc::BasicPacketSocketFactory { - public: - explicit MockDnsResolverPacketSocketFactory( - rtc::SocketFactory* socket_factory) - : rtc::BasicPacketSocketFactory(socket_factory) {} - - std::unique_ptr<webrtc::AsyncDnsResolverInterface> CreateAsyncDnsResolver() - override { - std::unique_ptr<webrtc::MockAsyncDnsResolver> resolver = - std::make_unique<webrtc::MockAsyncDnsResolver>(); - if (expectations_) { - expectations_(resolver.get(), &resolver_result_); - } - return resolver; - } - - void SetExpectations(DnsResolverExpectations expectations) { - expectations_ = expectations; - } - - private: - webrtc::MockAsyncDnsResolverResult resolver_result_; - DnsResolverExpectations expectations_; -}; - class FakeMdnsResponder : public webrtc::MdnsResponderInterface { public: void CreateNameForAddress(const rtc::IPAddress& addr, @@ -334,12 +303,13 @@ class StunPortWithMockDnsResolverTest : public StunPortTest { return &socket_factory_; } - void SetDnsResolverExpectations(DnsResolverExpectations expectations) { + void SetDnsResolverExpectations( + rtc::MockDnsResolvingPacketSocketFactory::Expectations expectations) { socket_factory_.SetExpectations(expectations); } private: - MockDnsResolverPacketSocketFactory socket_factory_; + rtc::MockDnsResolvingPacketSocketFactory socket_factory_; }; // Test that we can get an address from a STUN server specified by a hostname. @@ -682,12 +652,13 @@ class StunIPv6PortTestWithMockDnsResolver : public StunIPv6PortTest { return &socket_factory_; } - void SetDnsResolverExpectations(DnsResolverExpectations expectations) { + void SetDnsResolverExpectations( + rtc::MockDnsResolvingPacketSocketFactory::Expectations expectations) { socket_factory_.SetExpectations(expectations); } private: - MockDnsResolverPacketSocketFactory socket_factory_; + rtc::MockDnsResolvingPacketSocketFactory socket_factory_; }; // Test that we can get an address from a STUN server specified by a hostname. diff --git a/p2p/base/turn_port.cc b/p2p/base/turn_port.cc index 970d6adec6..3879ceb63a 100644 --- a/p2p/base/turn_port.cc +++ b/p2p/base/turn_port.cc @@ -26,6 +26,7 @@ #include "rtc_base/async_packet_socket.h" #include "rtc_base/byte_order.h" #include "rtc_base/checks.h" +#include "rtc_base/experiments/field_trial_parser.h" #include "rtc_base/logging.h" #include "rtc_base/net_helpers.h" #include "rtc_base/socket_address.h" @@ -33,6 +34,26 @@ namespace cricket { +namespace { + +bool ResolveTurnHostnameForFamily(const webrtc::FieldTrialsView& field_trials) { + // Bug fix for TURN hostname resolution on IPv6. + // Field trial key reserved in bugs.webrtc.org/14334 + static constexpr char field_trial_name[] = + "WebRTC-IPv6NetworkResolutionFixes"; + if (!field_trials.IsEnabled(field_trial_name)) { + return false; + } + + webrtc::FieldTrialParameter<bool> resolve_turn_hostname_for_family( + "ResolveTurnHostnameForFamily", /*default_value=*/false); + webrtc::ParseFieldTrial({&resolve_turn_hostname_for_family}, + field_trials.Lookup(field_trial_name)); + return resolve_turn_hostname_for_family; +} + +} // namespace + using ::webrtc::SafeTask; using ::webrtc::TaskQueueBase; using ::webrtc::TimeDelta; @@ -798,7 +819,7 @@ void TurnPort::ResolveTurnAddress(const rtc::SocketAddress& address) { RTC_LOG(LS_INFO) << ToString() << ": Starting TURN host lookup for " << address.ToSensitiveString(); resolver_ = socket_factory()->CreateAsyncDnsResolver(); - resolver_->Start(address, [this] { + auto callback = [this] { // If DNS resolve is failed when trying to connect to the server using TCP, // one of the reason could be due to DNS queries blocked by firewall. // In such cases we will try to connect to the server with hostname, @@ -829,7 +850,13 @@ void TurnPort::ResolveTurnAddress(const rtc::SocketAddress& address) { } server_address_.address = resolved_address; PrepareAddress(); - }); + }; + // TODO(bugs.webrtc.org/14733): remove duplicate resolution with STUN port. + if (ResolveTurnHostnameForFamily(field_trials())) { + resolver_->Start(address, Network()->family(), std::move(callback)); + } else { + resolver_->Start(address, std::move(callback)); + } } void TurnPort::OnSendStunPacket(const void* data, diff --git a/p2p/base/turn_port_unittest.cc b/p2p/base/turn_port_unittest.cc index 1d51c08f20..3f01fbef1b 100644 --- a/p2p/base/turn_port_unittest.cc +++ b/p2p/base/turn_port_unittest.cc @@ -22,6 +22,7 @@ #include "api/units/time_delta.h" #include "p2p/base/basic_packet_socket_factory.h" #include "p2p/base/connection.h" +#include "p2p/base/mock_dns_resolving_packet_socket_factory.h" #include "p2p/base/p2p_constants.h" #include "p2p/base/port_allocator.h" #include "p2p/base/stun_port.h" @@ -44,8 +45,16 @@ #include "test/gtest.h" #include "test/scoped_key_value_config.h" +namespace { using rtc::SocketAddress; +using ::testing::_; +using ::testing::DoAll; +using ::testing::InvokeArgument; +using ::testing::Return; +using ::testing::ReturnPointee; +using ::testing::SetArgPointee; + static const SocketAddress kLocalAddr1("11.11.11.11", 0); static const SocketAddress kLocalAddr2("22.22.22.22", 0); static const SocketAddress kLocalIPv6Addr("2401:fa00:4:1000:be30:5bff:fee5:c3", @@ -77,6 +86,7 @@ static const SocketAddress kTurnUdpIPv6IntAddr( "2400:4030:1:2c00:be30:abcd:efab:cdef", cricket::TURN_SERVER_PORT); static const SocketAddress kTurnInvalidAddr("www.google.invalid.", 3478); +static const SocketAddress kTurnValidAddr("www.google.valid.", 3478); static const char kCandidateFoundation[] = "foundation"; static const char kIceUfrag1[] = "TESTICEUFRAG0001"; @@ -114,9 +124,12 @@ static const cricket::ProtocolAddress kTurnPort80ProtoAddr(kTurnPort80Addr, cricket::PROTO_TCP); static const cricket::ProtocolAddress kTurnPort443ProtoAddr(kTurnPort443Addr, cricket::PROTO_TCP); -static const cricket::ProtocolAddress kTurnPortHostnameProtoAddr( +static const cricket::ProtocolAddress kTurnPortInvalidHostnameProtoAddr( kTurnInvalidAddr, cricket::PROTO_UDP); +static const cricket::ProtocolAddress kTurnPortValidHostnameProtoAddr( + kTurnValidAddr, + cricket::PROTO_UDP); #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) static int GetFDCount() { @@ -133,6 +146,8 @@ static int GetFDCount() { } #endif +} // unnamed namespace + namespace cricket { class TurnPortTestVirtualSocketServer : public rtc::VirtualSocketServer { @@ -180,8 +195,8 @@ class TurnPortTest : public ::testing::Test, TurnPortTest() : ss_(new TurnPortTestVirtualSocketServer()), main_(ss_.get()), - socket_factory_(ss_.get()), - turn_server_(&main_, ss_.get(), kTurnUdpIntAddr, kTurnUdpExtAddr) { + turn_server_(&main_, ss_.get(), kTurnUdpIntAddr, kTurnUdpExtAddr), + socket_factory_(ss_.get()) { // Some code uses "last received time == 0" to represent "nothing received // so far", so we need to start the fake clock at a nonzero time... // TODO(deadbeef): Fix this. @@ -280,7 +295,7 @@ class TurnPortTest : public ::testing::Test, config.credentials = RelayCredentials(username, password); CreateRelayPortArgs args; args.network_thread = &main_; - args.socket_factory = &socket_factory_; + args.socket_factory = socket_factory(); args.network = network; args.username = kIceUfrag1; args.password = kIcePwd1; @@ -314,7 +329,7 @@ class TurnPortTest : public ::testing::Test, RTC_CHECK(server_address.proto == PROTO_UDP); if (!socket_) { - socket_.reset(socket_factory_.CreateUdpSocket( + socket_.reset(socket_factory()->CreateUdpSocket( rtc::SocketAddress(kLocalAddr1.ipaddr(), 0), 0, 0)); ASSERT_TRUE(socket_ != NULL); socket_->SignalReadPacket.connect(this, @@ -325,7 +340,7 @@ class TurnPortTest : public ::testing::Test, config.credentials = RelayCredentials(username, password); CreateRelayPortArgs args; args.network_thread = &main_; - args.socket_factory = &socket_factory_; + args.socket_factory = socket_factory(); args.network = MakeNetwork(kLocalAddr1); args.username = kIceUfrag1; args.password = kIcePwd1; @@ -356,7 +371,7 @@ class TurnPortTest : public ::testing::Test, void CreateUdpPort() { CreateUdpPort(kLocalAddr2); } void CreateUdpPort(const SocketAddress& address) { - udp_port_ = UDPPort::Create(&main_, &socket_factory_, MakeNetwork(address), + udp_port_ = UDPPort::Create(&main_, socket_factory(), MakeNetwork(address), 0, 0, kIceUfrag2, kIcePwd2, false, absl::nullopt, &field_trials_); // UDP port will be controlled. @@ -436,8 +451,19 @@ class TurnPortTest : public ::testing::Test, return true; } + void TestTurnAllocateSucceeds(unsigned int timeout) { + ASSERT_TRUE(turn_port_); + turn_port_->PrepareAddress(); + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, timeout, fake_clock_); + ASSERT_EQ(1U, turn_port_->Candidates().size()); + EXPECT_EQ(kTurnUdpExtAddr.ipaddr(), + turn_port_->Candidates()[0].address().ipaddr()); + EXPECT_NE(0, turn_port_->Candidates()[0].address().port()); + } + void TestReconstructedServerUrl(ProtocolType protocol_type, absl::string_view expected_url) { + ASSERT_TRUE(turn_port_); turn_port_->PrepareAddress(); ASSERT_TRUE_SIMULATED_WAIT( turn_ready_, TimeToGetTurnCandidate(protocol_type), fake_clock_); @@ -762,6 +788,10 @@ class TurnPortTest : public ::testing::Test, } protected: + virtual rtc::PacketSocketFactory* socket_factory() { + return &socket_factory_; + } + webrtc::test::ScopedKeyValueConfig field_trials_; rtc::ScopedFakeClock fake_clock_; // When a "create port" helper method is called with an IP, we create a @@ -770,7 +800,6 @@ class TurnPortTest : public ::testing::Test, std::list<rtc::Network> networks_; std::unique_ptr<TurnPortTestVirtualSocketServer> ss_; rtc::AutoSocketServerThread main_; - rtc::BasicPacketSocketFactory socket_factory_; std::unique_ptr<rtc::AsyncPacketSocket> socket_; TestTurnServer turn_server_; std::unique_ptr<TurnPort> turn_port_; @@ -789,6 +818,9 @@ class TurnPortTest : public ::testing::Test, rtc::PacketOptions options; std::unique_ptr<webrtc::TurnCustomizer> turn_customizer_; cricket::IceCandidateErrorEvent error_event_; + + private: + rtc::BasicPacketSocketFactory socket_factory_; }; TEST_F(TurnPortTest, TestTurnPortType) { @@ -825,7 +857,8 @@ TEST_F(TurnPortTest, TestReconstructedServerUrlForTls) { } TEST_F(TurnPortTest, TestReconstructedServerUrlForHostname) { - CreateTurnPort(kTurnUsername, kTurnPassword, kTurnPortHostnameProtoAddr); + CreateTurnPort(kTurnUsername, kTurnPassword, + kTurnPortInvalidHostnameProtoAddr); // This test follows the pattern from TestTurnTcpOnAddressResolveFailure. // As VSS doesn't provide DNS resolution, name resolve will fail, // the error will be set and contain the url. @@ -840,12 +873,7 @@ TEST_F(TurnPortTest, TestReconstructedServerUrlForHostname) { TEST_F(TurnPortTest, TestTurnAllocate) { CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr); EXPECT_EQ(0, turn_port_->SetOption(rtc::Socket::OPT_SNDBUF, 10 * 1024)); - turn_port_->PrepareAddress(); - EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 2, fake_clock_); - ASSERT_EQ(1U, turn_port_->Candidates().size()); - EXPECT_EQ(kTurnUdpExtAddr.ipaddr(), - turn_port_->Candidates()[0].address().ipaddr()); - EXPECT_NE(0, turn_port_->Candidates()[0].address().port()); + TestTurnAllocateSucceeds(kSimulatedRtt * 2); } class TurnLoggingIdValidator : public StunMessageObserver { @@ -876,24 +904,14 @@ TEST_F(TurnPortTest, TestTurnAllocateWithLoggingId) { turn_port_->SetTurnLoggingId("KESO"); turn_server_.server()->SetStunMessageObserver( std::make_unique<TurnLoggingIdValidator>("KESO")); - turn_port_->PrepareAddress(); - EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 2, fake_clock_); - ASSERT_EQ(1U, turn_port_->Candidates().size()); - EXPECT_EQ(kTurnUdpExtAddr.ipaddr(), - turn_port_->Candidates()[0].address().ipaddr()); - EXPECT_NE(0, turn_port_->Candidates()[0].address().port()); + TestTurnAllocateSucceeds(kSimulatedRtt * 2); } TEST_F(TurnPortTest, TestTurnAllocateWithoutLoggingId) { CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr); turn_server_.server()->SetStunMessageObserver( std::make_unique<TurnLoggingIdValidator>(nullptr)); - turn_port_->PrepareAddress(); - EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 2, fake_clock_); - ASSERT_EQ(1U, turn_port_->Candidates().size()); - EXPECT_EQ(kTurnUdpExtAddr.ipaddr(), - turn_port_->Candidates()[0].address().ipaddr()); - EXPECT_NE(0, turn_port_->Candidates()[0].address().port()); + TestTurnAllocateSucceeds(kSimulatedRtt * 2); } // Test bad credentials. @@ -912,12 +930,7 @@ TEST_F(TurnPortTest, TestTurnTcpAllocate) { turn_server_.AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP); CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr); EXPECT_EQ(0, turn_port_->SetOption(rtc::Socket::OPT_SNDBUF, 10 * 1024)); - turn_port_->PrepareAddress(); - EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 3, fake_clock_); - ASSERT_EQ(1U, turn_port_->Candidates().size()); - EXPECT_EQ(kTurnUdpExtAddr.ipaddr(), - turn_port_->Candidates()[0].address().ipaddr()); - EXPECT_NE(0, turn_port_->Candidates()[0].address().port()); + TestTurnAllocateSucceeds(kSimulatedRtt * 3); } // Test case for WebRTC issue 3927 where a proxy binds to the local host address @@ -932,12 +945,7 @@ TEST_F(TurnPortTest, TestTurnTcpAllocationWhenProxyChangesAddressToLocalHost) { turn_server_.AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP); CreateTurnPort(kLocalAddr1, kTurnUsername, kTurnPassword, kTurnTcpProtoAddr); EXPECT_EQ(0, turn_port_->SetOption(rtc::Socket::OPT_SNDBUF, 10 * 1024)); - turn_port_->PrepareAddress(); - EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 3, fake_clock_); - ASSERT_EQ(1U, turn_port_->Candidates().size()); - EXPECT_EQ(kTurnUdpExtAddr.ipaddr(), - turn_port_->Candidates()[0].address().ipaddr()); - EXPECT_NE(0, turn_port_->Candidates()[0].address().port()); + TestTurnAllocateSucceeds(kSimulatedRtt * 3); // Verify that the socket actually used localhost, otherwise this test isn't // doing what it meant to. @@ -1525,12 +1533,7 @@ TEST_F(TurnPortTest, TestTurnLocalIPv6AddressServerIPv6ExtenalIPv4) { turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, PROTO_UDP); CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword, kTurnUdpIPv6ProtoAddr); - turn_port_->PrepareAddress(); - EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 2, fake_clock_); - ASSERT_EQ(1U, turn_port_->Candidates().size()); - EXPECT_EQ(kTurnUdpExtAddr.ipaddr(), - turn_port_->Candidates()[0].address().ipaddr()); - EXPECT_NE(0, turn_port_->Candidates()[0].address().port()); + TestTurnAllocateSucceeds(kSimulatedRtt * 2); } // Tests that the local and remote candidate address families should match when @@ -1861,4 +1864,139 @@ TEST_F(TurnPortTest, TestTurnDangerousServerAllowedWithFieldTrial) { ASSERT_TRUE(turn_port_); } +class TurnPortWithMockDnsResolverTest : public TurnPortTest { + public: + TurnPortWithMockDnsResolverTest() + : TurnPortTest(), socket_factory_(ss_.get()) {} + + rtc::PacketSocketFactory* socket_factory() override { + return &socket_factory_; + } + + void SetDnsResolverExpectations( + rtc::MockDnsResolvingPacketSocketFactory::Expectations expectations) { + socket_factory_.SetExpectations(expectations); + } + + private: + rtc::MockDnsResolvingPacketSocketFactory socket_factory_; +}; + +// Test an allocation from a TURN server specified by a hostname. +TEST_F(TurnPortWithMockDnsResolverTest, TestHostnameResolved) { + CreateTurnPort(kTurnUsername, kTurnPassword, kTurnPortValidHostnameProtoAddr); + SetDnsResolverExpectations( + [](webrtc::MockAsyncDnsResolver* resolver, + webrtc::MockAsyncDnsResolverResult* resolver_result) { + EXPECT_CALL(*resolver, Start(kTurnValidAddr, _)) + .WillOnce(InvokeArgument<1>()); + EXPECT_CALL(*resolver, result) + .WillRepeatedly(ReturnPointee(resolver_result)); + EXPECT_CALL(*resolver_result, GetError).WillRepeatedly(Return(0)); + EXPECT_CALL(*resolver_result, GetResolvedAddress(AF_INET, _)) + .WillOnce(DoAll(SetArgPointee<1>(kTurnUdpIntAddr), Return(true))); + }); + TestTurnAllocateSucceeds(kSimulatedRtt * 2); +} + +// Test an allocation from a TURN server specified by a hostname on an IPv6 +// network. +TEST_F(TurnPortWithMockDnsResolverTest, TestHostnameResolvedIPv6Network) { + turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, PROTO_UDP); + CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword, + kTurnPortValidHostnameProtoAddr); + SetDnsResolverExpectations( + [](webrtc::MockAsyncDnsResolver* resolver, + webrtc::MockAsyncDnsResolverResult* resolver_result) { + EXPECT_CALL(*resolver, Start(kTurnValidAddr, _)) + .WillOnce(InvokeArgument<1>()); + EXPECT_CALL(*resolver, result) + .WillRepeatedly(ReturnPointee(resolver_result)); + EXPECT_CALL(*resolver_result, GetError).WillRepeatedly(Return(0)); + EXPECT_CALL(*resolver_result, GetResolvedAddress(AF_INET6, _)) + .WillOnce( + DoAll(SetArgPointee<1>(kTurnUdpIPv6IntAddr), Return(true))); + }); + TestTurnAllocateSucceeds(kSimulatedRtt * 2); +} + +// Test an allocation from a TURN server specified by a hostname on an IPv6 +// network, without network family-specific resolution. +TEST_F(TurnPortWithMockDnsResolverTest, + TestHostnameResolvedIPv6NetworkFamilyFieldTrialDisabled) { + webrtc::test::ScopedKeyValueConfig override_field_trials( + field_trials_, "WebRTC-IPv6NetworkResolutionFixes/Disabled/"); + turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, PROTO_UDP); + CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword, + kTurnPortValidHostnameProtoAddr); + SetDnsResolverExpectations( + [](webrtc::MockAsyncDnsResolver* resolver, + webrtc::MockAsyncDnsResolverResult* resolver_result) { + // Expect to call Resolver::Start without family arg. + EXPECT_CALL(*resolver, Start(kTurnValidAddr, _)) + .WillOnce(InvokeArgument<1>()); + EXPECT_CALL(*resolver, result) + .WillRepeatedly(ReturnPointee(resolver_result)); + EXPECT_CALL(*resolver_result, GetError).WillRepeatedly(Return(0)); + EXPECT_CALL(*resolver_result, GetResolvedAddress(AF_INET6, _)) + .WillOnce( + DoAll(SetArgPointee<1>(kTurnUdpIPv6IntAddr), Return(true))); + }); + TestTurnAllocateSucceeds(kSimulatedRtt * 2); +} + +// Test an allocation from a TURN server specified by a hostname on an IPv6 +// network, without network family-specific resolution. +TEST_F(TurnPortWithMockDnsResolverTest, + TestHostnameResolvedIPv6NetworkFamilyFieldTrialParamDisabled) { + webrtc::test::ScopedKeyValueConfig override_field_trials( + field_trials_, + "WebRTC-IPv6NetworkResolutionFixes/" + "Enabled,ResolveTurnHostnameForFamily:false/"); + turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, PROTO_UDP); + CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword, + kTurnPortValidHostnameProtoAddr); + SetDnsResolverExpectations( + [](webrtc::MockAsyncDnsResolver* resolver, + webrtc::MockAsyncDnsResolverResult* resolver_result) { + // Expect to call Resolver::Start without family arg. + EXPECT_CALL(*resolver, Start(kTurnValidAddr, _)) + .WillOnce(InvokeArgument<1>()); + EXPECT_CALL(*resolver, result) + .WillRepeatedly(ReturnPointee(resolver_result)); + EXPECT_CALL(*resolver_result, GetError).WillRepeatedly(Return(0)); + EXPECT_CALL(*resolver_result, GetResolvedAddress(AF_INET6, _)) + .WillOnce( + DoAll(SetArgPointee<1>(kTurnUdpIPv6IntAddr), Return(true))); + }); + TestTurnAllocateSucceeds(kSimulatedRtt * 2); +} + +// Test an allocation from a TURN server specified by a hostname on an IPv6 +// network, with network family-specific resolution. +TEST_F(TurnPortWithMockDnsResolverTest, + TestHostnameResolvedIPv6NetworkFieldTrialEnabled) { + webrtc::test::ScopedKeyValueConfig override_field_trials( + field_trials_, + "WebRTC-IPv6NetworkResolutionFixes/" + "Enabled,ResolveTurnHostnameForFamily:true/"); + turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, PROTO_UDP); + CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword, + kTurnPortValidHostnameProtoAddr); + SetDnsResolverExpectations( + [](webrtc::MockAsyncDnsResolver* resolver, + webrtc::MockAsyncDnsResolverResult* resolver_result) { + // Expect to call Resolver::Start _with_ family arg. + EXPECT_CALL(*resolver, Start(kTurnValidAddr, /*family=*/AF_INET6, _)) + .WillOnce(InvokeArgument<2>()); + EXPECT_CALL(*resolver, result) + .WillRepeatedly(ReturnPointee(resolver_result)); + EXPECT_CALL(*resolver_result, GetError).WillRepeatedly(Return(0)); + EXPECT_CALL(*resolver_result, GetResolvedAddress(AF_INET6, _)) + .WillOnce( + DoAll(SetArgPointee<1>(kTurnUdpIPv6IntAddr), Return(true))); + }); + TestTurnAllocateSucceeds(kSimulatedRtt * 2); +} + } // namespace cricket |