diff --git a/api/BUILD.gn b/api/BUILD.gn index 376c83f603..e969fecbb8 100644 --- a/api/BUILD.gn +++ b/api/BUILD.gn @@ -255,6 +255,7 @@ rtc_source_set("packet_socket_factory") { ] deps = [ ":async_dns_resolver", + ":wrapping_async_dns_resolver", "../rtc_base:async_resolver_interface", "../rtc_base:rtc_base", "../rtc_base:socket_address", @@ -271,6 +272,28 @@ rtc_source_set("async_dns_resolver") { ] } +rtc_source_set("wrapping_async_dns_resolver") { + visibility = [ + ":*", + "../p2p:rtc_p2p", + ] + sources = [ + "wrapping_async_dns_resolver.cc", + "wrapping_async_dns_resolver.h", + ] + deps = [ + ":async_dns_resolver", + ":sequence_checker", + "../rtc_base:async_resolver_interface", + "../rtc_base:checks", + "../rtc_base:macromagic", + "../rtc_base:socket_address", + "../rtc_base:threading", + "../rtc_base/third_party/sigslot", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/memory" ] +} + rtc_source_set("scoped_refptr") { visibility = [ "*" ] sources = [ "scoped_refptr.h" ] diff --git a/api/DEPS b/api/DEPS index d201a4413a..cadaaa2a7f 100644 --- a/api/DEPS +++ b/api/DEPS @@ -305,6 +305,14 @@ specific_include_rules = { "+rtc_base/thread_annotations.h", ], + "wrapping_async_dns_resolver\.h": [ + "+rtc_base/async_resolver.h", + "+rtc_base/async_resolver_interface.h", + "+rtc_base/socket_address.h", + "+rtc_base/third_party/sigslot/sigslot.h", + "+rtc_base/thread_annotations.h", + ], + # .cc files in api/ should not be restricted in what they can #include, # so we re-add all the top-level directories here. (That's because .h # files leak their #includes to whoever's #including them, but .cc files diff --git a/api/packet_socket_factory.h b/api/packet_socket_factory.h index 1e9f470357..79f48f230f 100644 --- a/api/packet_socket_factory.h +++ b/api/packet_socket_factory.h @@ -11,9 +11,12 @@ #ifndef API_PACKET_SOCKET_FACTORY_H_ #define API_PACKET_SOCKET_FACTORY_H_ +#include #include #include +#include "api/async_dns_resolver.h" +#include "api/wrapping_async_dns_resolver.h" #include "rtc_base/async_packet_socket.h" #include "rtc_base/proxy_info.h" #include "rtc_base/system/rtc_export.h" @@ -69,7 +72,23 @@ class RTC_EXPORT PacketSocketFactory { const std::string& user_agent, const PacketSocketTcpOptions& tcp_options) = 0; - virtual AsyncResolverInterface* CreateAsyncResolver() = 0; + // The AsyncResolverInterface is deprecated; users are encouraged + // to switch to the AsyncDnsResolverInterface. + // TODO(bugs.webrtc.org/12598): Remove once all downstream users + // are converted. + virtual AsyncResolverInterface* CreateAsyncResolver() { + // Default implementation, so that downstream users can remove this + // immediately after changing to CreateAsyncDnsResolver + RTC_NOTREACHED(); + return nullptr; + } + + virtual std::unique_ptr + CreateAsyncDnsResolver() { + // Default implementation, to aid in transition to AsyncDnsResolverInterface + return std::make_unique( + CreateAsyncResolver()); + } private: PacketSocketFactory(const PacketSocketFactory&) = delete; diff --git a/api/wrapping_async_dns_resolver.cc b/api/wrapping_async_dns_resolver.cc new file mode 100644 index 0000000000..866cb0076d --- /dev/null +++ b/api/wrapping_async_dns_resolver.cc @@ -0,0 +1,31 @@ +/* + * 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. + */ + +#include "api/wrapping_async_dns_resolver.h" + +namespace webrtc { + +bool WrappingAsyncDnsResolverResult::GetResolvedAddress( + int family, + rtc::SocketAddress* addr) const { + if (!owner_->wrapped()) { + return false; + } + return owner_->wrapped()->GetResolvedAddress(family, addr); +} + +int WrappingAsyncDnsResolverResult::GetError() const { + if (!owner_->wrapped()) { + return -1; // FIXME: Find a code that makes sense. + } + return owner_->wrapped()->GetError(); +} + +} // namespace webrtc diff --git a/api/wrapping_async_dns_resolver.h b/api/wrapping_async_dns_resolver.h new file mode 100644 index 0000000000..80da206e75 --- /dev/null +++ b/api/wrapping_async_dns_resolver.h @@ -0,0 +1,117 @@ +/* + * 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_WRAPPING_ASYNC_DNS_RESOLVER_H_ +#define API_WRAPPING_ASYNC_DNS_RESOLVER_H_ + +#include +#include + +#include "absl/memory/memory.h" +#include "api/async_dns_resolver.h" +#include "api/sequence_checker.h" +#include "rtc_base/async_resolver.h" +#include "rtc_base/async_resolver_interface.h" +#include "rtc_base/checks.h" +#include "rtc_base/socket_address.h" +#include "rtc_base/third_party/sigslot/sigslot.h" +#include "rtc_base/thread_annotations.h" + +// This file defines a DNS resolver that wraps an old-style +// AsyncResolver. +// It is part of the conversion to the newer interface, and will go away +// once conversion is finished. +// TODO(bugs.webrtc.org/12598): Delete this API. + +namespace webrtc { + +class WrappingAsyncDnsResolver; + +class RTC_EXPORT WrappingAsyncDnsResolverResult + : public AsyncDnsResolverResult { + public: + explicit WrappingAsyncDnsResolverResult(WrappingAsyncDnsResolver* owner) + : owner_(owner) {} + ~WrappingAsyncDnsResolverResult() {} + + // Note: Inline declaration not possible, since it refers to + // WrappingAsyncDnsResolver. + bool GetResolvedAddress(int family, rtc::SocketAddress* addr) const override; + int GetError() const override; + + private: + WrappingAsyncDnsResolver* const owner_; +}; + +class RTC_EXPORT WrappingAsyncDnsResolver : public AsyncDnsResolverInterface, + public sigslot::has_slots<> { + public: + explicit WrappingAsyncDnsResolver(rtc::AsyncResolverInterface* wrapped) + : wrapped_(absl::WrapUnique(wrapped)), result_(this) {} + + ~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, + std::function callback) override { + RTC_DCHECK_RUN_ON(&sequence_checker_); + RTC_DCHECK_EQ(State::kNotStarted, state_); + state_ = State::kStarted; + callback_ = callback; + wrapped_->SignalDone.connect(this, + &WrappingAsyncDnsResolver::OnResolveResult); + wrapped_->Start(addr); + } + + const AsyncDnsResolverResult& result() const override { + RTC_DCHECK_RUN_ON(&sequence_checker_); + RTC_DCHECK_EQ(State::kResolved, state_); + return result_; + } + + private: + 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) { + RTC_DCHECK_RUN_ON(&sequence_checker_); + RTC_DCHECK(state_ == State::kStarted); + RTC_DCHECK_EQ(ref, wrapped_.get()); + state_ = State::kResolved; + within_resolve_result_ = true; + callback_(); + within_resolve_result_ = false; + } + + // The class variables need to be accessed on a single thread. + SequenceChecker sequence_checker_; + std::function callback_ RTC_GUARDED_BY(sequence_checker_); + std::unique_ptr 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; +}; + +} // namespace webrtc + +#endif // API_WRAPPING_ASYNC_DNS_RESOLVER_H_ diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn index f88569480f..3029e0ac44 100644 --- a/p2p/BUILD.gn +++ b/p2p/BUILD.gn @@ -91,6 +91,7 @@ rtc_library("rtc_p2p") { "../api:rtc_error", "../api:scoped_refptr", "../api:sequence_checker", + "../api:wrapping_async_dns_resolver", "../api/crypto:options", "../api/rtc_event_log", "../api/task_queue", diff --git a/p2p/base/basic_async_resolver_factory.cc b/p2p/base/basic_async_resolver_factory.cc index 7f26a981ee..6824357821 100644 --- a/p2p/base/basic_async_resolver_factory.cc +++ b/p2p/base/basic_async_resolver_factory.cc @@ -15,6 +15,7 @@ #include "absl/memory/memory.h" #include "api/async_dns_resolver.h" +#include "api/wrapping_async_dns_resolver.h" #include "rtc_base/async_resolver.h" #include "rtc_base/logging.h" @@ -24,100 +25,6 @@ rtc::AsyncResolverInterface* BasicAsyncResolverFactory::Create() { return new rtc::AsyncResolver(); } -class WrappingAsyncDnsResolver; - -class WrappingAsyncDnsResolverResult : public AsyncDnsResolverResult { - public: - explicit WrappingAsyncDnsResolverResult(WrappingAsyncDnsResolver* owner) - : owner_(owner) {} - ~WrappingAsyncDnsResolverResult() {} - - // Note: Inline declaration not possible, since it refers to - // WrappingAsyncDnsResolver. - bool GetResolvedAddress(int family, rtc::SocketAddress* addr) const override; - int GetError() const override; - - private: - WrappingAsyncDnsResolver* const owner_; -}; - -class WrappingAsyncDnsResolver : public AsyncDnsResolverInterface, - public sigslot::has_slots<> { - public: - explicit WrappingAsyncDnsResolver(rtc::AsyncResolverInterface* wrapped) - : wrapped_(absl::WrapUnique(wrapped)), result_(this) {} - - ~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, - std::function callback) override { - RTC_DCHECK_RUN_ON(&sequence_checker_); - RTC_DCHECK_EQ(State::kNotStarted, state_); - state_ = State::kStarted; - callback_ = callback; - wrapped_->SignalDone.connect(this, - &WrappingAsyncDnsResolver::OnResolveResult); - wrapped_->Start(addr); - } - - const AsyncDnsResolverResult& result() const override { - RTC_DCHECK_RUN_ON(&sequence_checker_); - RTC_DCHECK_EQ(State::kResolved, state_); - return result_; - } - - private: - 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) { - RTC_DCHECK_RUN_ON(&sequence_checker_); - RTC_DCHECK(state_ == State::kStarted); - RTC_DCHECK_EQ(ref, wrapped_.get()); - state_ = State::kResolved; - within_resolve_result_ = true; - callback_(); - within_resolve_result_ = false; - } - - // The class variables need to be accessed on a single thread. - SequenceChecker sequence_checker_; - std::function callback_ RTC_GUARDED_BY(sequence_checker_); - std::unique_ptr 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( - int family, - rtc::SocketAddress* addr) const { - if (!owner_->wrapped()) { - return false; - } - return owner_->wrapped()->GetResolvedAddress(family, addr); -} - -int WrappingAsyncDnsResolverResult::GetError() const { - if (!owner_->wrapped()) { - return -1; // FIXME: Find a code that makes sense. - } - return owner_->wrapped()->GetError(); -} std::unique_ptr WrappingAsyncDnsResolverFactory::Create() {