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