Reland "Use the new DNS resolver API in PeerConnection"

This reverts commit 5a40b37105.

Reason for revert: Fixed the bug and ran layout tests.

Original change's description:
> Revert "Use the new DNS resolver API in PeerConnection"
>
> This reverts commit acf8ccb3c9.
>
> Reason for revert: Speculative revert for https://ci.chromium.org/ui/p/chromium/builders/try/win10_chromium_x64_rel_ng/b8851745102358680592/overview.
>
> Original change's description:
> > Use the new DNS resolver API in PeerConnection
> >
> > Bug: webrtc:12598
> > Change-Id: I5a14058e7f28c993ed927749df7357c715ba83fb
> > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/212961
> > Reviewed-by: Niels Moller <nisse@webrtc.org>
> > Commit-Queue: Harald Alvestrand <hta@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#33561}
>
> # Not skipping CQ checks because original CL landed > 1 day ago.
>
> TBR=hta@webrtc.org
>
> Bug: webrtc:12598
> Change-Id: Idc9853cb569849c49052f9cbd865614710fff979
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/213188
> Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
> Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#33591}

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: webrtc:12598
Change-Id: Ief7867f2f23de66504877cdab1b23a11df2d5de4
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/214120
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Tommi <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33647}
This commit is contained in:
Harald Alvestrand 2021-04-08 07:25:04 +00:00 committed by Commit Bot
parent 11bd143974
commit 0ccfbd2de7
20 changed files with 517 additions and 222 deletions

View file

@ -160,6 +160,7 @@ rtc_library("libjingle_peerconnection_api") {
] ]
deps = [ deps = [
":array_view", ":array_view",
":async_dns_resolver",
":audio_options_api", ":audio_options_api",
":callfactory_api", ":callfactory_api",
":fec_controller_api", ":fec_controller_api",
@ -249,11 +250,11 @@ rtc_library("rtc_error") {
rtc_source_set("packet_socket_factory") { rtc_source_set("packet_socket_factory") {
visibility = [ "*" ] visibility = [ "*" ]
sources = [ sources = [
"async_dns_resolver.h",
"async_resolver_factory.h", "async_resolver_factory.h",
"packet_socket_factory.h", "packet_socket_factory.h",
] ]
deps = [ deps = [
":async_dns_resolver",
"../rtc_base:async_resolver_interface", "../rtc_base:async_resolver_interface",
"../rtc_base:rtc_base", "../rtc_base:rtc_base",
"../rtc_base:socket_address", "../rtc_base:socket_address",
@ -261,6 +262,14 @@ rtc_source_set("packet_socket_factory") {
] ]
} }
rtc_source_set("async_dns_resolver") {
sources = [ "async_dns_resolver.h" ]
deps = [
"../rtc_base:socket_address",
"../rtc_base/system:rtc_export",
]
}
rtc_source_set("scoped_refptr") { rtc_source_set("scoped_refptr") {
visibility = [ "*" ] visibility = [ "*" ]
sources = [ "scoped_refptr.h" ] sources = [ "scoped_refptr.h" ]
@ -940,6 +949,15 @@ if (rtc_include_tests) {
] ]
} }
rtc_source_set("mock_async_dns_resolver") {
testonly = true
sources = [ "test/mock_async_dns_resolver.h" ]
deps = [
":async_dns_resolver",
"../test:test_support",
]
}
rtc_source_set("mock_rtp") { rtc_source_set("mock_rtp") {
visibility = [ "*" ] visibility = [ "*" ]
testonly = true testonly = true
@ -1092,6 +1110,7 @@ if (rtc_include_tests) {
":dummy_peer_connection", ":dummy_peer_connection",
":fake_frame_decryptor", ":fake_frame_decryptor",
":fake_frame_encryptor", ":fake_frame_encryptor",
":mock_async_dns_resolver",
":mock_audio_mixer", ":mock_audio_mixer",
":mock_data_channel", ":mock_data_channel",
":mock_frame_decryptor", ":mock_frame_decryptor",

View file

@ -11,6 +11,7 @@
#ifndef API_ASYNC_DNS_RESOLVER_H_ #ifndef API_ASYNC_DNS_RESOLVER_H_
#define API_ASYNC_DNS_RESOLVER_H_ #define API_ASYNC_DNS_RESOLVER_H_
#include <functional>
#include <memory> #include <memory>
#include "rtc_base/socket_address.h" #include "rtc_base/socket_address.h"

View file

@ -58,10 +58,18 @@ rtc::scoped_refptr<IceTransportInterface> CreateIceTransport(
rtc::scoped_refptr<IceTransportInterface> CreateIceTransport( rtc::scoped_refptr<IceTransportInterface> CreateIceTransport(
IceTransportInit init) { IceTransportInit init) {
if (init.async_resolver_factory()) {
// Backwards compatibility mode
return new rtc::RefCountedObject<IceTransportWithTransportChannel>( return new rtc::RefCountedObject<IceTransportWithTransportChannel>(
std::make_unique<cricket::P2PTransportChannel>( std::make_unique<cricket::P2PTransportChannel>(
"", cricket::ICE_CANDIDATE_COMPONENT_RTP, init.port_allocator(), "", cricket::ICE_CANDIDATE_COMPONENT_RTP, init.port_allocator(),
init.async_resolver_factory(), init.event_log())); init.async_resolver_factory(), init.event_log()));
} else {
return new rtc::RefCountedObject<IceTransportWithTransportChannel>(
cricket::P2PTransportChannel::Create(
"", cricket::ICE_CANDIDATE_COMPONENT_RTP, init.port_allocator(),
init.async_dns_resolver_factory(), init.event_log()));
}
} }
} // namespace webrtc } // namespace webrtc

View file

@ -13,6 +13,7 @@
#include <string> #include <string>
#include "api/async_dns_resolver.h"
#include "api/async_resolver_factory.h" #include "api/async_resolver_factory.h"
#include "api/rtc_error.h" #include "api/rtc_error.h"
#include "api/rtc_event_log/rtc_event_log.h" #include "api/rtc_event_log/rtc_event_log.h"
@ -52,11 +53,21 @@ struct IceTransportInit final {
port_allocator_ = port_allocator; port_allocator_ = port_allocator;
} }
AsyncDnsResolverFactoryInterface* async_dns_resolver_factory() {
return async_dns_resolver_factory_;
}
void set_async_dns_resolver_factory(
AsyncDnsResolverFactoryInterface* async_dns_resolver_factory) {
RTC_DCHECK(!async_resolver_factory_);
async_dns_resolver_factory_ = async_dns_resolver_factory;
}
AsyncResolverFactory* async_resolver_factory() { AsyncResolverFactory* async_resolver_factory() {
return async_resolver_factory_; return async_resolver_factory_;
} }
ABSL_DEPRECATED("bugs.webrtc.org/12598")
void set_async_resolver_factory( void set_async_resolver_factory(
AsyncResolverFactory* async_resolver_factory) { AsyncResolverFactory* async_resolver_factory) {
RTC_DCHECK(!async_dns_resolver_factory_);
async_resolver_factory_ = async_resolver_factory; async_resolver_factory_ = async_resolver_factory;
} }
@ -65,8 +76,11 @@ struct IceTransportInit final {
private: private:
cricket::PortAllocator* port_allocator_ = nullptr; cricket::PortAllocator* port_allocator_ = nullptr;
AsyncDnsResolverFactoryInterface* async_dns_resolver_factory_ = nullptr;
// For backwards compatibility. Only one resolver factory can be set.
AsyncResolverFactory* async_resolver_factory_ = nullptr; AsyncResolverFactory* async_resolver_factory_ = nullptr;
RtcEventLog* event_log_ = nullptr; RtcEventLog* event_log_ = nullptr;
// TODO(https://crbug.com/webrtc/12657): Redesign to have const members.
}; };
// TODO(qingsi): The factory interface is defined in this file instead of its // TODO(qingsi): The factory interface is defined in this file instead of its

View file

@ -74,6 +74,7 @@
#include <vector> #include <vector>
#include "api/adaptation/resource.h" #include "api/adaptation/resource.h"
#include "api/async_dns_resolver.h"
#include "api/async_resolver_factory.h" #include "api/async_resolver_factory.h"
#include "api/audio/audio_mixer.h" #include "api/audio/audio_mixer.h"
#include "api/audio_codecs/audio_decoder_factory.h" #include "api/audio_codecs/audio_decoder_factory.h"
@ -1322,6 +1323,10 @@ struct RTC_EXPORT PeerConnectionDependencies final {
// packet_socket_factory, not both. // packet_socket_factory, not both.
std::unique_ptr<cricket::PortAllocator> allocator; std::unique_ptr<cricket::PortAllocator> allocator;
std::unique_ptr<rtc::PacketSocketFactory> packet_socket_factory; std::unique_ptr<rtc::PacketSocketFactory> packet_socket_factory;
// Factory for creating resolvers that look up hostnames in DNS
std::unique_ptr<webrtc::AsyncDnsResolverFactoryInterface>
async_dns_resolver_factory;
// Deprecated - use async_dns_resolver_factory
std::unique_ptr<webrtc::AsyncResolverFactory> async_resolver_factory; std::unique_ptr<webrtc::AsyncResolverFactory> async_resolver_factory;
std::unique_ptr<webrtc::IceTransportFactory> ice_transport_factory; std::unique_ptr<webrtc::IceTransportFactory> ice_transport_factory;
std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator; std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator;

View file

@ -30,6 +30,7 @@
#include "api/test/dummy_peer_connection.h" #include "api/test/dummy_peer_connection.h"
#include "api/test/fake_frame_decryptor.h" #include "api/test/fake_frame_decryptor.h"
#include "api/test/fake_frame_encryptor.h" #include "api/test/fake_frame_encryptor.h"
#include "api/test/mock_async_dns_resolver.h"
#include "api/test/mock_audio_mixer.h" #include "api/test/mock_audio_mixer.h"
#include "api/test/mock_data_channel.h" #include "api/test/mock_data_channel.h"
#include "api/test/mock_frame_decryptor.h" #include "api/test/mock_frame_decryptor.h"

View file

@ -0,0 +1,54 @@
/*
* Copyright 2021 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 API_TEST_MOCK_ASYNC_DNS_RESOLVER_H_
#define API_TEST_MOCK_ASYNC_DNS_RESOLVER_H_
#include <functional>
#include <memory>
#include "api/async_dns_resolver.h"
#include "test/gmock.h"
namespace webrtc {
class MockAsyncDnsResolverResult : public AsyncDnsResolverResult {
public:
MOCK_METHOD(bool,
GetResolvedAddress,
(int, rtc::SocketAddress*),
(const override));
MOCK_METHOD(int, GetError, (), (const override));
};
class MockAsyncDnsResolver : public AsyncDnsResolverInterface {
public:
MOCK_METHOD(void,
Start,
(const rtc::SocketAddress&, std::function<void()>),
(override));
MOCK_METHOD(AsyncDnsResolverResult&, result, (), (const override));
};
class MockAsyncDnsResolverFactory : public AsyncDnsResolverFactoryInterface {
public:
MOCK_METHOD(std::unique_ptr<webrtc::AsyncDnsResolverInterface>,
CreateAndResolve,
(const rtc::SocketAddress&, std::function<void()>),
(override));
MOCK_METHOD(std::unique_ptr<webrtc::AsyncDnsResolverInterface>,
Create,
(),
(override));
};
} // namespace webrtc
#endif // API_TEST_MOCK_ASYNC_DNS_RESOLVER_H_

View file

@ -86,6 +86,8 @@ rtc_library("rtc_p2p") {
] ]
deps = [ deps = [
"../api:array_view",
"../api:async_dns_resolver",
"../api:libjingle_peerconnection_api", "../api:libjingle_peerconnection_api",
"../api:packet_socket_factory", "../api:packet_socket_factory",
"../api:rtc_error", "../api:rtc_error",
@ -93,6 +95,7 @@ rtc_library("rtc_p2p") {
"../api:sequence_checker", "../api:sequence_checker",
"../api/crypto:options", "../api/crypto:options",
"../api/rtc_event_log", "../api/rtc_event_log",
"../api/task_queue",
"../api/transport:enums", "../api/transport:enums",
"../api/transport:stun_types", "../api/transport:stun_types",
"../logging:ice_log", "../logging:ice_log",
@ -235,6 +238,7 @@ if (rtc_include_tests) {
":p2p_test_utils", ":p2p_test_utils",
":rtc_p2p", ":rtc_p2p",
"../api:libjingle_peerconnection_api", "../api:libjingle_peerconnection_api",
"../api:mock_async_dns_resolver",
"../api:packet_socket_factory", "../api:packet_socket_factory",
"../api:scoped_refptr", "../api:scoped_refptr",
"../api/transport:stun_types", "../api/transport:stun_types",
@ -256,6 +260,7 @@ if (rtc_include_tests) {
"../rtc_base/third_party/sigslot", "../rtc_base/third_party/sigslot",
"../system_wrappers:metrics", "../system_wrappers:metrics",
"../test:field_trial", "../test:field_trial",
"../test:rtc_expect_death",
"../test:test_support", "../test:test_support",
"//testing/gtest", "//testing/gtest",
] ]

View file

@ -16,6 +16,7 @@
#include "absl/memory/memory.h" #include "absl/memory/memory.h"
#include "api/async_dns_resolver.h" #include "api/async_dns_resolver.h"
#include "rtc_base/async_resolver.h" #include "rtc_base/async_resolver.h"
#include "rtc_base/logging.h"
namespace webrtc { namespace webrtc {
@ -46,11 +47,19 @@ class WrappingAsyncDnsResolver : public AsyncDnsResolverInterface,
explicit WrappingAsyncDnsResolver(rtc::AsyncResolverInterface* wrapped) explicit WrappingAsyncDnsResolver(rtc::AsyncResolverInterface* wrapped)
: wrapped_(absl::WrapUnique(wrapped)), result_(this) {} : wrapped_(absl::WrapUnique(wrapped)), result_(this) {}
~WrappingAsyncDnsResolver() override { wrapped_.release()->Destroy(false); } ~WrappingAsyncDnsResolver() override {
// Workaround to get around the fact that sigslot-using objects can't be
// destroyed from within their callback: Alert class users early.
// TODO(bugs.webrtc.org/12651): Delete this class once the sigslot users are
// gone.
RTC_CHECK(!within_resolve_result_);
wrapped_.release()->Destroy(false);
}
void Start(const rtc::SocketAddress& addr, void Start(const rtc::SocketAddress& addr,
std::function<void()> callback) override { std::function<void()> callback) override {
RTC_DCHECK(state_ == State::kNotStarted); RTC_DCHECK_RUN_ON(&sequence_checker_);
RTC_DCHECK_EQ(State::kNotStarted, state_);
state_ = State::kStarted; state_ = State::kStarted;
callback_ = callback; callback_ = callback;
wrapped_->SignalDone.connect(this, wrapped_->SignalDone.connect(this,
@ -59,27 +68,39 @@ class WrappingAsyncDnsResolver : public AsyncDnsResolverInterface,
} }
const AsyncDnsResolverResult& result() const override { const AsyncDnsResolverResult& result() const override {
RTC_DCHECK(state_ == State::kResolved); RTC_DCHECK_RUN_ON(&sequence_checker_);
RTC_DCHECK_EQ(State::kResolved, state_);
return result_; return result_;
} }
// For use by WrappingAsyncDnsResolverResult
rtc::AsyncResolverInterface* wrapped() const { return wrapped_.get(); }
private: private:
enum class State { kNotStarted, kStarted, kResolved }; enum class State { kNotStarted, kStarted, kResolved };
friend class WrappingAsyncDnsResolverResult;
// For use by WrappingAsyncDnsResolverResult
rtc::AsyncResolverInterface* wrapped() const {
RTC_DCHECK_RUN_ON(&sequence_checker_);
return wrapped_.get();
}
void OnResolveResult(rtc::AsyncResolverInterface* ref) { void OnResolveResult(rtc::AsyncResolverInterface* ref) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
RTC_DCHECK(state_ == State::kStarted); RTC_DCHECK(state_ == State::kStarted);
RTC_DCHECK_EQ(ref, wrapped_.get()); RTC_DCHECK_EQ(ref, wrapped_.get());
state_ = State::kResolved; state_ = State::kResolved;
within_resolve_result_ = true;
callback_(); callback_();
within_resolve_result_ = false;
} }
std::function<void()> callback_; // The class variables need to be accessed on a single thread.
std::unique_ptr<rtc::AsyncResolverInterface> wrapped_; SequenceChecker sequence_checker_;
State state_ = State::kNotStarted; std::function<void()> callback_ RTC_GUARDED_BY(sequence_checker_);
WrappingAsyncDnsResolverResult result_; std::unique_ptr<rtc::AsyncResolverInterface> wrapped_
RTC_GUARDED_BY(sequence_checker_);
State state_ RTC_GUARDED_BY(sequence_checker_) = State::kNotStarted;
WrappingAsyncDnsResolverResult result_ RTC_GUARDED_BY(sequence_checker_);
bool within_resolve_result_ RTC_GUARDED_BY(sequence_checker_) = false;
}; };
bool WrappingAsyncDnsResolverResult::GetResolvedAddress( bool WrappingAsyncDnsResolverResult::GetResolvedAddress(

View file

@ -32,9 +32,15 @@ class BasicAsyncResolverFactory final : public AsyncResolverFactory {
class WrappingAsyncDnsResolverFactory final class WrappingAsyncDnsResolverFactory final
: public AsyncDnsResolverFactoryInterface { : public AsyncDnsResolverFactoryInterface {
public: public:
WrappingAsyncDnsResolverFactory( explicit WrappingAsyncDnsResolverFactory(
std::unique_ptr<AsyncResolverFactory> wrapped_factory) std::unique_ptr<AsyncResolverFactory> wrapped_factory)
: wrapped_factory_(std::move(wrapped_factory)) {} : owned_factory_(std::move(wrapped_factory)),
wrapped_factory_(owned_factory_.get()) {}
explicit WrappingAsyncDnsResolverFactory(
AsyncResolverFactory* non_owned_factory)
: wrapped_factory_(non_owned_factory) {}
std::unique_ptr<webrtc::AsyncDnsResolverInterface> CreateAndResolve( std::unique_ptr<webrtc::AsyncDnsResolverInterface> CreateAndResolve(
const rtc::SocketAddress& addr, const rtc::SocketAddress& addr,
std::function<void()> callback) override; std::function<void()> callback) override;
@ -42,7 +48,8 @@ class WrappingAsyncDnsResolverFactory final
std::unique_ptr<webrtc::AsyncDnsResolverInterface> Create() override; std::unique_ptr<webrtc::AsyncDnsResolverInterface> Create() override;
private: private:
const std::unique_ptr<AsyncResolverFactory> wrapped_factory_; const std::unique_ptr<AsyncResolverFactory> owned_factory_;
AsyncResolverFactory* const wrapped_factory_;
}; };
} // namespace webrtc } // namespace webrtc

View file

@ -10,10 +10,15 @@
#include "p2p/base/basic_async_resolver_factory.h" #include "p2p/base/basic_async_resolver_factory.h"
#include "api/test/mock_async_dns_resolver.h"
#include "p2p/base/mock_async_resolver.h"
#include "rtc_base/async_resolver.h"
#include "rtc_base/gunit.h" #include "rtc_base/gunit.h"
#include "rtc_base/socket_address.h" #include "rtc_base/socket_address.h"
#include "rtc_base/third_party/sigslot/sigslot.h" #include "rtc_base/third_party/sigslot/sigslot.h"
#include "test/gmock.h"
#include "test/gtest.h" #include "test/gtest.h"
#include "test/testsupport/rtc_expect_death.h"
namespace webrtc { namespace webrtc {
@ -47,7 +52,7 @@ TEST_F(BasicAsyncResolverFactoryTest, TestCreate) {
TestCreate(); TestCreate();
} }
TEST(WrappingAsyncDnsResolverFactoryTest, TestCreate) { TEST(WrappingAsyncDnsResolverFactoryTest, TestCreateAndResolve) {
WrappingAsyncDnsResolverFactory factory( WrappingAsyncDnsResolverFactory factory(
std::make_unique<BasicAsyncResolverFactory>()); std::make_unique<BasicAsyncResolverFactory>());
@ -61,4 +66,24 @@ TEST(WrappingAsyncDnsResolverFactoryTest, TestCreate) {
resolver.reset(); resolver.reset();
} }
TEST(WrappingAsyncDnsResolverFactoryTest, WrapOtherResolver) {
BasicAsyncResolverFactory non_owned_factory;
WrappingAsyncDnsResolverFactory factory(&non_owned_factory);
std::unique_ptr<AsyncDnsResolverInterface> resolver(factory.Create());
ASSERT_TRUE(resolver);
bool address_resolved = false;
rtc::SocketAddress address("", 0);
resolver->Start(address, [&address_resolved]() { address_resolved = true; });
ASSERT_TRUE_WAIT(address_resolved, 10000 /*ms*/);
resolver.reset();
}
void CallResolver(WrappingAsyncDnsResolverFactory& factory) {
rtc::SocketAddress address("", 0);
std::unique_ptr<AsyncDnsResolverInterface> resolver(factory.Create());
resolver->Start(address, [&resolver]() { resolver.reset(); });
WAIT(!resolver.get(), 10000 /*ms*/);
}
} // namespace webrtc } // namespace webrtc

View file

@ -45,9 +45,9 @@ DefaultIceTransportFactory::CreateIceTransport(
IceTransportInit init) { IceTransportInit init) {
BasicIceControllerFactory factory; BasicIceControllerFactory factory;
return new rtc::RefCountedObject<DefaultIceTransport>( return new rtc::RefCountedObject<DefaultIceTransport>(
std::make_unique<cricket::P2PTransportChannel>( cricket::P2PTransportChannel::Create(
transport_name, component, init.port_allocator(), transport_name, component, init.port_allocator(),
init.async_resolver_factory(), init.event_log(), &factory)); init.async_dns_resolver_factory(), init.event_log(), &factory));
} }
} // namespace webrtc } // namespace webrtc

View file

@ -10,27 +10,38 @@
#include "p2p/base/p2p_transport_channel.h" #include "p2p/base/p2p_transport_channel.h"
#include <iterator> #include <errno.h>
#include <stdlib.h>
#include <algorithm>
#include <functional>
#include <memory> #include <memory>
#include <set> #include <set>
#include <utility> #include <utility>
#include "absl/algorithm/container.h" #include "absl/algorithm/container.h"
#include "absl/memory/memory.h"
#include "absl/strings/match.h" #include "absl/strings/match.h"
#include "api/async_dns_resolver.h"
#include "api/candidate.h" #include "api/candidate.h"
#include "api/task_queue/queued_task.h"
#include "logging/rtc_event_log/ice_logger.h" #include "logging/rtc_event_log/ice_logger.h"
#include "p2p/base/basic_async_resolver_factory.h"
#include "p2p/base/basic_ice_controller.h" #include "p2p/base/basic_ice_controller.h"
#include "p2p/base/candidate_pair_interface.h"
#include "p2p/base/connection.h" #include "p2p/base/connection.h"
#include "p2p/base/connection_info.h"
#include "p2p/base/port.h" #include "p2p/base/port.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/crc32.h" #include "rtc_base/crc32.h"
#include "rtc_base/experiments/struct_parameters_parser.h" #include "rtc_base/experiments/struct_parameters_parser.h"
#include "rtc_base/ip_address.h"
#include "rtc_base/logging.h" #include "rtc_base/logging.h"
#include "rtc_base/net_helper.h" #include "rtc_base/net_helper.h"
#include "rtc_base/net_helpers.h" #include "rtc_base/network.h"
#include "rtc_base/network_constants.h"
#include "rtc_base/string_encode.h" #include "rtc_base/string_encode.h"
#include "rtc_base/task_utils/to_queued_task.h" #include "rtc_base/task_utils/to_queued_task.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/time_utils.h" #include "rtc_base/time_utils.h"
#include "system_wrappers/include/field_trial.h" #include "system_wrappers/include/field_trial.h"
#include "system_wrappers/include/metrics.h" #include "system_wrappers/include/metrics.h"
@ -122,26 +133,50 @@ bool IceCredentialsChanged(const std::string& old_ufrag,
return (old_ufrag != new_ufrag) || (old_pwd != new_pwd); return (old_ufrag != new_ufrag) || (old_pwd != new_pwd);
} }
// static
std::unique_ptr<P2PTransportChannel> P2PTransportChannel::Create(
const std::string& transport_name,
int component,
PortAllocator* allocator,
webrtc::AsyncDnsResolverFactoryInterface* async_dns_resolver_factory,
webrtc::RtcEventLog* event_log,
IceControllerFactoryInterface* ice_controller_factory) {
return absl::WrapUnique(new P2PTransportChannel(
transport_name, component, allocator, async_dns_resolver_factory,
/* owned_dns_resolver_factory= */ nullptr, event_log,
ice_controller_factory));
}
P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, P2PTransportChannel::P2PTransportChannel(const std::string& transport_name,
int component, int component,
PortAllocator* allocator) PortAllocator* allocator)
: P2PTransportChannel(transport_name, : P2PTransportChannel(transport_name,
component, component,
allocator, allocator,
nullptr, /* async_dns_resolver_factory= */ nullptr,
nullptr) {} /* owned_dns_resolver_factory= */ nullptr,
/* event_log= */ nullptr,
/* ice_controller_factory= */ nullptr) {}
// Private constructor, called from Create()
P2PTransportChannel::P2PTransportChannel( P2PTransportChannel::P2PTransportChannel(
const std::string& transport_name, const std::string& transport_name,
int component, int component,
PortAllocator* allocator, PortAllocator* allocator,
webrtc::AsyncResolverFactory* async_resolver_factory, webrtc::AsyncDnsResolverFactoryInterface* async_dns_resolver_factory,
std::unique_ptr<webrtc::AsyncDnsResolverFactoryInterface>
owned_dns_resolver_factory,
webrtc::RtcEventLog* event_log, webrtc::RtcEventLog* event_log,
IceControllerFactoryInterface* ice_controller_factory) IceControllerFactoryInterface* ice_controller_factory)
: transport_name_(transport_name), : transport_name_(transport_name),
component_(component), component_(component),
allocator_(allocator), allocator_(allocator),
async_resolver_factory_(async_resolver_factory), // If owned_dns_resolver_factory is given, async_dns_resolver_factory is
// ignored.
async_dns_resolver_factory_(owned_dns_resolver_factory
? owned_dns_resolver_factory.get()
: async_dns_resolver_factory),
owned_dns_resolver_factory_(std::move(owned_dns_resolver_factory)),
network_thread_(rtc::Thread::Current()), network_thread_(rtc::Thread::Current()),
incoming_only_(false), incoming_only_(false),
error_(0), error_(0),
@ -192,15 +227,31 @@ P2PTransportChannel::P2PTransportChannel(
} }
} }
// Public constructor, exposed for backwards compatibility.
// Deprecated.
P2PTransportChannel::P2PTransportChannel(
const std::string& transport_name,
int component,
PortAllocator* allocator,
webrtc::AsyncResolverFactory* async_resolver_factory,
webrtc::RtcEventLog* event_log,
IceControllerFactoryInterface* ice_controller_factory)
: P2PTransportChannel(
transport_name,
component,
allocator,
nullptr,
std::make_unique<webrtc::WrappingAsyncDnsResolverFactory>(
async_resolver_factory),
event_log,
ice_controller_factory) {}
P2PTransportChannel::~P2PTransportChannel() { P2PTransportChannel::~P2PTransportChannel() {
RTC_DCHECK_RUN_ON(network_thread_); RTC_DCHECK_RUN_ON(network_thread_);
std::vector<Connection*> copy(connections().begin(), connections().end()); std::vector<Connection*> copy(connections().begin(), connections().end());
for (Connection* con : copy) { for (Connection* con : copy) {
con->Destroy(); con->Destroy();
} }
for (auto& p : resolvers_) {
p.resolver_->Destroy(false);
}
resolvers_.clear(); resolvers_.clear();
} }
@ -1164,16 +1215,17 @@ void P2PTransportChannel::OnNominated(Connection* conn) {
void P2PTransportChannel::ResolveHostnameCandidate(const Candidate& candidate) { void P2PTransportChannel::ResolveHostnameCandidate(const Candidate& candidate) {
RTC_DCHECK_RUN_ON(network_thread_); RTC_DCHECK_RUN_ON(network_thread_);
if (!async_resolver_factory_) { if (!async_dns_resolver_factory_) {
RTC_LOG(LS_WARNING) << "Dropping ICE candidate with hostname address " RTC_LOG(LS_WARNING) << "Dropping ICE candidate with hostname address "
"(no AsyncResolverFactory)"; "(no AsyncResolverFactory)";
return; return;
} }
rtc::AsyncResolverInterface* resolver = async_resolver_factory_->Create(); auto resolver = async_dns_resolver_factory_->Create();
resolvers_.emplace_back(candidate, resolver); auto resptr = resolver.get();
resolver->SignalDone.connect(this, &P2PTransportChannel::OnCandidateResolved); resolvers_.emplace_back(candidate, std::move(resolver));
resolver->Start(candidate.address()); resptr->Start(candidate.address(),
[this, resptr]() { OnCandidateResolved(resptr); });
RTC_LOG(LS_INFO) << "Asynchronously resolving ICE candidate hostname " RTC_LOG(LS_INFO) << "Asynchronously resolving ICE candidate hostname "
<< candidate.address().HostAsSensitiveURIString(); << candidate.address().HostAsSensitiveURIString();
} }
@ -1228,38 +1280,44 @@ void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) {
P2PTransportChannel::CandidateAndResolver::CandidateAndResolver( P2PTransportChannel::CandidateAndResolver::CandidateAndResolver(
const Candidate& candidate, const Candidate& candidate,
rtc::AsyncResolverInterface* resolver) std::unique_ptr<webrtc::AsyncDnsResolverInterface>&& resolver)
: candidate_(candidate), resolver_(resolver) {} : candidate_(candidate), resolver_(std::move(resolver)) {}
P2PTransportChannel::CandidateAndResolver::~CandidateAndResolver() {} P2PTransportChannel::CandidateAndResolver::~CandidateAndResolver() {}
void P2PTransportChannel::OnCandidateResolved( void P2PTransportChannel::OnCandidateResolved(
rtc::AsyncResolverInterface* resolver) { webrtc::AsyncDnsResolverInterface* resolver) {
RTC_DCHECK_RUN_ON(network_thread_); RTC_DCHECK_RUN_ON(network_thread_);
auto p = auto p =
absl::c_find_if(resolvers_, [resolver](const CandidateAndResolver& cr) { absl::c_find_if(resolvers_, [resolver](const CandidateAndResolver& cr) {
return cr.resolver_ == resolver; return cr.resolver_.get() == resolver;
}); });
if (p == resolvers_.end()) { if (p == resolvers_.end()) {
RTC_LOG(LS_ERROR) << "Unexpected AsyncResolver signal"; RTC_LOG(LS_ERROR) << "Unexpected AsyncDnsResolver return";
RTC_NOTREACHED(); RTC_NOTREACHED();
return; return;
} }
Candidate candidate = p->candidate_; Candidate candidate = p->candidate_;
resolvers_.erase(p); AddRemoteCandidateWithResult(candidate, resolver->result());
AddRemoteCandidateWithResolver(candidate, resolver); // Now we can delete the resolver.
// TODO(bugs.webrtc.org/12651): Replace the stuff below with
// resolvers_.erase(p);
std::unique_ptr<webrtc::AsyncDnsResolverInterface> to_delete =
std::move(p->resolver_);
// Delay the actual deletion of the resolver until the lambda executes.
network_thread_->PostTask( network_thread_->PostTask(
ToQueuedTask([resolver]() { resolver->Destroy(false); })); ToQueuedTask([delete_this = std::move(to_delete)] {}));
resolvers_.erase(p);
} }
void P2PTransportChannel::AddRemoteCandidateWithResolver( void P2PTransportChannel::AddRemoteCandidateWithResult(
Candidate candidate, Candidate candidate,
rtc::AsyncResolverInterface* resolver) { const webrtc::AsyncDnsResolverResult& result) {
RTC_DCHECK_RUN_ON(network_thread_); RTC_DCHECK_RUN_ON(network_thread_);
if (resolver->GetError()) { if (result.GetError()) {
RTC_LOG(LS_WARNING) << "Failed to resolve ICE candidate hostname " RTC_LOG(LS_WARNING) << "Failed to resolve ICE candidate hostname "
<< candidate.address().HostAsSensitiveURIString() << candidate.address().HostAsSensitiveURIString()
<< " with error " << resolver->GetError(); << " with error " << result.GetError();
return; return;
} }
@ -1267,9 +1325,8 @@ void P2PTransportChannel::AddRemoteCandidateWithResolver(
// Prefer IPv6 to IPv4 if we have it (see RFC 5245 Section 15.1). // Prefer IPv6 to IPv4 if we have it (see RFC 5245 Section 15.1).
// TODO(zstein): This won't work if we only have IPv4 locally but receive an // TODO(zstein): This won't work if we only have IPv4 locally but receive an
// AAAA DNS record. // AAAA DNS record.
bool have_address = bool have_address = result.GetResolvedAddress(AF_INET6, &resolved_address) ||
resolver->GetResolvedAddress(AF_INET6, &resolved_address) || result.GetResolvedAddress(AF_INET, &resolved_address);
resolver->GetResolvedAddress(AF_INET, &resolved_address);
if (!have_address) { if (!have_address) {
RTC_LOG(LS_INFO) << "ICE candidate hostname " RTC_LOG(LS_INFO) << "ICE candidate hostname "
<< candidate.address().HostAsSensitiveURIString() << candidate.address().HostAsSensitiveURIString()

View file

@ -20,6 +20,9 @@
#ifndef P2P_BASE_P2P_TRANSPORT_CHANNEL_H_ #ifndef P2P_BASE_P2P_TRANSPORT_CHANNEL_H_
#define P2P_BASE_P2P_TRANSPORT_CHANNEL_H_ #define P2P_BASE_P2P_TRANSPORT_CHANNEL_H_
#include <stddef.h>
#include <stdint.h>
#include <algorithm> #include <algorithm>
#include <map> #include <map>
#include <memory> #include <memory>
@ -27,26 +30,43 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "absl/base/attributes.h"
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "api/async_dns_resolver.h"
#include "api/async_resolver_factory.h" #include "api/async_resolver_factory.h"
#include "api/candidate.h" #include "api/candidate.h"
#include "api/rtc_error.h" #include "api/rtc_error.h"
#include "api/sequence_checker.h"
#include "api/transport/enums.h"
#include "api/transport/stun.h"
#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h" #include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h"
#include "logging/rtc_event_log/ice_logger.h" #include "logging/rtc_event_log/ice_logger.h"
#include "p2p/base/candidate_pair_interface.h" #include "p2p/base/candidate_pair_interface.h"
#include "p2p/base/connection.h"
#include "p2p/base/ice_controller_factory_interface.h" #include "p2p/base/ice_controller_factory_interface.h"
#include "p2p/base/ice_controller_interface.h" #include "p2p/base/ice_controller_interface.h"
#include "p2p/base/ice_transport_internal.h" #include "p2p/base/ice_transport_internal.h"
#include "p2p/base/p2p_constants.h" #include "p2p/base/p2p_constants.h"
#include "p2p/base/p2p_transport_channel_ice_field_trials.h" #include "p2p/base/p2p_transport_channel_ice_field_trials.h"
#include "p2p/base/port.h"
#include "p2p/base/port_allocator.h" #include "p2p/base/port_allocator.h"
#include "p2p/base/port_interface.h" #include "p2p/base/port_interface.h"
#include "p2p/base/regathering_controller.h" #include "p2p/base/regathering_controller.h"
#include "p2p/base/transport_description.h"
#include "rtc_base/async_packet_socket.h" #include "rtc_base/async_packet_socket.h"
#include "rtc_base/checks.h"
#include "rtc_base/constructor_magic.h" #include "rtc_base/constructor_magic.h"
#include "rtc_base/dscp.h"
#include "rtc_base/network/sent_packet.h"
#include "rtc_base/network_route.h"
#include "rtc_base/socket.h"
#include "rtc_base/socket_address.h"
#include "rtc_base/strings/string_builder.h" #include "rtc_base/strings/string_builder.h"
#include "rtc_base/system/rtc_export.h" #include "rtc_base/system/rtc_export.h"
#include "rtc_base/task_utils/pending_task_safety_flag.h" #include "rtc_base/task_utils/pending_task_safety_flag.h"
#include "rtc_base/third_party/sigslot/sigslot.h" #include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"
#include "rtc_base/thread_annotations.h" #include "rtc_base/thread_annotations.h"
namespace webrtc { namespace webrtc {
@ -82,11 +102,19 @@ class RemoteCandidate : public Candidate {
// two P2P clients connected to each other. // two P2P clients connected to each other.
class RTC_EXPORT P2PTransportChannel : public IceTransportInternal { class RTC_EXPORT P2PTransportChannel : public IceTransportInternal {
public: public:
static std::unique_ptr<P2PTransportChannel> Create(
const std::string& transport_name,
int component,
PortAllocator* allocator,
webrtc::AsyncDnsResolverFactoryInterface* async_dns_resolver_factory,
webrtc::RtcEventLog* event_log = nullptr,
IceControllerFactoryInterface* ice_controller_factory = nullptr);
// For testing only. // For testing only.
// TODO(zstein): Remove once AsyncResolverFactory is required. // TODO(zstein): Remove once AsyncDnsResolverFactory is required.
P2PTransportChannel(const std::string& transport_name, P2PTransportChannel(const std::string& transport_name,
int component, int component,
PortAllocator* allocator); PortAllocator* allocator);
ABSL_DEPRECATED("bugs.webrtc.org/12598")
P2PTransportChannel( P2PTransportChannel(
const std::string& transport_name, const std::string& transport_name,
int component, int component,
@ -209,6 +237,18 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal {
} }
private: private:
P2PTransportChannel(
const std::string& transport_name,
int component,
PortAllocator* allocator,
// DNS resolver factory
webrtc::AsyncDnsResolverFactoryInterface* async_dns_resolver_factory,
// If the P2PTransportChannel has to delete the DNS resolver factory
// on release, this pointer is set.
std::unique_ptr<webrtc::AsyncDnsResolverFactoryInterface>
owned_dns_resolver_factory,
webrtc::RtcEventLog* event_log = nullptr,
IceControllerFactoryInterface* ice_controller_factory = nullptr);
bool IsGettingPorts() { bool IsGettingPorts() {
RTC_DCHECK_RUN_ON(network_thread_); RTC_DCHECK_RUN_ON(network_thread_);
return allocator_session()->IsGettingPorts(); return allocator_session()->IsGettingPorts();
@ -363,8 +403,10 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal {
std::string transport_name_ RTC_GUARDED_BY(network_thread_); std::string transport_name_ RTC_GUARDED_BY(network_thread_);
int component_ RTC_GUARDED_BY(network_thread_); int component_ RTC_GUARDED_BY(network_thread_);
PortAllocator* allocator_ RTC_GUARDED_BY(network_thread_); PortAllocator* allocator_ RTC_GUARDED_BY(network_thread_);
webrtc::AsyncResolverFactory* async_resolver_factory_ webrtc::AsyncDnsResolverFactoryInterface* const async_dns_resolver_factory_
RTC_GUARDED_BY(network_thread_); RTC_GUARDED_BY(network_thread_);
const std::unique_ptr<webrtc::AsyncDnsResolverFactoryInterface>
owned_dns_resolver_factory_;
rtc::Thread* const network_thread_; rtc::Thread* const network_thread_;
bool incoming_only_ RTC_GUARDED_BY(network_thread_); bool incoming_only_ RTC_GUARDED_BY(network_thread_);
int error_ RTC_GUARDED_BY(network_thread_); int error_ RTC_GUARDED_BY(network_thread_);
@ -426,17 +468,23 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal {
RTC_GUARDED_BY(network_thread_); RTC_GUARDED_BY(network_thread_);
struct CandidateAndResolver final { struct CandidateAndResolver final {
CandidateAndResolver(const Candidate& candidate, CandidateAndResolver(
rtc::AsyncResolverInterface* resolver); const Candidate& candidate,
std::unique_ptr<webrtc::AsyncDnsResolverInterface>&& resolver);
~CandidateAndResolver(); ~CandidateAndResolver();
// Moveable, but not copyable.
CandidateAndResolver(CandidateAndResolver&&) = default;
CandidateAndResolver& operator=(CandidateAndResolver&&) = default;
Candidate candidate_; Candidate candidate_;
rtc::AsyncResolverInterface* resolver_; std::unique_ptr<webrtc::AsyncDnsResolverInterface> resolver_;
}; };
std::vector<CandidateAndResolver> resolvers_ RTC_GUARDED_BY(network_thread_); std::vector<CandidateAndResolver> resolvers_ RTC_GUARDED_BY(network_thread_);
void FinishAddingRemoteCandidate(const Candidate& new_remote_candidate); void FinishAddingRemoteCandidate(const Candidate& new_remote_candidate);
void OnCandidateResolved(rtc::AsyncResolverInterface* resolver); void OnCandidateResolved(webrtc::AsyncDnsResolverInterface* resolver);
void AddRemoteCandidateWithResolver(Candidate candidate, void AddRemoteCandidateWithResult(
rtc::AsyncResolverInterface* resolver); Candidate candidate,
const webrtc::AsyncDnsResolverResult& result);
// Number of times the selected_connection_ has been modified. // Number of times the selected_connection_ has been modified.
uint32_t selected_candidate_pair_changes_ = 0; uint32_t selected_candidate_pair_changes_ = 0;

View file

@ -14,6 +14,7 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
#include "api/test/mock_async_dns_resolver.h"
#include "p2p/base/basic_ice_controller.h" #include "p2p/base/basic_ice_controller.h"
#include "p2p/base/connection.h" #include "p2p/base/connection.h"
#include "p2p/base/fake_port_allocator.h" #include "p2p/base/fake_port_allocator.h"
@ -51,9 +52,12 @@ using ::testing::Assign;
using ::testing::Contains; using ::testing::Contains;
using ::testing::DoAll; using ::testing::DoAll;
using ::testing::InSequence; using ::testing::InSequence;
using ::testing::InvokeArgument;
using ::testing::InvokeWithoutArgs; using ::testing::InvokeWithoutArgs;
using ::testing::NiceMock; using ::testing::NiceMock;
using ::testing::Return; using ::testing::Return;
using ::testing::ReturnRef;
using ::testing::SaveArg;
using ::testing::SetArgPointee; using ::testing::SetArgPointee;
using ::testing::SizeIs; using ::testing::SizeIs;
@ -187,6 +191,51 @@ class MockIceControllerFactory : public cricket::IceControllerFactoryInterface {
MOCK_METHOD(void, RecordIceControllerCreated, ()); MOCK_METHOD(void, RecordIceControllerCreated, ());
}; };
// An one-shot resolver factory with default return arguments.
// Resolution is immediate, always succeeds, and returns nonsense.
class ResolverFactoryFixture : public webrtc::MockAsyncDnsResolverFactory {
public:
ResolverFactoryFixture() {
mock_async_dns_resolver_ = std::make_unique<webrtc::MockAsyncDnsResolver>();
ON_CALL(*mock_async_dns_resolver_, Start(_, _))
.WillByDefault(InvokeArgument<1>());
EXPECT_CALL(*mock_async_dns_resolver_, result())
.WillOnce(ReturnRef(mock_async_dns_resolver_result_));
// A default action for GetResolvedAddress. Will be overruled
// by SetAddressToReturn.
ON_CALL(mock_async_dns_resolver_result_, GetResolvedAddress(_, _))
.WillByDefault(Return(true));
EXPECT_CALL(mock_async_dns_resolver_result_, GetError())
.WillOnce(Return(0));
EXPECT_CALL(*this, Create()).WillOnce([this]() {
return std::move(mock_async_dns_resolver_);
});
}
void SetAddressToReturn(rtc::SocketAddress address_to_return) {
EXPECT_CALL(mock_async_dns_resolver_result_, GetResolvedAddress(_, _))
.WillOnce(DoAll(SetArgPointee<1>(address_to_return), Return(true)));
}
void DelayResolution() {
// This function must be called before Create().
ASSERT_TRUE(!!mock_async_dns_resolver_);
EXPECT_CALL(*mock_async_dns_resolver_, Start(_, _))
.WillOnce(SaveArg<1>(&saved_callback_));
}
void FireDelayedResolution() {
// This function must be called after Create().
ASSERT_TRUE(saved_callback_);
saved_callback_();
}
private:
std::unique_ptr<webrtc::MockAsyncDnsResolver> mock_async_dns_resolver_;
webrtc::MockAsyncDnsResolverResult mock_async_dns_resolver_result_;
std::function<void()> saved_callback_;
};
} // namespace } // namespace
namespace cricket { namespace cricket {
@ -345,7 +394,7 @@ class P2PTransportChannelTestBase : public ::testing::Test,
rtc::FakeNetworkManager network_manager_; rtc::FakeNetworkManager network_manager_;
std::unique_ptr<BasicPortAllocator> allocator_; std::unique_ptr<BasicPortAllocator> allocator_;
webrtc::AsyncResolverFactory* async_resolver_factory_; webrtc::AsyncDnsResolverFactoryInterface* async_dns_resolver_factory_;
ChannelData cd1_; ChannelData cd1_;
ChannelData cd2_; ChannelData cd2_;
IceRole role_; IceRole role_;
@ -378,10 +427,10 @@ class P2PTransportChannelTestBase : public ::testing::Test,
IceParamsWithRenomination(kIceParams[0], renomination); IceParamsWithRenomination(kIceParams[0], renomination);
IceParameters ice_ep2_cd1_ch = IceParameters ice_ep2_cd1_ch =
IceParamsWithRenomination(kIceParams[1], renomination); IceParamsWithRenomination(kIceParams[1], renomination);
ep1_.cd1_.ch_.reset(CreateChannel(0, ICE_CANDIDATE_COMPONENT_DEFAULT, ep1_.cd1_.ch_ = CreateChannel(0, ICE_CANDIDATE_COMPONENT_DEFAULT,
ice_ep1_cd1_ch, ice_ep2_cd1_ch)); ice_ep1_cd1_ch, ice_ep2_cd1_ch);
ep2_.cd1_.ch_.reset(CreateChannel(1, ICE_CANDIDATE_COMPONENT_DEFAULT, ep2_.cd1_.ch_ = CreateChannel(1, ICE_CANDIDATE_COMPONENT_DEFAULT,
ice_ep2_cd1_ch, ice_ep1_cd1_ch)); ice_ep2_cd1_ch, ice_ep1_cd1_ch);
ep1_.cd1_.ch_->SetIceConfig(ep1_config); ep1_.cd1_.ch_->SetIceConfig(ep1_config);
ep2_.cd1_.ch_->SetIceConfig(ep2_config); ep2_.cd1_.ch_->SetIceConfig(ep2_config);
ep1_.cd1_.ch_->MaybeStartGathering(); ep1_.cd1_.ch_->MaybeStartGathering();
@ -397,13 +446,14 @@ class P2PTransportChannelTestBase : public ::testing::Test,
CreateChannels(default_config, default_config, false); CreateChannels(default_config, default_config, false);
} }
P2PTransportChannel* CreateChannel(int endpoint, std::unique_ptr<P2PTransportChannel> CreateChannel(
int endpoint,
int component, int component,
const IceParameters& local_ice, const IceParameters& local_ice,
const IceParameters& remote_ice) { const IceParameters& remote_ice) {
P2PTransportChannel* channel = new P2PTransportChannel( auto channel = P2PTransportChannel::Create(
"test content name", component, GetAllocator(endpoint), "test content name", component, GetAllocator(endpoint),
GetEndpoint(endpoint)->async_resolver_factory_); GetEndpoint(endpoint)->async_dns_resolver_factory_);
channel->SignalReadyToSend.connect( channel->SignalReadyToSend.connect(
this, &P2PTransportChannelTestBase::OnReadyToSend); this, &P2PTransportChannelTestBase::OnReadyToSend);
channel->SignalCandidateGathered.connect( channel->SignalCandidateGathered.connect(
@ -2079,8 +2129,8 @@ TEST_F(P2PTransportChannelTest, TurnToTurnPresumedWritable) {
kDefaultPortAllocatorFlags); kDefaultPortAllocatorFlags);
// Only configure one channel so we can control when the remote candidate // Only configure one channel so we can control when the remote candidate
// is added. // is added.
GetEndpoint(0)->cd1_.ch_.reset(CreateChannel( GetEndpoint(0)->cd1_.ch_ = CreateChannel(0, ICE_CANDIDATE_COMPONENT_DEFAULT,
0, ICE_CANDIDATE_COMPONENT_DEFAULT, kIceParams[0], kIceParams[1])); kIceParams[0], kIceParams[1]);
IceConfig config; IceConfig config;
config.presume_writable_when_fully_relayed = true; config.presume_writable_when_fully_relayed = true;
ep1_ch1()->SetIceConfig(config); ep1_ch1()->SetIceConfig(config);
@ -2128,10 +2178,10 @@ TEST_F(P2PTransportChannelTest, TurnToPrflxPresumedWritable) {
test_turn_server()->set_enable_permission_checks(false); test_turn_server()->set_enable_permission_checks(false);
IceConfig config; IceConfig config;
config.presume_writable_when_fully_relayed = true; config.presume_writable_when_fully_relayed = true;
GetEndpoint(0)->cd1_.ch_.reset(CreateChannel( GetEndpoint(0)->cd1_.ch_ = CreateChannel(0, ICE_CANDIDATE_COMPONENT_DEFAULT,
0, ICE_CANDIDATE_COMPONENT_DEFAULT, kIceParams[0], kIceParams[1])); kIceParams[0], kIceParams[1]);
GetEndpoint(1)->cd1_.ch_.reset(CreateChannel( GetEndpoint(1)->cd1_.ch_ = CreateChannel(1, ICE_CANDIDATE_COMPONENT_DEFAULT,
1, ICE_CANDIDATE_COMPONENT_DEFAULT, kIceParams[1], kIceParams[0])); kIceParams[1], kIceParams[0]);
ep1_ch1()->SetIceConfig(config); ep1_ch1()->SetIceConfig(config);
ep2_ch1()->SetIceConfig(config); ep2_ch1()->SetIceConfig(config);
// Don't signal candidates from channel 2, so that channel 1 sees the TURN // Don't signal candidates from channel 2, so that channel 1 sees the TURN
@ -2167,10 +2217,10 @@ TEST_F(P2PTransportChannelTest, PresumedWritablePreferredOverUnreliable) {
kDefaultPortAllocatorFlags); kDefaultPortAllocatorFlags);
IceConfig config; IceConfig config;
config.presume_writable_when_fully_relayed = true; config.presume_writable_when_fully_relayed = true;
GetEndpoint(0)->cd1_.ch_.reset(CreateChannel( GetEndpoint(0)->cd1_.ch_ = CreateChannel(0, ICE_CANDIDATE_COMPONENT_DEFAULT,
0, ICE_CANDIDATE_COMPONENT_DEFAULT, kIceParams[0], kIceParams[1])); kIceParams[0], kIceParams[1]);
GetEndpoint(1)->cd1_.ch_.reset(CreateChannel( GetEndpoint(1)->cd1_.ch_ = CreateChannel(1, ICE_CANDIDATE_COMPONENT_DEFAULT,
1, ICE_CANDIDATE_COMPONENT_DEFAULT, kIceParams[1], kIceParams[0])); kIceParams[1], kIceParams[0]);
ep1_ch1()->SetIceConfig(config); ep1_ch1()->SetIceConfig(config);
ep2_ch1()->SetIceConfig(config); ep2_ch1()->SetIceConfig(config);
ep1_ch1()->MaybeStartGathering(); ep1_ch1()->MaybeStartGathering();
@ -2205,8 +2255,8 @@ TEST_F(P2PTransportChannelTest, SignalReadyToSendWithPresumedWritable) {
kDefaultPortAllocatorFlags); kDefaultPortAllocatorFlags);
// Only test one endpoint, so we can ensure the connection doesn't receive a // Only test one endpoint, so we can ensure the connection doesn't receive a
// binding response and advance beyond being "presumed" writable. // binding response and advance beyond being "presumed" writable.
GetEndpoint(0)->cd1_.ch_.reset(CreateChannel( GetEndpoint(0)->cd1_.ch_ = CreateChannel(0, ICE_CANDIDATE_COMPONENT_DEFAULT,
0, ICE_CANDIDATE_COMPONENT_DEFAULT, kIceParams[0], kIceParams[1])); kIceParams[0], kIceParams[1]);
IceConfig config; IceConfig config;
config.presume_writable_when_fully_relayed = true; config.presume_writable_when_fully_relayed = true;
ep1_ch1()->SetIceConfig(config); ep1_ch1()->SetIceConfig(config);
@ -2258,10 +2308,10 @@ TEST_F(P2PTransportChannelTest,
// to configure the server to accept packets from an address we haven't // to configure the server to accept packets from an address we haven't
// explicitly installed permission for. // explicitly installed permission for.
test_turn_server()->set_enable_permission_checks(false); test_turn_server()->set_enable_permission_checks(false);
GetEndpoint(0)->cd1_.ch_.reset(CreateChannel( GetEndpoint(0)->cd1_.ch_ = CreateChannel(0, ICE_CANDIDATE_COMPONENT_DEFAULT,
0, ICE_CANDIDATE_COMPONENT_DEFAULT, kIceParams[0], kIceParams[1])); kIceParams[0], kIceParams[1]);
GetEndpoint(1)->cd1_.ch_.reset(CreateChannel( GetEndpoint(1)->cd1_.ch_ = CreateChannel(1, ICE_CANDIDATE_COMPONENT_DEFAULT,
1, ICE_CANDIDATE_COMPONENT_DEFAULT, kIceParams[1], kIceParams[0])); kIceParams[1], kIceParams[0]);
// Don't signal candidates from channel 2, so that channel 1 sees the TURN // Don't signal candidates from channel 2, so that channel 1 sees the TURN
// candidate as peer reflexive. // candidate as peer reflexive.
PauseCandidates(1); PauseCandidates(1);
@ -4834,31 +4884,18 @@ TEST_F(P2PTransportChannelMostLikelyToWorkFirstTest, TestTcpTurn) {
// when the address is a hostname. The destruction should happen even // when the address is a hostname. The destruction should happen even
// if the channel is not destroyed. // if the channel is not destroyed.
TEST(P2PTransportChannelResolverTest, HostnameCandidateIsResolved) { TEST(P2PTransportChannelResolverTest, HostnameCandidateIsResolved) {
rtc::MockAsyncResolver mock_async_resolver; ResolverFactoryFixture resolver_fixture;
EXPECT_CALL(mock_async_resolver, GetError()).WillOnce(Return(0));
EXPECT_CALL(mock_async_resolver, GetResolvedAddress(_, _))
.WillOnce(Return(true));
// Destroy is called asynchronously after the address is resolved,
// so we need a variable to wait on.
bool destroy_called = false;
EXPECT_CALL(mock_async_resolver, Destroy(_))
.WillOnce(Assign(&destroy_called, true));
webrtc::MockAsyncResolverFactory mock_async_resolver_factory;
EXPECT_CALL(mock_async_resolver_factory, Create())
.WillOnce(Return(&mock_async_resolver));
FakePortAllocator allocator(rtc::Thread::Current(), nullptr); FakePortAllocator allocator(rtc::Thread::Current(), nullptr);
P2PTransportChannel channel("tn", 0, &allocator, auto channel =
&mock_async_resolver_factory); P2PTransportChannel::Create("tn", 0, &allocator, &resolver_fixture);
Candidate hostname_candidate; Candidate hostname_candidate;
SocketAddress hostname_address("fake.test", 1000); SocketAddress hostname_address("fake.test", 1000);
hostname_candidate.set_address(hostname_address); hostname_candidate.set_address(hostname_address);
channel.AddRemoteCandidate(hostname_candidate); channel->AddRemoteCandidate(hostname_candidate);
ASSERT_EQ_WAIT(1u, channel.remote_candidates().size(), kDefaultTimeout); ASSERT_EQ_WAIT(1u, channel->remote_candidates().size(), kDefaultTimeout);
const RemoteCandidate& candidate = channel.remote_candidates()[0]; const RemoteCandidate& candidate = channel->remote_candidates()[0];
EXPECT_FALSE(candidate.address().IsUnresolvedIP()); EXPECT_FALSE(candidate.address().IsUnresolvedIP());
WAIT(destroy_called, kShortTimeout);
} }
// Test that if we signal a hostname candidate after the remote endpoint // Test that if we signal a hostname candidate after the remote endpoint
@ -4867,11 +4904,6 @@ TEST(P2PTransportChannelResolverTest, HostnameCandidateIsResolved) {
// done. // done.
TEST_F(P2PTransportChannelTest, TEST_F(P2PTransportChannelTest,
PeerReflexiveCandidateBeforeSignalingWithMdnsName) { PeerReflexiveCandidateBeforeSignalingWithMdnsName) {
rtc::MockAsyncResolver mock_async_resolver;
webrtc::MockAsyncResolverFactory mock_async_resolver_factory;
EXPECT_CALL(mock_async_resolver_factory, Create())
.WillOnce(Return(&mock_async_resolver));
// ep1 and ep2 will only gather host candidates with addresses // ep1 and ep2 will only gather host candidates with addresses
// kPublicAddrs[0] and kPublicAddrs[1], respectively. // kPublicAddrs[0] and kPublicAddrs[1], respectively.
ConfigureEndpoints(OPEN, OPEN, kOnlyLocalPorts, kOnlyLocalPorts); ConfigureEndpoints(OPEN, OPEN, kOnlyLocalPorts, kOnlyLocalPorts);
@ -4879,7 +4911,9 @@ TEST_F(P2PTransportChannelTest,
set_remote_ice_parameter_source(FROM_SETICEPARAMETERS); set_remote_ice_parameter_source(FROM_SETICEPARAMETERS);
GetEndpoint(0)->network_manager_.set_mdns_responder( GetEndpoint(0)->network_manager_.set_mdns_responder(
std::make_unique<webrtc::FakeMdnsResponder>(rtc::Thread::Current())); std::make_unique<webrtc::FakeMdnsResponder>(rtc::Thread::Current()));
GetEndpoint(1)->async_resolver_factory_ = &mock_async_resolver_factory;
ResolverFactoryFixture resolver_fixture;
GetEndpoint(1)->async_dns_resolver_factory_ = &resolver_fixture;
CreateChannels(); CreateChannels();
// Pause sending candidates from both endpoints until we find out what port // Pause sending candidates from both endpoints until we find out what port
// number is assgined to ep1's host candidate. // number is assgined to ep1's host candidate.
@ -4894,6 +4928,7 @@ TEST_F(P2PTransportChannelTest,
// This is the underlying private IP address of the same candidate at ep1. // This is the underlying private IP address of the same candidate at ep1.
const auto local_address = rtc::SocketAddress( const auto local_address = rtc::SocketAddress(
kPublicAddrs[0].ipaddr(), local_candidate.address().port()); kPublicAddrs[0].ipaddr(), local_candidate.address().port());
// Let ep2 signal its candidate to ep1. ep1 should form a candidate // Let ep2 signal its candidate to ep1. ep1 should form a candidate
// pair and start to ping. After receiving the ping, ep2 discovers a prflx // pair and start to ping. After receiving the ping, ep2 discovers a prflx
// remote candidate and form a candidate pair as well. // remote candidate and form a candidate pair as well.
@ -4909,19 +4944,7 @@ TEST_F(P2PTransportChannelTest,
EXPECT_EQ(kIceUfrag[0], selected_connection->remote_candidate().username()); EXPECT_EQ(kIceUfrag[0], selected_connection->remote_candidate().username());
EXPECT_EQ(kIcePwd[0], selected_connection->remote_candidate().password()); EXPECT_EQ(kIcePwd[0], selected_connection->remote_candidate().password());
// Set expectation before ep1 signals a hostname candidate. // Set expectation before ep1 signals a hostname candidate.
{ resolver_fixture.SetAddressToReturn(local_address);
InSequence sequencer;
EXPECT_CALL(mock_async_resolver, Start(_));
EXPECT_CALL(mock_async_resolver, GetError()).WillOnce(Return(0));
// Let the mock resolver of ep2 receives the correct resolution.
EXPECT_CALL(mock_async_resolver, GetResolvedAddress(_, _))
.WillOnce(DoAll(SetArgPointee<1>(local_address), Return(true)));
}
// Destroy is called asynchronously after the address is resolved,
// so we need a variable to wait on.
bool destroy_called = false;
EXPECT_CALL(mock_async_resolver, Destroy(_))
.WillOnce(Assign(&destroy_called, true));
ResumeCandidates(0); ResumeCandidates(0);
// Verify ep2's selected connection is updated to use the 'local' candidate. // Verify ep2's selected connection is updated to use the 'local' candidate.
EXPECT_EQ_WAIT(LOCAL_PORT_TYPE, EXPECT_EQ_WAIT(LOCAL_PORT_TYPE,
@ -4929,7 +4952,6 @@ TEST_F(P2PTransportChannelTest,
kMediumTimeout); kMediumTimeout);
EXPECT_EQ(selected_connection, ep2_ch1()->selected_connection()); EXPECT_EQ(selected_connection, ep2_ch1()->selected_connection());
WAIT(destroy_called, kShortTimeout);
DestroyChannels(); DestroyChannels();
} }
@ -4939,13 +4961,9 @@ TEST_F(P2PTransportChannelTest,
// address after the resolution completes. // address after the resolution completes.
TEST_F(P2PTransportChannelTest, TEST_F(P2PTransportChannelTest,
PeerReflexiveCandidateDuringResolvingHostCandidateWithMdnsName) { PeerReflexiveCandidateDuringResolvingHostCandidateWithMdnsName) {
auto mock_async_resolver = new NiceMock<rtc::MockAsyncResolver>(); ResolverFactoryFixture resolver_fixture;
ON_CALL(*mock_async_resolver, Destroy).WillByDefault([mock_async_resolver] { // Prevent resolution until triggered by FireDelayedResolution.
delete mock_async_resolver; resolver_fixture.DelayResolution();
});
webrtc::MockAsyncResolverFactory mock_async_resolver_factory;
EXPECT_CALL(mock_async_resolver_factory, Create())
.WillOnce(Return(mock_async_resolver));
// ep1 and ep2 will only gather host candidates with addresses // ep1 and ep2 will only gather host candidates with addresses
// kPublicAddrs[0] and kPublicAddrs[1], respectively. // kPublicAddrs[0] and kPublicAddrs[1], respectively.
@ -4954,12 +4972,13 @@ TEST_F(P2PTransportChannelTest,
set_remote_ice_parameter_source(FROM_SETICEPARAMETERS); set_remote_ice_parameter_source(FROM_SETICEPARAMETERS);
GetEndpoint(0)->network_manager_.set_mdns_responder( GetEndpoint(0)->network_manager_.set_mdns_responder(
std::make_unique<webrtc::FakeMdnsResponder>(rtc::Thread::Current())); std::make_unique<webrtc::FakeMdnsResponder>(rtc::Thread::Current()));
GetEndpoint(1)->async_resolver_factory_ = &mock_async_resolver_factory; GetEndpoint(1)->async_dns_resolver_factory_ = &resolver_fixture;
CreateChannels(); CreateChannels();
// Pause sending candidates from both endpoints until we find out what port // Pause sending candidates from both endpoints until we find out what port
// number is assgined to ep1's host candidate. // number is assgined to ep1's host candidate.
PauseCandidates(0); PauseCandidates(0);
PauseCandidates(1); PauseCandidates(1);
ASSERT_EQ_WAIT(1u, GetEndpoint(0)->saved_candidates_.size(), kMediumTimeout); ASSERT_EQ_WAIT(1u, GetEndpoint(0)->saved_candidates_.size(), kMediumTimeout);
ASSERT_EQ(1u, GetEndpoint(0)->saved_candidates_[0]->candidates.size()); ASSERT_EQ(1u, GetEndpoint(0)->saved_candidates_[0]->candidates.size());
const auto& local_candidate = const auto& local_candidate =
@ -4969,24 +4988,16 @@ TEST_F(P2PTransportChannelTest,
// This is the underlying private IP address of the same candidate at ep1. // This is the underlying private IP address of the same candidate at ep1.
const auto local_address = rtc::SocketAddress( const auto local_address = rtc::SocketAddress(
kPublicAddrs[0].ipaddr(), local_candidate.address().port()); kPublicAddrs[0].ipaddr(), local_candidate.address().port());
bool mock_async_resolver_started = false;
// Not signaling done yet, and only make sure we are in the process of
// resolution.
EXPECT_CALL(*mock_async_resolver, Start(_))
.WillOnce(InvokeWithoutArgs([&mock_async_resolver_started]() {
mock_async_resolver_started = true;
}));
// Let ep1 signal its hostname candidate to ep2. // Let ep1 signal its hostname candidate to ep2.
ResumeCandidates(0); ResumeCandidates(0);
ASSERT_TRUE_WAIT(mock_async_resolver_started, kMediumTimeout);
// Now that ep2 is in the process of resolving the hostname candidate signaled // Now that ep2 is in the process of resolving the hostname candidate signaled
// by ep1. Let ep2 signal its host candidate with an IP address to ep1, so // by ep1. Let ep2 signal its host candidate with an IP address to ep1, so
// that ep1 can form a candidate pair, select it and start to ping ep2. // that ep1 can form a candidate pair, select it and start to ping ep2.
ResumeCandidates(1); ResumeCandidates(1);
ASSERT_TRUE_WAIT(ep1_ch1()->selected_connection() != nullptr, kMediumTimeout); ASSERT_TRUE_WAIT(ep1_ch1()->selected_connection() != nullptr, kMediumTimeout);
// Let the mock resolver of ep2 receives the correct resolution. // Let the mock resolver of ep2 receives the correct resolution.
EXPECT_CALL(*mock_async_resolver, GetResolvedAddress(_, _)) resolver_fixture.SetAddressToReturn(local_address);
.WillOnce(DoAll(SetArgPointee<1>(local_address), Return(true)));
// Upon receiving a ping from ep1, ep2 adds a prflx candidate from the // Upon receiving a ping from ep1, ep2 adds a prflx candidate from the
// unknown address and establishes a connection. // unknown address and establishes a connection.
// //
@ -4997,7 +5008,9 @@ TEST_F(P2PTransportChannelTest,
ep2_ch1()->selected_connection()->remote_candidate().type()); ep2_ch1()->selected_connection()->remote_candidate().type());
// ep2 should also be able resolve the hostname candidate. The resolved remote // ep2 should also be able resolve the hostname candidate. The resolved remote
// host candidate should be merged with the prflx remote candidate. // host candidate should be merged with the prflx remote candidate.
mock_async_resolver->SignalDone(mock_async_resolver);
resolver_fixture.FireDelayedResolution();
EXPECT_EQ_WAIT(LOCAL_PORT_TYPE, EXPECT_EQ_WAIT(LOCAL_PORT_TYPE,
ep2_ch1()->selected_connection()->remote_candidate().type(), ep2_ch1()->selected_connection()->remote_candidate().type(),
kMediumTimeout); kMediumTimeout);
@ -5010,10 +5023,7 @@ TEST_F(P2PTransportChannelTest,
// which is obfuscated by an mDNS name, and if the peer can complete the name // which is obfuscated by an mDNS name, and if the peer can complete the name
// resolution with the correct IP address, we can have a p2p connection. // resolution with the correct IP address, we can have a p2p connection.
TEST_F(P2PTransportChannelTest, CanConnectWithHostCandidateWithMdnsName) { TEST_F(P2PTransportChannelTest, CanConnectWithHostCandidateWithMdnsName) {
NiceMock<rtc::MockAsyncResolver> mock_async_resolver; ResolverFactoryFixture resolver_fixture;
webrtc::MockAsyncResolverFactory mock_async_resolver_factory;
EXPECT_CALL(mock_async_resolver_factory, Create())
.WillOnce(Return(&mock_async_resolver));
// ep1 and ep2 will only gather host candidates with addresses // ep1 and ep2 will only gather host candidates with addresses
// kPublicAddrs[0] and kPublicAddrs[1], respectively. // kPublicAddrs[0] and kPublicAddrs[1], respectively.
@ -5022,7 +5032,7 @@ TEST_F(P2PTransportChannelTest, CanConnectWithHostCandidateWithMdnsName) {
set_remote_ice_parameter_source(FROM_SETICEPARAMETERS); set_remote_ice_parameter_source(FROM_SETICEPARAMETERS);
GetEndpoint(0)->network_manager_.set_mdns_responder( GetEndpoint(0)->network_manager_.set_mdns_responder(
std::make_unique<webrtc::FakeMdnsResponder>(rtc::Thread::Current())); std::make_unique<webrtc::FakeMdnsResponder>(rtc::Thread::Current()));
GetEndpoint(1)->async_resolver_factory_ = &mock_async_resolver_factory; GetEndpoint(1)->async_dns_resolver_factory_ = &resolver_fixture;
CreateChannels(); CreateChannels();
// Pause sending candidates from both endpoints until we find out what port // Pause sending candidates from both endpoints until we find out what port
// number is assgined to ep1's host candidate. // number is assgined to ep1's host candidate.
@ -5039,8 +5049,7 @@ TEST_F(P2PTransportChannelTest, CanConnectWithHostCandidateWithMdnsName) {
rtc::SocketAddress resolved_address_ep1(local_candidate_ep1.address()); rtc::SocketAddress resolved_address_ep1(local_candidate_ep1.address());
resolved_address_ep1.SetResolvedIP(kPublicAddrs[0].ipaddr()); resolved_address_ep1.SetResolvedIP(kPublicAddrs[0].ipaddr());
EXPECT_CALL(mock_async_resolver, GetResolvedAddress(_, _)) resolver_fixture.SetAddressToReturn(resolved_address_ep1);
.WillOnce(DoAll(SetArgPointee<1>(resolved_address_ep1), Return(true)));
// Let ep1 signal its hostname candidate to ep2. // Let ep1 signal its hostname candidate to ep2.
ResumeCandidates(0); ResumeCandidates(0);
@ -5064,10 +5073,7 @@ TEST_F(P2PTransportChannelTest, CanConnectWithHostCandidateWithMdnsName) {
// this remote host candidate in stats. // this remote host candidate in stats.
TEST_F(P2PTransportChannelTest, TEST_F(P2PTransportChannelTest,
CandidatesSanitizedInStatsWhenMdnsObfuscationEnabled) { CandidatesSanitizedInStatsWhenMdnsObfuscationEnabled) {
NiceMock<rtc::MockAsyncResolver> mock_async_resolver; ResolverFactoryFixture resolver_fixture;
webrtc::MockAsyncResolverFactory mock_async_resolver_factory;
EXPECT_CALL(mock_async_resolver_factory, Create())
.WillOnce(Return(&mock_async_resolver));
// ep1 and ep2 will gather host candidates with addresses // ep1 and ep2 will gather host candidates with addresses
// kPublicAddrs[0] and kPublicAddrs[1], respectively. ep1 also gathers a srflx // kPublicAddrs[0] and kPublicAddrs[1], respectively. ep1 also gathers a srflx
@ -5079,7 +5085,7 @@ TEST_F(P2PTransportChannelTest,
set_remote_ice_parameter_source(FROM_SETICEPARAMETERS); set_remote_ice_parameter_source(FROM_SETICEPARAMETERS);
GetEndpoint(0)->network_manager_.set_mdns_responder( GetEndpoint(0)->network_manager_.set_mdns_responder(
std::make_unique<webrtc::FakeMdnsResponder>(rtc::Thread::Current())); std::make_unique<webrtc::FakeMdnsResponder>(rtc::Thread::Current()));
GetEndpoint(1)->async_resolver_factory_ = &mock_async_resolver_factory; GetEndpoint(1)->async_dns_resolver_factory_ = &resolver_fixture;
CreateChannels(); CreateChannels();
// Pause sending candidates from both endpoints until we find out what port // Pause sending candidates from both endpoints until we find out what port
// number is assigned to ep1's host candidate. // number is assigned to ep1's host candidate.
@ -5097,9 +5103,7 @@ TEST_F(P2PTransportChannelTest,
// and let the mock resolver of ep2 receive the correct resolution. // and let the mock resolver of ep2 receive the correct resolution.
rtc::SocketAddress resolved_address_ep1(local_candidate_ep1.address()); rtc::SocketAddress resolved_address_ep1(local_candidate_ep1.address());
resolved_address_ep1.SetResolvedIP(kPublicAddrs[0].ipaddr()); resolved_address_ep1.SetResolvedIP(kPublicAddrs[0].ipaddr());
EXPECT_CALL(mock_async_resolver, GetResolvedAddress(_, _)) resolver_fixture.SetAddressToReturn(resolved_address_ep1);
.WillOnce(
DoAll(SetArgPointee<1>(resolved_address_ep1), Return(true)));
break; break;
} }
} }
@ -5248,10 +5252,7 @@ TEST_F(P2PTransportChannelTest,
// when it is queried via GetSelectedCandidatePair. // when it is queried via GetSelectedCandidatePair.
TEST_F(P2PTransportChannelTest, TEST_F(P2PTransportChannelTest,
SelectedCandidatePairSanitizedWhenMdnsObfuscationEnabled) { SelectedCandidatePairSanitizedWhenMdnsObfuscationEnabled) {
NiceMock<rtc::MockAsyncResolver> mock_async_resolver; ResolverFactoryFixture resolver_fixture;
webrtc::MockAsyncResolverFactory mock_async_resolver_factory;
EXPECT_CALL(mock_async_resolver_factory, Create())
.WillOnce(Return(&mock_async_resolver));
// ep1 and ep2 will gather host candidates with addresses // ep1 and ep2 will gather host candidates with addresses
// kPublicAddrs[0] and kPublicAddrs[1], respectively. // kPublicAddrs[0] and kPublicAddrs[1], respectively.
@ -5260,7 +5261,7 @@ TEST_F(P2PTransportChannelTest,
set_remote_ice_parameter_source(FROM_SETICEPARAMETERS); set_remote_ice_parameter_source(FROM_SETICEPARAMETERS);
GetEndpoint(0)->network_manager_.set_mdns_responder( GetEndpoint(0)->network_manager_.set_mdns_responder(
std::make_unique<webrtc::FakeMdnsResponder>(rtc::Thread::Current())); std::make_unique<webrtc::FakeMdnsResponder>(rtc::Thread::Current()));
GetEndpoint(1)->async_resolver_factory_ = &mock_async_resolver_factory; GetEndpoint(1)->async_dns_resolver_factory_ = &resolver_fixture;
CreateChannels(); CreateChannels();
// Pause sending candidates from both endpoints until we find out what port // Pause sending candidates from both endpoints until we find out what port
// number is assigned to ep1's host candidate. // number is assigned to ep1's host candidate.
@ -5275,8 +5276,8 @@ TEST_F(P2PTransportChannelTest,
// and let the mock resolver of ep2 receive the correct resolution. // and let the mock resolver of ep2 receive the correct resolution.
rtc::SocketAddress resolved_address_ep1(local_candidate_ep1.address()); rtc::SocketAddress resolved_address_ep1(local_candidate_ep1.address());
resolved_address_ep1.SetResolvedIP(kPublicAddrs[0].ipaddr()); resolved_address_ep1.SetResolvedIP(kPublicAddrs[0].ipaddr());
EXPECT_CALL(mock_async_resolver, GetResolvedAddress(_, _)) resolver_fixture.SetAddressToReturn(resolved_address_ep1);
.WillOnce(DoAll(SetArgPointee<1>(resolved_address_ep1), Return(true)));
ResumeCandidates(0); ResumeCandidates(0);
ResumeCandidates(1); ResumeCandidates(1);
@ -5305,8 +5306,8 @@ TEST_F(P2PTransportChannelTest,
// We use one endpoint to test the behavior of adding remote candidates, and // We use one endpoint to test the behavior of adding remote candidates, and
// this endpoint only gathers relay candidates. // this endpoint only gathers relay candidates.
ConfigureEndpoints(OPEN, OPEN, kOnlyRelayPorts, kDefaultPortAllocatorFlags); ConfigureEndpoints(OPEN, OPEN, kOnlyRelayPorts, kDefaultPortAllocatorFlags);
GetEndpoint(0)->cd1_.ch_.reset(CreateChannel( GetEndpoint(0)->cd1_.ch_ = CreateChannel(0, ICE_CANDIDATE_COMPONENT_DEFAULT,
0, ICE_CANDIDATE_COMPONENT_DEFAULT, kIceParams[0], kIceParams[1])); kIceParams[0], kIceParams[1]);
IceConfig config; IceConfig config;
// Start gathering and we should have only a single relay port. // Start gathering and we should have only a single relay port.
ep1_ch1()->SetIceConfig(config); ep1_ch1()->SetIceConfig(config);
@ -5869,21 +5870,21 @@ class ForgetLearnedStateControllerFactory
TEST_F(P2PTransportChannelPingTest, TestForgetLearnedState) { TEST_F(P2PTransportChannelPingTest, TestForgetLearnedState) {
ForgetLearnedStateControllerFactory factory; ForgetLearnedStateControllerFactory factory;
FakePortAllocator pa(rtc::Thread::Current(), nullptr); FakePortAllocator pa(rtc::Thread::Current(), nullptr);
P2PTransportChannel ch("ping sufficiently", 1, &pa, nullptr, nullptr, auto ch = P2PTransportChannel::Create("ping sufficiently", 1, &pa, nullptr,
&factory); nullptr, &factory);
PrepareChannel(&ch); PrepareChannel(ch.get());
ch.MaybeStartGathering(); ch->MaybeStartGathering();
ch.AddRemoteCandidate(CreateUdpCandidate(LOCAL_PORT_TYPE, "1.1.1.1", 1, 1)); ch->AddRemoteCandidate(CreateUdpCandidate(LOCAL_PORT_TYPE, "1.1.1.1", 1, 1));
ch.AddRemoteCandidate(CreateUdpCandidate(LOCAL_PORT_TYPE, "2.2.2.2", 2, 2)); ch->AddRemoteCandidate(CreateUdpCandidate(LOCAL_PORT_TYPE, "2.2.2.2", 2, 2));
Connection* conn1 = WaitForConnectionTo(&ch, "1.1.1.1", 1); Connection* conn1 = WaitForConnectionTo(ch.get(), "1.1.1.1", 1);
Connection* conn2 = WaitForConnectionTo(&ch, "2.2.2.2", 2); Connection* conn2 = WaitForConnectionTo(ch.get(), "2.2.2.2", 2);
ASSERT_TRUE(conn1 != nullptr); ASSERT_TRUE(conn1 != nullptr);
ASSERT_TRUE(conn2 != nullptr); ASSERT_TRUE(conn2 != nullptr);
// Wait for conn1 to be selected. // Wait for conn1 to be selected.
conn1->ReceivedPingResponse(LOW_RTT, "id"); conn1->ReceivedPingResponse(LOW_RTT, "id");
EXPECT_EQ_WAIT(conn1, ch.selected_connection(), kMediumTimeout); EXPECT_EQ_WAIT(conn1, ch->selected_connection(), kMediumTimeout);
conn2->ReceivedPingResponse(LOW_RTT, "id"); conn2->ReceivedPingResponse(LOW_RTT, "id");
EXPECT_TRUE(conn2->writable()); EXPECT_TRUE(conn2->writable());
@ -5904,23 +5905,23 @@ TEST_F(P2PTransportChannelTest, DisableDnsLookupsWithTransportPolicyRelay) {
auto* ep1 = GetEndpoint(0); auto* ep1 = GetEndpoint(0);
ep1->allocator_->SetCandidateFilter(CF_RELAY); ep1->allocator_->SetCandidateFilter(CF_RELAY);
rtc::MockAsyncResolver mock_async_resolver; std::unique_ptr<webrtc::MockAsyncDnsResolver> mock_async_resolver =
webrtc::MockAsyncResolverFactory mock_async_resolver_factory; std::make_unique<webrtc::MockAsyncDnsResolver>();
ON_CALL(mock_async_resolver_factory, Create()) // This test expects resolution to not be started.
.WillByDefault(Return(&mock_async_resolver)); EXPECT_CALL(*mock_async_resolver, Start(_, _)).Times(0);
ep1->async_resolver_factory_ = &mock_async_resolver_factory;
bool lookup_started = false; webrtc::MockAsyncDnsResolverFactory mock_async_resolver_factory;
ON_CALL(mock_async_resolver, Start(_)) ON_CALL(mock_async_resolver_factory, Create())
.WillByDefault(Assign(&lookup_started, true)); .WillByDefault(
[&mock_async_resolver]() { return std::move(mock_async_resolver); });
ep1->async_dns_resolver_factory_ = &mock_async_resolver_factory;
CreateChannels(); CreateChannels();
ep1_ch1()->AddRemoteCandidate( ep1_ch1()->AddRemoteCandidate(
CreateUdpCandidate(LOCAL_PORT_TYPE, "hostname.test", 1, 100)); CreateUdpCandidate(LOCAL_PORT_TYPE, "hostname.test", 1, 100));
EXPECT_FALSE(lookup_started);
DestroyChannels(); DestroyChannels();
} }
@ -5930,23 +5931,23 @@ TEST_F(P2PTransportChannelTest, DisableDnsLookupsWithTransportPolicyNone) {
auto* ep1 = GetEndpoint(0); auto* ep1 = GetEndpoint(0);
ep1->allocator_->SetCandidateFilter(CF_NONE); ep1->allocator_->SetCandidateFilter(CF_NONE);
rtc::MockAsyncResolver mock_async_resolver; std::unique_ptr<webrtc::MockAsyncDnsResolver> mock_async_resolver =
webrtc::MockAsyncResolverFactory mock_async_resolver_factory; std::make_unique<webrtc::MockAsyncDnsResolver>();
ON_CALL(mock_async_resolver_factory, Create()) // This test expects resolution to not be started.
.WillByDefault(Return(&mock_async_resolver)); EXPECT_CALL(*mock_async_resolver, Start(_, _)).Times(0);
ep1->async_resolver_factory_ = &mock_async_resolver_factory;
bool lookup_started = false; webrtc::MockAsyncDnsResolverFactory mock_async_resolver_factory;
ON_CALL(mock_async_resolver, Start(_)) ON_CALL(mock_async_resolver_factory, Create())
.WillByDefault(Assign(&lookup_started, true)); .WillByDefault(
[&mock_async_resolver]() { return std::move(mock_async_resolver); });
ep1->async_dns_resolver_factory_ = &mock_async_resolver_factory;
CreateChannels(); CreateChannels();
ep1_ch1()->AddRemoteCandidate( ep1_ch1()->AddRemoteCandidate(
CreateUdpCandidate(LOCAL_PORT_TYPE, "hostname.test", 1, 100)); CreateUdpCandidate(LOCAL_PORT_TYPE, "hostname.test", 1, 100));
EXPECT_FALSE(lookup_started);
DestroyChannels(); DestroyChannels();
} }
@ -5956,18 +5957,19 @@ TEST_F(P2PTransportChannelTest, EnableDnsLookupsWithTransportPolicyNoHost) {
auto* ep1 = GetEndpoint(0); auto* ep1 = GetEndpoint(0);
ep1->allocator_->SetCandidateFilter(CF_ALL & ~CF_HOST); ep1->allocator_->SetCandidateFilter(CF_ALL & ~CF_HOST);
rtc::MockAsyncResolver mock_async_resolver; std::unique_ptr<webrtc::MockAsyncDnsResolver> mock_async_resolver =
webrtc::MockAsyncResolverFactory mock_async_resolver_factory; std::make_unique<webrtc::MockAsyncDnsResolver>();
EXPECT_CALL(mock_async_resolver_factory, Create())
.WillOnce(Return(&mock_async_resolver));
EXPECT_CALL(mock_async_resolver, Destroy(_));
ep1->async_resolver_factory_ = &mock_async_resolver_factory;
bool lookup_started = false; bool lookup_started = false;
EXPECT_CALL(mock_async_resolver, Start(_)) EXPECT_CALL(*mock_async_resolver, Start(_, _))
.WillOnce(Assign(&lookup_started, true)); .WillOnce(Assign(&lookup_started, true));
webrtc::MockAsyncDnsResolverFactory mock_async_resolver_factory;
EXPECT_CALL(mock_async_resolver_factory, Create())
.WillOnce(
[&mock_async_resolver]() { return std::move(mock_async_resolver); });
ep1->async_dns_resolver_factory_ = &mock_async_resolver_factory;
CreateChannels(); CreateChannels();
ep1_ch1()->AddRemoteCandidate( ep1_ch1()->AddRemoteCandidate(

View file

@ -77,6 +77,7 @@ rtc_library("rtc_pc_base") {
deps = [ deps = [
":media_protocol_names", ":media_protocol_names",
"../api:array_view", "../api:array_view",
"../api:async_dns_resolver",
"../api:audio_options_api", "../api:audio_options_api",
"../api:call_api", "../api:call_api",
"../api:function_view", "../api:function_view",
@ -236,6 +237,7 @@ rtc_library("peerconnection") {
":video_track", ":video_track",
":video_track_source", ":video_track_source",
"../api:array_view", "../api:array_view",
"../api:async_dns_resolver",
"../api:audio_options_api", "../api:audio_options_api",
"../api:call_api", "../api:call_api",
"../api:callfactory_api", "../api:callfactory_api",

View file

@ -39,11 +39,11 @@ namespace webrtc {
JsepTransportController::JsepTransportController( JsepTransportController::JsepTransportController(
rtc::Thread* network_thread, rtc::Thread* network_thread,
cricket::PortAllocator* port_allocator, cricket::PortAllocator* port_allocator,
AsyncResolverFactory* async_resolver_factory, AsyncDnsResolverFactoryInterface* async_dns_resolver_factory,
Config config) Config config)
: network_thread_(network_thread), : network_thread_(network_thread),
port_allocator_(port_allocator), port_allocator_(port_allocator),
async_resolver_factory_(async_resolver_factory), async_dns_resolver_factory_(async_dns_resolver_factory),
config_(config), config_(config),
active_reset_srtp_params_(config.active_reset_srtp_params) { active_reset_srtp_params_(config.active_reset_srtp_params) {
// The |transport_observer| is assumed to be non-null. // The |transport_observer| is assumed to be non-null.
@ -398,7 +398,7 @@ JsepTransportController::CreateIceTransport(const std::string& transport_name,
IceTransportInit init; IceTransportInit init;
init.set_port_allocator(port_allocator_); init.set_port_allocator(port_allocator_);
init.set_async_resolver_factory(async_resolver_factory_); init.set_async_dns_resolver_factory(async_dns_resolver_factory_);
init.set_event_log(config_.event_log); init.set_event_log(config_.event_log);
return config_.ice_transport_factory->CreateIceTransport( return config_.ice_transport_factory->CreateIceTransport(
transport_name, component, std::move(init)); transport_name, component, std::move(init));

View file

@ -21,7 +21,7 @@
#include <vector> #include <vector>
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include "api/async_resolver_factory.h" #include "api/async_dns_resolver.h"
#include "api/candidate.h" #include "api/candidate.h"
#include "api/crypto/crypto_options.h" #include "api/crypto/crypto_options.h"
#include "api/ice_transport_factory.h" #include "api/ice_transport_factory.h"
@ -140,9 +140,10 @@ class JsepTransportController : public sigslot::has_slots<> {
// All the transport related methods are called on the |network_thread| // All the transport related methods are called on the |network_thread|
// and destruction of the JsepTransportController must occur on the // and destruction of the JsepTransportController must occur on the
// |network_thread|. // |network_thread|.
JsepTransportController(rtc::Thread* network_thread, JsepTransportController(
rtc::Thread* network_thread,
cricket::PortAllocator* port_allocator, cricket::PortAllocator* port_allocator,
AsyncResolverFactory* async_resolver_factory, AsyncDnsResolverFactoryInterface* async_dns_resolver_factory,
Config config); Config config);
virtual ~JsepTransportController(); virtual ~JsepTransportController();
@ -461,7 +462,7 @@ class JsepTransportController : public sigslot::has_slots<> {
rtc::Thread* const network_thread_ = nullptr; rtc::Thread* const network_thread_ = nullptr;
cricket::PortAllocator* const port_allocator_ = nullptr; cricket::PortAllocator* const port_allocator_ = nullptr;
AsyncResolverFactory* const async_resolver_factory_ = nullptr; AsyncDnsResolverFactoryInterface* const async_dns_resolver_factory_ = nullptr;
std::map<std::string, std::unique_ptr<cricket::JsepTransport>> std::map<std::string, std::unique_ptr<cricket::JsepTransport>>
jsep_transports_by_name_ RTC_GUARDED_BY(network_thread_); jsep_transports_by_name_ RTC_GUARDED_BY(network_thread_);

View file

@ -12,6 +12,7 @@
#include <limits.h> #include <limits.h>
#include <stddef.h> #include <stddef.h>
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
#include <set> #include <set>
@ -33,6 +34,7 @@
#include "media/base/rid_description.h" #include "media/base/rid_description.h"
#include "media/base/stream_params.h" #include "media/base/stream_params.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "p2p/base/basic_async_resolver_factory.h"
#include "p2p/base/connection.h" #include "p2p/base/connection.h"
#include "p2p/base/connection_info.h" #include "p2p/base/connection_info.h"
#include "p2p/base/dtls_transport_internal.h" #include "p2p/base/dtls_transport_internal.h"
@ -435,6 +437,30 @@ RTCErrorOr<rtc::scoped_refptr<PeerConnection>> PeerConnection::Create(
bool is_unified_plan = bool is_unified_plan =
configuration.sdp_semantics == SdpSemantics::kUnifiedPlan; configuration.sdp_semantics == SdpSemantics::kUnifiedPlan;
bool dtls_enabled = DtlsEnabled(configuration, options, dependencies); bool dtls_enabled = DtlsEnabled(configuration, options, dependencies);
// Interim code: If an AsyncResolverFactory is given, but not an
// AsyncDnsResolverFactory, wrap it in a WrappingAsyncDnsResolverFactory
// If neither is given, create a WrappingAsyncDnsResolverFactory wrapping
// a BasicAsyncResolver.
// TODO(bugs.webrtc.org/12598): Remove code once all callers pass a
// AsyncDnsResolverFactory.
if (dependencies.async_dns_resolver_factory &&
dependencies.async_resolver_factory) {
RTC_LOG(LS_ERROR)
<< "Attempt to set both old and new type of DNS resolver factory";
return RTCError(RTCErrorType::INVALID_PARAMETER,
"Both old and new type of DNS resolver given");
}
if (dependencies.async_resolver_factory) {
dependencies.async_dns_resolver_factory =
std::make_unique<WrappingAsyncDnsResolverFactory>(
std::move(dependencies.async_resolver_factory));
} else {
dependencies.async_dns_resolver_factory =
std::make_unique<WrappingAsyncDnsResolverFactory>(
std::make_unique<BasicAsyncResolverFactory>());
}
// The PeerConnection constructor consumes some, but not all, dependencies. // The PeerConnection constructor consumes some, but not all, dependencies.
rtc::scoped_refptr<PeerConnection> pc( rtc::scoped_refptr<PeerConnection> pc(
new rtc::RefCountedObject<PeerConnection>( new rtc::RefCountedObject<PeerConnection>(
@ -462,7 +488,8 @@ PeerConnection::PeerConnection(
is_unified_plan_(is_unified_plan), is_unified_plan_(is_unified_plan),
event_log_(std::move(event_log)), event_log_(std::move(event_log)),
event_log_ptr_(event_log_.get()), event_log_ptr_(event_log_.get()),
async_resolver_factory_(std::move(dependencies.async_resolver_factory)), async_dns_resolver_factory_(
std::move(dependencies.async_dns_resolver_factory)),
port_allocator_(std::move(dependencies.allocator)), port_allocator_(std::move(dependencies.allocator)),
ice_transport_factory_(std::move(dependencies.ice_transport_factory)), ice_transport_factory_(std::move(dependencies.ice_transport_factory)),
tls_cert_verifier_(std::move(dependencies.tls_cert_verifier)), tls_cert_verifier_(std::move(dependencies.tls_cert_verifier)),
@ -672,7 +699,7 @@ void PeerConnection::InitializeTransportController_n(
transport_controller_.reset( transport_controller_.reset(
new JsepTransportController(network_thread(), port_allocator_.get(), new JsepTransportController(network_thread(), port_allocator_.get(),
async_resolver_factory_.get(), config)); async_dns_resolver_factory_.get(), config));
transport_controller_->SubscribeIceConnectionState( transport_controller_->SubscribeIceConnectionState(
[this](cricket::IceConnectionState s) { [this](cricket::IceConnectionState s) {

View file

@ -23,6 +23,7 @@
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include "api/adaptation/resource.h" #include "api/adaptation/resource.h"
#include "api/async_dns_resolver.h"
#include "api/async_resolver_factory.h" #include "api/async_resolver_factory.h"
#include "api/audio_options.h" #include "api/audio_options.h"
#include "api/candidate.h" #include "api/candidate.h"
@ -637,11 +638,8 @@ class PeerConnection : public PeerConnectionInternal,
PeerConnectionInterface::RTCConfiguration configuration_ PeerConnectionInterface::RTCConfiguration configuration_
RTC_GUARDED_BY(signaling_thread()); RTC_GUARDED_BY(signaling_thread());
// TODO(zstein): |async_resolver_factory_| can currently be nullptr if it const std::unique_ptr<AsyncDnsResolverFactoryInterface>
// is not injected. It should be required once chromium supplies it. async_dns_resolver_factory_;
// This member variable is only used by JsepTransportController so we should
// consider moving ownership to there.
const std::unique_ptr<AsyncResolverFactory> async_resolver_factory_;
std::unique_ptr<cricket::PortAllocator> std::unique_ptr<cricket::PortAllocator>
port_allocator_; // TODO(bugs.webrtc.org/9987): Accessed on both port_allocator_; // TODO(bugs.webrtc.org/9987): Accessed on both
// signaling and network thread. // signaling and network thread.