xref: /aosp_15_r20/external/cronet/net/dns/host_resolver_system_task.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef NET_DNS_HOST_RESOLVER_SYSTEM_TASK_H_
6 #define NET_DNS_HOST_RESOLVER_SYSTEM_TASK_H_
7 
8 #include <optional>
9 #include <string>
10 
11 #include "base/functional/callback.h"
12 #include "base/functional/callback_helpers.h"
13 #include "base/task/task_runner.h"
14 #include "net/base/address_list.h"
15 #include "net/base/net_export.h"
16 #include "net/base/network_handle.h"
17 #include "net/dns/host_resolver_proc.h"
18 #include "net/log/net_log_with_source.h"
19 
20 namespace net {
21 
22 using SystemDnsResultsCallback = base::OnceCallback<
23     void(const AddressList& addr_list, int os_error, int net_error)>;
24 
25 // Calls SystemHostResolverCall() (or in some tests, HostResolverProc::Resolve)
26 // in ThreadPool. So EnsureSystemHostResolverCallReady() must be called before
27 // using this class.
28 //
29 // Performs retries if specified by HostResolverSystemTask::Params.
30 //
31 // Whenever we try to resolve the host, we post a delayed task to check if host
32 // resolution (OnLookupComplete) is completed or not. If the original attempt
33 // hasn't completed, then we start another attempt for host resolution. We take
34 // the results from the first attempt that finishes and ignore the results from
35 // all other attempts.
36 //
37 // This class is designed to be used not just by HostResolverManager, but by
38 // general consumers.
39 //
40 // It should only be used on the main thread to ensure that hooks (see
41 // SetSystemHostResolverOverride()) only ever run on the main thread.
42 class NET_EXPORT HostResolverSystemTask {
43  public:
44   // Parameters for customizing HostResolverSystemTask behavior.
45   //
46   // |resolver_proc| is used to override resolution in tests; it must be
47   // thread-safe since it may be run from multiple worker threads. If
48   // |resolver_proc| is NULL then the default host resolver procedure is
49   // to call SystemHostResolverCall().
50   //
51   // For each attempt, we could start another attempt if host is not resolved
52   // within |unresponsive_delay| time. We keep attempting to resolve the host
53   // for |max_retry_attempts|. For every retry attempt, we grow the
54   // |unresponsive_delay| by the |retry_factor| amount (that is retry interval
55   // is multiplied by the retry factor each time). Once we have retried
56   // |max_retry_attempts|, we give up on additional attempts.
57   struct NET_EXPORT_PRIVATE Params {
58     // Default delay between calls to the system resolver for the same hostname.
59     // (Can be overridden by field trial.)
60     static constexpr base::TimeDelta kDnsDefaultUnresponsiveDelay =
61         base::Seconds(6);
62 
63     // Set |max_system_retry_attempts| to this to select a default retry value.
64     static constexpr size_t kDefaultRetryAttempts = -1;
65 
66     // Sets up defaults.
67     Params(scoped_refptr<HostResolverProc> resolver_proc,
68            size_t max_retry_attempts);
69 
70     Params(const Params& other);
71 
72     ~Params();
73 
74     // The procedure to use for resolving host names. This will be NULL, except
75     // in the case of some-tests which inject custom host resolving behaviors.
76     scoped_refptr<HostResolverProc> resolver_proc;
77 
78     // Maximum number retry attempts to resolve the hostname.
79     // Pass HostResolver::Options::kDefaultRetryAttempts to choose a default
80     // value.
81     size_t max_retry_attempts;
82 
83     // This is the limit after which we make another attempt to resolve the host
84     // if the worker thread has not responded yet.
85     base::TimeDelta unresponsive_delay = kDnsDefaultUnresponsiveDelay;
86 
87     // Factor to grow |unresponsive_delay| when we re-re-try.
88     uint32_t retry_factor = 2;
89   };
90 
91   static std::unique_ptr<HostResolverSystemTask> Create(
92       std::string hostname,
93       AddressFamily address_family,
94       HostResolverFlags flags,
95       const Params& params = Params(nullptr, 0),
96       const NetLogWithSource& job_net_log = NetLogWithSource(),
97       handles::NetworkHandle network = handles::kInvalidNetworkHandle);
98 
99   // Same as above but resolves the result of GetHostName() (the machine's own
100   // hostname).
101   static std::unique_ptr<HostResolverSystemTask> CreateForOwnHostname(
102       AddressFamily address_family,
103       HostResolverFlags flags,
104       const Params& params = Params(nullptr, 0),
105       const NetLogWithSource& job_net_log = NetLogWithSource(),
106       handles::NetworkHandle network = handles::kInvalidNetworkHandle);
107 
108   // If `hostname` is std::nullopt, resolves the result of GetHostName().
109   // Prefer using the above 2 static functions for constructing a
110   // HostResolverSystemTask.
111   HostResolverSystemTask(
112       std::optional<std::string> hostname,
113       AddressFamily address_family,
114       HostResolverFlags flags,
115       const Params& params = Params(nullptr, 0),
116       const NetLogWithSource& job_net_log = NetLogWithSource(),
117       handles::NetworkHandle network = handles::kInvalidNetworkHandle);
118 
119   HostResolverSystemTask(const HostResolverSystemTask&) = delete;
120   HostResolverSystemTask& operator=(const HostResolverSystemTask&) = delete;
121 
122   // Cancels this HostResolverSystemTask. Any outstanding resolve attempts
123   // cannot be cancelled, but they will post back to the current thread before
124   // checking their WeakPtrs to find that this task is cancelled.
125   ~HostResolverSystemTask();
126 
127   // Starts the resolution task. This can only be called once per
128   // HostResolverSystemTask. `results_cb` will not be invoked synchronously and
129   // can own `this`.
130   void Start(SystemDnsResultsCallback results_cb);
131 
was_completed()132   bool was_completed() const {
133     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
134     return results_cb_.is_null();
135   }
136 
137  private:
138   void StartLookupAttempt();
139 
140   // Callback for when DoLookup() completes.
141   void OnLookupComplete(const uint32_t attempt_number,
142                         const AddressList& results,
143                         const int os_error,
144                         int error);
145 
146   // If `hostname_` is std::nullopt, this class should resolve the result of
147   // net::GetHostName() (the machine's own hostname).
148   const std::optional<std::string> hostname_;
149   const AddressFamily address_family_;
150   const HostResolverFlags flags_;
151 
152   // Holds an owning reference to the HostResolverProc that we are going to use.
153   // This may not be the current resolver procedure by the time we call
154   // ResolveAddrInfo, but that's OK... we'll use it anyways, and the owning
155   // reference ensures that it remains valid until we are done.
156   Params params_;
157 
158   // The listener to the results of this HostResolverSystemTask.
159   SystemDnsResultsCallback results_cb_;
160 
161   // Keeps track of the number of attempts we have made so far to resolve the
162   // host. Whenever we start an attempt to resolve the host, we increase this
163   // number.
164   uint32_t attempt_number_ = 0;
165 
166   NetLogWithSource net_log_;
167 
168   // Network to perform DNS lookups for.
169   const handles::NetworkHandle network_;
170 
171   SEQUENCE_CHECKER(sequence_checker_);
172 
173   // Used to loop back from the blocking lookup attempt tasks as well as from
174   // delayed retry tasks. Invalidate WeakPtrs on completion and cancellation to
175   // cancel handling of such posted tasks.
176   base::WeakPtrFactory<HostResolverSystemTask> weak_ptr_factory_{this};
177 };
178 
179 // Ensures any necessary initialization occurs such that
180 // SystemHostResolverCall() can be called on other threads.
181 NET_EXPORT void EnsureSystemHostResolverCallReady();
182 
183 // Resolves `host` to an address list, using the system's default host resolver.
184 // (i.e. this calls out to getaddrinfo()). If successful returns OK and fills
185 // `addrlist` with a list of socket addresses. Otherwise returns a
186 // network error code, and fills `os_error` with a more specific error if it
187 // was non-NULL.
188 // `network` is an optional parameter, when specified (!=
189 // handles::kInvalidNetworkHandle) the lookup will be performed specifically for
190 // `network`.
191 //
192 // This should NOT be called in a sandboxed process.
193 NET_EXPORT_PRIVATE int SystemHostResolverCall(
194     const std::string& host,
195     AddressFamily address_family,
196     HostResolverFlags host_resolver_flags,
197     AddressList* addrlist,
198     int* os_error,
199     handles::NetworkHandle network = handles::kInvalidNetworkHandle);
200 
201 // Sets the task runner that system DNS resolution will run on, which is mostly
202 // useful for tests and fuzzers that need reproducibilty of failures.
203 NET_EXPORT_PRIVATE void SetSystemDnsResolutionTaskRunnerForTesting(
204     scoped_refptr<base::TaskRunner> task_runner);
205 
206 // The following will be used to override the behavior of
207 // HostResolverSystemTask. This override will be called instead of posting
208 // SystemHostResolverCall() to a worker thread. The override will only be
209 // invoked on the main thread.
210 // The override should never invoke `results_cb` synchronously.
211 NET_EXPORT void SetSystemDnsResolverOverride(
212     base::RepeatingCallback<void(const std::optional<std::string>& host,
213                                  AddressFamily address_family,
214                                  HostResolverFlags host_resolver_flags,
215                                  SystemDnsResultsCallback results_cb,
216                                  handles::NetworkHandle network)> dns_override);
217 
218 }  // namespace net
219 
220 #endif  // NET_DNS_HOST_RESOLVER_SYSTEM_TASK_H_
221