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