1 /* 2 * Copyright 2021 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef API_WRAPPING_ASYNC_DNS_RESOLVER_H_ 12 #define API_WRAPPING_ASYNC_DNS_RESOLVER_H_ 13 14 #include <functional> 15 #include <memory> 16 #include <utility> 17 18 #include "absl/memory/memory.h" 19 #include "api/async_dns_resolver.h" 20 #include "api/sequence_checker.h" 21 #include "rtc_base/async_resolver.h" 22 #include "rtc_base/async_resolver_interface.h" 23 #include "rtc_base/checks.h" 24 #include "rtc_base/socket_address.h" 25 #include "rtc_base/third_party/sigslot/sigslot.h" 26 #include "rtc_base/thread_annotations.h" 27 28 // This file defines a DNS resolver that wraps an old-style 29 // AsyncResolver. 30 // It is part of the conversion to the newer interface, and will go away 31 // once conversion is finished. 32 // TODO(bugs.webrtc.org/12598): Delete this API. 33 34 namespace webrtc { 35 36 class WrappingAsyncDnsResolver; 37 38 class RTC_EXPORT WrappingAsyncDnsResolverResult 39 : public AsyncDnsResolverResult { 40 public: WrappingAsyncDnsResolverResult(WrappingAsyncDnsResolver * owner)41 explicit WrappingAsyncDnsResolverResult(WrappingAsyncDnsResolver* owner) 42 : owner_(owner) {} ~WrappingAsyncDnsResolverResult()43 ~WrappingAsyncDnsResolverResult() {} 44 45 // Note: Inline declaration not possible, since it refers to 46 // WrappingAsyncDnsResolver. 47 bool GetResolvedAddress(int family, rtc::SocketAddress* addr) const override; 48 int GetError() const override; 49 50 private: 51 WrappingAsyncDnsResolver* const owner_; 52 }; 53 54 class RTC_EXPORT WrappingAsyncDnsResolver : public AsyncDnsResolverInterface, 55 public sigslot::has_slots<> { 56 public: WrappingAsyncDnsResolver(rtc::AsyncResolverInterface * wrapped)57 explicit WrappingAsyncDnsResolver(rtc::AsyncResolverInterface* wrapped) 58 : wrapped_(absl::WrapUnique(wrapped)), result_(this) {} 59 ~WrappingAsyncDnsResolver()60 ~WrappingAsyncDnsResolver() override { 61 // Workaround to get around the fact that sigslot-using objects can't be 62 // destroyed from within their callback: Alert class users early. 63 // TODO(bugs.webrtc.org/12651): Delete this class once the sigslot users are 64 // gone. 65 RTC_CHECK(!within_resolve_result_); 66 wrapped_.release()->Destroy(false); 67 } 68 Start(const rtc::SocketAddress & addr,std::function<void ()> callback)69 void Start(const rtc::SocketAddress& addr, 70 std::function<void()> callback) override { 71 RTC_DCHECK_RUN_ON(&sequence_checker_); 72 PrepareToResolve(std::move(callback)); 73 wrapped_->Start(addr); 74 } 75 Start(const rtc::SocketAddress & addr,int family,std::function<void ()> callback)76 void Start(const rtc::SocketAddress& addr, 77 int family, 78 std::function<void()> callback) override { 79 RTC_DCHECK_RUN_ON(&sequence_checker_); 80 PrepareToResolve(std::move(callback)); 81 wrapped_->Start(addr, family); 82 } 83 result()84 const AsyncDnsResolverResult& result() const override { 85 RTC_DCHECK_RUN_ON(&sequence_checker_); 86 RTC_DCHECK_EQ(State::kResolved, state_); 87 return result_; 88 } 89 90 private: 91 enum class State { kNotStarted, kStarted, kResolved }; 92 93 friend class WrappingAsyncDnsResolverResult; 94 // For use by WrappingAsyncDnsResolverResult wrapped()95 rtc::AsyncResolverInterface* wrapped() const { 96 RTC_DCHECK_RUN_ON(&sequence_checker_); 97 return wrapped_.get(); 98 } 99 PrepareToResolve(std::function<void ()> callback)100 void PrepareToResolve(std::function<void()> callback) { 101 RTC_DCHECK_RUN_ON(&sequence_checker_); 102 RTC_DCHECK_EQ(State::kNotStarted, state_); 103 state_ = State::kStarted; 104 callback_ = std::move(callback); 105 wrapped_->SignalDone.connect(this, 106 &WrappingAsyncDnsResolver::OnResolveResult); 107 } 108 OnResolveResult(rtc::AsyncResolverInterface * ref)109 void OnResolveResult(rtc::AsyncResolverInterface* ref) { 110 RTC_DCHECK_RUN_ON(&sequence_checker_); 111 RTC_DCHECK(state_ == State::kStarted); 112 RTC_DCHECK_EQ(ref, wrapped_.get()); 113 state_ = State::kResolved; 114 within_resolve_result_ = true; 115 callback_(); 116 within_resolve_result_ = false; 117 } 118 119 // The class variables need to be accessed on a single thread. 120 SequenceChecker sequence_checker_; 121 std::function<void()> callback_ RTC_GUARDED_BY(sequence_checker_); 122 std::unique_ptr<rtc::AsyncResolverInterface> wrapped_ 123 RTC_GUARDED_BY(sequence_checker_); 124 State state_ RTC_GUARDED_BY(sequence_checker_) = State::kNotStarted; 125 WrappingAsyncDnsResolverResult result_ RTC_GUARDED_BY(sequence_checker_); 126 bool within_resolve_result_ RTC_GUARDED_BY(sequence_checker_) = false; 127 }; 128 129 } // namespace webrtc 130 131 #endif // API_WRAPPING_ASYNC_DNS_RESOLVER_H_ 132