xref: /aosp_15_r20/external/webrtc/api/wrapping_async_dns_resolver.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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