Add CreateAsyncDnsResolver to PacketSocketFactory API

This unlocks migration from AsyncResolver to AsyncDnsResolver for
clients that implement PacketSocketFactory.

A default implementation is provided, so that clients that implement
CreateAsyncResolver will still see their name resolution work.

Bug: webrtc:12598
Change-Id: If835cbc753712e9f5b4bd3d5805c7f7d2a561ee5
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/233500
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Markus Handell <handellm@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35131}
This commit is contained in:
Harald Alvestrand 2021-10-01 15:11:17 +00:00 committed by WebRTC LUCI CQ
parent ae566cd831
commit 985310ea3b
7 changed files with 201 additions and 95 deletions

View file

@ -255,6 +255,7 @@ rtc_source_set("packet_socket_factory") {
] ]
deps = [ deps = [
":async_dns_resolver", ":async_dns_resolver",
":wrapping_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",
@ -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") { rtc_source_set("scoped_refptr") {
visibility = [ "*" ] visibility = [ "*" ]
sources = [ "scoped_refptr.h" ] sources = [ "scoped_refptr.h" ]

View file

@ -305,6 +305,14 @@ specific_include_rules = {
"+rtc_base/thread_annotations.h", "+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, # .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 # 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 # files leak their #includes to whoever's #including them, but .cc files

View file

@ -11,9 +11,12 @@
#ifndef API_PACKET_SOCKET_FACTORY_H_ #ifndef API_PACKET_SOCKET_FACTORY_H_
#define API_PACKET_SOCKET_FACTORY_H_ #define API_PACKET_SOCKET_FACTORY_H_
#include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include "api/async_dns_resolver.h"
#include "api/wrapping_async_dns_resolver.h"
#include "rtc_base/async_packet_socket.h" #include "rtc_base/async_packet_socket.h"
#include "rtc_base/proxy_info.h" #include "rtc_base/proxy_info.h"
#include "rtc_base/system/rtc_export.h" #include "rtc_base/system/rtc_export.h"
@ -69,7 +72,23 @@ class RTC_EXPORT PacketSocketFactory {
const std::string& user_agent, const std::string& user_agent,
const PacketSocketTcpOptions& tcp_options) = 0; 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<webrtc::AsyncDnsResolverInterface>
CreateAsyncDnsResolver() {
// Default implementation, to aid in transition to AsyncDnsResolverInterface
return std::make_unique<webrtc::WrappingAsyncDnsResolver>(
CreateAsyncResolver());
}
private: private:
PacketSocketFactory(const PacketSocketFactory&) = delete; PacketSocketFactory(const PacketSocketFactory&) = delete;

View file

@ -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

View file

@ -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 <functional>
#include <memory>
#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<void()> 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<void()> callback_ RTC_GUARDED_BY(sequence_checker_);
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;
};
} // namespace webrtc
#endif // API_WRAPPING_ASYNC_DNS_RESOLVER_H_

View file

@ -91,6 +91,7 @@ rtc_library("rtc_p2p") {
"../api:rtc_error", "../api:rtc_error",
"../api:scoped_refptr", "../api:scoped_refptr",
"../api:sequence_checker", "../api:sequence_checker",
"../api:wrapping_async_dns_resolver",
"../api/crypto:options", "../api/crypto:options",
"../api/rtc_event_log", "../api/rtc_event_log",
"../api/task_queue", "../api/task_queue",

View file

@ -15,6 +15,7 @@
#include "absl/memory/memory.h" #include "absl/memory/memory.h"
#include "api/async_dns_resolver.h" #include "api/async_dns_resolver.h"
#include "api/wrapping_async_dns_resolver.h"
#include "rtc_base/async_resolver.h" #include "rtc_base/async_resolver.h"
#include "rtc_base/logging.h" #include "rtc_base/logging.h"
@ -24,100 +25,6 @@ rtc::AsyncResolverInterface* BasicAsyncResolverFactory::Create() {
return new rtc::AsyncResolver(); 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<void()> 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<void()> callback_ RTC_GUARDED_BY(sequence_checker_);
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(
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<webrtc::AsyncDnsResolverInterface> std::unique_ptr<webrtc::AsyncDnsResolverInterface>
WrappingAsyncDnsResolverFactory::Create() { WrappingAsyncDnsResolverFactory::Create() {