blob: cdad9144ab414c91742ca251d59cb5bae6a78dd2 [file] [log] [blame]
[email protected]a2730882012-01-21 00:56:271// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]b59ff372009-07-15 22:04:322// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]f2cb3cf2013-03-21 01:40:535#include "net/dns/host_resolver_impl.h"
[email protected]b59ff372009-07-15 22:04:326
[email protected]21526002010-05-16 19:42:467#if defined(OS_WIN)
8#include <Winsock2.h>
Fabrice de Gans-Riberi7de47372018-05-08 20:23:479#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
[email protected]21526002010-05-16 19:42:4610#include <netdb.h>
tfarinada9e1362017-03-14 16:49:0611#include <netinet/in.h>
12#if !defined(OS_NACL)
13#include <net/if.h>
14#if !defined(OS_ANDROID)
15#include <ifaddrs.h>
16#endif // !defined(OS_ANDROID)
17#endif // !defined(OS_NACL)
Fabrice de Gans-Riberi7de47372018-05-08 20:23:4718#endif // defined(OS_WIN)
tfarinada9e1362017-03-14 16:49:0619
Eric Orth70992982018-07-24 00:25:0020#include <algorithm>
[email protected]68ad3ee2010-01-30 03:45:3921#include <cmath>
Eric Orth70992982018-07-24 00:25:0022#include <limits>
thestiga74ad2b2016-07-11 20:52:3623#include <memory>
[email protected]0f292de02012-02-01 22:28:2024#include <utility>
[email protected]21526002010-05-16 19:42:4625#include <vector>
[email protected]68ad3ee2010-01-30 03:45:3926
[email protected]33152acc2011-10-20 23:37:1227#include "base/bind.h"
[email protected]aa22b242011-11-16 18:58:2928#include "base/bind_helpers.h"
[email protected]0f292de02012-02-01 22:28:2029#include "base/callback.h"
maksim.sisov31452af2016-07-27 06:38:1030#include "base/callback_helpers.h"
[email protected]b59ff372009-07-15 22:04:3231#include "base/compiler_specific.h"
David Benjamina5677192018-04-23 23:25:4232#include "base/containers/linked_list.h"
[email protected]58580352010-10-26 04:07:5033#include "base/debug/debugger.h"
34#include "base/debug/stack_trace.h"
Avi Drissman13fc8932015-12-20 04:40:4635#include "base/macros.h"
mmenke91c17162016-06-02 16:03:2336#include "base/memory/ptr_util.h"
[email protected]1e9bbd22010-10-15 16:42:4537#include "base/metrics/field_trial.h"
Maks Orlovich5393c8682018-02-26 16:17:5038#include "base/metrics/field_trial_params.h"
Ilya Sherman0eb39802017-12-08 20:58:1839#include "base/metrics/histogram_functions.h"
davidbenad6fc442015-05-18 20:59:1340#include "base/metrics/histogram_macros.h"
anujk.sharma7c907f02015-05-29 02:55:4441#include "base/single_thread_task_runner.h"
[email protected]be528af2013-06-11 07:39:4842#include "base/strings/string_util.h"
[email protected]750b2f3c2013-06-07 18:41:0543#include "base/strings/utf_string_conversions.h"
Gabriel Charette44db1422018-08-06 11:19:3344#include "base/task/post_task.h"
Francois Doraya2d01ba2017-09-25 19:17:4045#include "base/threading/scoped_blocking_call.h"
gabf767595f2016-05-11 18:50:3546#include "base/threading/thread_task_runner_handle.h"
Misha Efimovb99e7da2018-05-30 16:59:0247#include "base/time/default_tick_clock.h"
[email protected]66e96c42013-06-28 15:20:3148#include "base/time/time.h"
ssid6d6b40102016-04-05 18:59:5649#include "base/trace_event/trace_event.h"
[email protected]21526002010-05-16 19:42:4650#include "base/values.h"
Fabrice de Gans-Riberi7de47372018-05-08 20:23:4751#include "build/build_config.h"
[email protected]b3601bc22012-02-21 21:23:2052#include "net/base/address_family.h"
[email protected]b59ff372009-07-15 22:04:3253#include "net/base/address_list.h"
[email protected]ee094b82010-08-24 15:55:5154#include "net/base/host_port_pair.h"
martijna23c8962016-03-04 18:18:5155#include "net/base/ip_address.h"
[email protected]1c7cf3f82014-08-07 21:33:4856#include "net/base/ip_endpoint.h"
[email protected]2bb04442010-08-18 18:01:1557#include "net/base/net_errors.h"
xunjieli0b7f5b62016-12-06 20:43:4858#include "net/base/trace_constants.h"
tfarina9ed7f8c52016-02-19 17:50:1859#include "net/base/url_util.h"
[email protected]0adcb2b2012-08-15 21:30:4660#include "net/dns/address_sorter.h"
[email protected]78eac2a2012-03-14 19:09:2761#include "net/dns/dns_client.h"
[email protected]b3601bc22012-02-21 21:23:2062#include "net/dns/dns_protocol.h"
tfarina47598f042015-10-07 23:08:3563#include "net/dns/dns_reloader.h"
[email protected]b3601bc22012-02-21 21:23:2064#include "net/dns/dns_response.h"
[email protected]b3601bc22012-02-21 21:23:2065#include "net/dns/dns_transaction.h"
tfarina77021d62015-10-11 20:19:0366#include "net/dns/dns_util.h"
Eric Orth9871aafa2018-10-02 19:59:1867#include "net/dns/host_resolver_mdns_task.h"
[email protected]f2cb3cf2013-03-21 01:40:5368#include "net/dns/host_resolver_proc.h"
Eric Orth9871aafa2018-10-02 19:59:1869#include "net/dns/mdns_client.h"
eroman87c53d62015-04-02 06:51:0770#include "net/log/net_log.h"
mikecironef22f9812016-10-04 03:40:1971#include "net/log/net_log_capture_mode.h"
mikecirone8b85c432016-09-08 19:11:0072#include "net/log/net_log_event_type.h"
mikecironef22f9812016-10-04 03:40:1973#include "net/log/net_log_parameters_callback.h"
74#include "net/log/net_log_source.h"
mikecirone8b85c432016-09-08 19:11:0075#include "net/log/net_log_source_type.h"
mikecironef22f9812016-10-04 03:40:1976#include "net/log/net_log_with_source.h"
[email protected]9db6f702013-04-10 18:10:5177#include "net/socket/client_socket_factory.h"
tfarina5dd13c22016-11-16 12:08:2678#include "net/socket/datagram_client_socket.h"
pauljensen370f1c72015-02-17 16:59:1479#include "url/url_canon_ip.h"
[email protected]b59ff372009-07-15 22:04:3280
Eric Orth9871aafa2018-10-02 19:59:1881#if BUILDFLAG(ENABLE_MDNS)
82#include "net/dns/mdns_client_impl.h"
83#endif
84
[email protected]b59ff372009-07-15 22:04:3285#if defined(OS_WIN)
86#include "net/base/winsock_init.h"
87#endif
88
tfarinada9e1362017-03-14 16:49:0689#if defined(OS_ANDROID)
90#include "net/android/network_library.h"
91#endif
92
[email protected]b59ff372009-07-15 22:04:3293namespace net {
94
[email protected]e95d3aca2010-01-11 22:47:4395namespace {
96
ttuttlecf1158bf2016-03-18 16:37:4497// Default delay between calls to the system resolver for the same hostname.
98// (Can be overridden by field trial.)
99const int64_t kDnsDefaultUnresponsiveDelayMs = 6000;
100
[email protected]6e78dfb2011-07-28 21:34:47101// Limit the size of hostnames that will be resolved to combat issues in
102// some platform's resolvers.
103const size_t kMaxHostLength = 4096;
104
[email protected]a2730882012-01-21 00:56:27105// Default TTL for successful resolutions with ProcTask.
106const unsigned kCacheEntryTTLSeconds = 60;
107
[email protected]b3601bc22012-02-21 21:23:20108// Default TTL for unsuccessful resolutions with ProcTask.
109const unsigned kNegativeCacheEntryTTLSeconds = 0;
110
[email protected]895123222012-10-25 15:21:17111// Minimum TTL for successful resolutions with DnsTask.
112const unsigned kMinimumTTLSeconds = kCacheEntryTTLSeconds;
113
sergeyub8cdc212015-05-14 18:50:37114// Time between IPv6 probes, i.e. for how long results of each IPv6 probe are
115// cached.
116const int kIPv6ProbePeriodMs = 1000;
117
118// Google DNS address used for IPv6 probes.
119const uint8_t kIPv6ProbeAddress[] =
120 { 0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88 };
122
[email protected]24f4bab2010-10-15 01:27:11123// We use a separate histogram name for each platform to facilitate the
124// display of error codes by their symbolic name (since each platform has
125// different mappings).
126const char kOSErrorsForGetAddrinfoHistogramName[] =
127#if defined(OS_WIN)
128 "Net.OSErrorsForGetAddrinfo_Win";
129#elif defined(OS_MACOSX)
130 "Net.OSErrorsForGetAddrinfo_Mac";
131#elif defined(OS_LINUX)
132 "Net.OSErrorsForGetAddrinfo_Linux";
Fabrice de Gans-Riberi7de47372018-05-08 20:23:47133#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
[email protected]24f4bab2010-10-15 01:27:11134 "Net.OSErrorsForGetAddrinfo";
135#endif
136
[email protected]c89b2442011-05-26 14:28:27137// Gets a list of the likely error codes that getaddrinfo() can return
138// (non-exhaustive). These are the error codes that we will track via
139// a histogram.
140std::vector<int> GetAllGetAddrinfoOSErrors() {
141 int os_errors[] = {
Fabrice de Gans-Riberi7de47372018-05-08 20:23:47142#if defined(OS_WIN)
143 // See: http://msdn.microsoft.com/en-us/library/ms738520(VS.85).aspx
144 WSA_NOT_ENOUGH_MEMORY,
145 WSAEAFNOSUPPORT,
146 WSAEINVAL,
147 WSAESOCKTNOSUPPORT,
148 WSAHOST_NOT_FOUND,
149 WSANO_DATA,
150 WSANO_RECOVERY,
151 WSANOTINITIALISED,
152 WSATRY_AGAIN,
153 WSATYPE_NOT_FOUND,
154 // The following are not in doc, but might be to appearing in results :-(.
155 WSA_INVALID_HANDLE,
156#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
[email protected]23f771162011-06-02 18:37:51157#if !defined(OS_FREEBSD)
[email protected]39588992011-07-11 19:54:37158#if !defined(OS_ANDROID)
[email protected]c48aef92011-11-22 23:41:45159 // EAI_ADDRFAMILY has been declared obsolete in Android's and
160 // FreeBSD's netdb.h.
[email protected]c89b2442011-05-26 14:28:27161 EAI_ADDRFAMILY,
[email protected]39588992011-07-11 19:54:37162#endif
[email protected]c48aef92011-11-22 23:41:45163 // EAI_NODATA has been declared obsolete in FreeBSD's netdb.h.
[email protected]23f771162011-06-02 18:37:51164 EAI_NODATA,
165#endif
[email protected]c89b2442011-05-26 14:28:27166 EAI_AGAIN,
167 EAI_BADFLAGS,
168 EAI_FAIL,
169 EAI_FAMILY,
170 EAI_MEMORY,
[email protected]c89b2442011-05-26 14:28:27171 EAI_NONAME,
172 EAI_SERVICE,
173 EAI_SOCKTYPE,
174 EAI_SYSTEM,
[email protected]c89b2442011-05-26 14:28:27175#endif
176 };
177
178 // Ensure all errors are positive, as histogram only tracks positive values.
179 for (size_t i = 0; i < arraysize(os_errors); ++i) {
180 os_errors[i] = std::abs(os_errors[i]);
181 }
182
Ryan Sleevi9c79c3542018-05-12 01:38:09183 return base::CustomHistogram::ArrayToCustomEnumRanges(os_errors);
[email protected]c89b2442011-05-26 14:28:27184}
185
[email protected]1def74c2012-03-22 20:07:00186enum DnsResolveStatus {
187 RESOLVE_STATUS_DNS_SUCCESS = 0,
188 RESOLVE_STATUS_PROC_SUCCESS,
189 RESOLVE_STATUS_FAIL,
[email protected]1d932852012-06-19 19:40:33190 RESOLVE_STATUS_SUSPECT_NETBIOS,
[email protected]1def74c2012-03-22 20:07:00191 RESOLVE_STATUS_MAX
192};
193
eroman91dd3602015-03-26 03:46:33194// ICANN uses this localhost address to indicate a name collision.
195//
196// The policy in Chromium is to fail host resolving if it resolves to
197// this special address.
198//
199// Not however that IP literals are exempt from this policy, so it is still
200// possible to navigate to http://127.0.53.53/ directly.
201//
202// For more details: https://www.icann.org/news/announcement-2-2014-08-01-en
martijna23c8962016-03-04 18:18:51203const uint8_t kIcanNameCollisionIp[] = {127, 0, 53, 53};
eroman91dd3602015-03-26 03:46:33204
eroman1efc237c2016-12-14 00:00:45205bool ContainsIcannNameCollisionIp(const AddressList& addr_list) {
206 for (const auto& endpoint : addr_list) {
207 const IPAddress& addr = endpoint.address();
208 if (addr.IsIPv4() && IPAddressStartsWith(addr, kIcanNameCollisionIp)) {
209 return true;
210 }
211 }
212 return false;
213}
214
[email protected]1def74c2012-03-22 20:07:00215void UmaAsyncDnsResolveStatus(DnsResolveStatus result) {
216 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ResolveStatus",
217 result,
218 RESOLVE_STATUS_MAX);
219}
220
[email protected]1d932852012-06-19 19:40:33221bool ResemblesNetBIOSName(const std::string& hostname) {
222 return (hostname.size() < 16) && (hostname.find('.') == std::string::npos);
223}
224
225// True if |hostname| ends with either ".local" or ".local.".
226bool ResemblesMulticastDNSName(const std::string& hostname) {
227 DCHECK(!hostname.empty());
228 const char kSuffix[] = ".local.";
229 const size_t kSuffixLen = sizeof(kSuffix) - 1;
230 const size_t kSuffixLenTrimmed = kSuffixLen - 1;
thestiga74ad2b2016-07-11 20:52:36231 if (hostname.back() == '.') {
[email protected]1d932852012-06-19 19:40:33232 return hostname.size() > kSuffixLen &&
233 !hostname.compare(hostname.size() - kSuffixLen, kSuffixLen, kSuffix);
234 }
235 return hostname.size() > kSuffixLenTrimmed &&
236 !hostname.compare(hostname.size() - kSuffixLenTrimmed, kSuffixLenTrimmed,
237 kSuffix, kSuffixLenTrimmed);
238}
239
[email protected]51b9a6b2012-06-25 21:50:29240// A macro to simplify code and readability.
Miriam Gershenson4e7c9ecf2017-09-26 23:17:21241#define DNS_HISTOGRAM_BY_PRIORITY(basename, priority, time) \
242 do { \
243 switch (priority) { \
244 case HIGHEST: \
Miriam Gershenson90d05e02017-09-28 19:29:28245 UMA_HISTOGRAM_LONG_TIMES_100(basename ".HIGHEST", time); \
Miriam Gershenson4e7c9ecf2017-09-26 23:17:21246 break; \
247 case MEDIUM: \
Miriam Gershenson90d05e02017-09-28 19:29:28248 UMA_HISTOGRAM_LONG_TIMES_100(basename ".MEDIUM", time); \
Miriam Gershenson4e7c9ecf2017-09-26 23:17:21249 break; \
250 case LOW: \
Miriam Gershenson90d05e02017-09-28 19:29:28251 UMA_HISTOGRAM_LONG_TIMES_100(basename ".LOW", time); \
Miriam Gershenson4e7c9ecf2017-09-26 23:17:21252 break; \
253 case LOWEST: \
Miriam Gershenson90d05e02017-09-28 19:29:28254 UMA_HISTOGRAM_LONG_TIMES_100(basename ".LOWEST", time); \
Miriam Gershenson4e7c9ecf2017-09-26 23:17:21255 break; \
256 case IDLE: \
Miriam Gershenson90d05e02017-09-28 19:29:28257 UMA_HISTOGRAM_LONG_TIMES_100(basename ".IDLE", time); \
Miriam Gershenson4e7c9ecf2017-09-26 23:17:21258 break; \
259 case THROTTLED: \
Miriam Gershenson90d05e02017-09-28 19:29:28260 UMA_HISTOGRAM_LONG_TIMES_100(basename ".THROTTLED", time); \
Miriam Gershenson4e7c9ecf2017-09-26 23:17:21261 break; \
262 } \
263 UMA_HISTOGRAM_LONG_TIMES_100(basename, time); \
[email protected]51b9a6b2012-06-25 21:50:29264 } while (0)
265
266// Record time from Request creation until a valid DNS response.
Miriam Gershenson90d05e02017-09-28 19:29:28267void RecordTotalTime(bool speculative,
268 bool from_cache,
[email protected]51b9a6b2012-06-25 21:50:29269 base::TimeDelta duration) {
Miriam Gershenson7ba03e12018-02-07 22:48:24270 if (!speculative) {
Miriam Gershenson90d05e02017-09-28 19:29:28271 UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.TotalTime", duration);
Miriam Gershenson90d05e02017-09-28 19:29:28272
Miriam Gershenson7ba03e12018-02-07 22:48:24273 if (!from_cache)
Miriam Gershenson90d05e02017-09-28 19:29:28274 UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.TotalTimeNotCached", duration);
[email protected]51b9a6b2012-06-25 21:50:29275 }
276}
277
[email protected]1339a2a22012-10-17 08:39:43278void RecordTTL(base::TimeDelta ttl) {
279 UMA_HISTOGRAM_CUSTOM_TIMES("AsyncDNS.TTL", ttl,
280 base::TimeDelta::FromSeconds(1),
281 base::TimeDelta::FromDays(1), 100);
282}
283
[email protected]16c2bd72013-06-28 01:19:22284bool ConfigureAsyncDnsNoFallbackFieldTrial() {
285 const bool kDefault = false;
286
287 // Configure the AsyncDns field trial as follows:
288 // groups AsyncDnsNoFallbackA and AsyncDnsNoFallbackB: return true,
289 // groups AsyncDnsA and AsyncDnsB: return false,
290 // groups SystemDnsA and SystemDnsB: return false,
291 // otherwise (trial absent): return default.
292 std::string group_name = base::FieldTrialList::FindFullName("AsyncDns");
brettw3a2c6902015-07-06 19:43:29293 if (!group_name.empty()) {
294 return base::StartsWith(group_name, "AsyncDnsNoFallback",
295 base::CompareCase::INSENSITIVE_ASCII);
296 }
[email protected]16c2bd72013-06-28 01:19:22297 return kDefault;
298}
299
Maks Orlovich5393c8682018-02-26 16:17:50300const base::FeatureParam<base::TaskPriority>::Option prio_modes[] = {
301 {base::TaskPriority::USER_VISIBLE, "default"},
302 {base::TaskPriority::USER_BLOCKING, "user_blocking"}};
303const base::Feature kSystemResolverPriorityExperiment = {
304 "SystemResolverPriorityExperiment", base::FEATURE_DISABLED_BY_DEFAULT};
305const base::FeatureParam<base::TaskPriority> priority_mode{
306 &kSystemResolverPriorityExperiment, "mode",
307 base::TaskPriority::USER_VISIBLE, &prio_modes};
308
[email protected]d7b9a2b2012-05-31 22:31:19309//-----------------------------------------------------------------------------
310
Avi Drissman13fc8932015-12-20 04:40:46311AddressList EnsurePortOnAddressList(const AddressList& list, uint16_t port) {
[email protected]895123222012-10-25 15:21:17312 if (list.empty() || list.front().port() == port)
313 return list;
314 return AddressList::CopyWithPort(list, port);
[email protected]7054e78f2012-05-07 21:44:56315}
316
[email protected]ec666ab22013-04-17 20:05:59317// Returns true if |addresses| contains only IPv4 loopback addresses.
318bool IsAllIPv4Loopback(const AddressList& addresses) {
319 for (unsigned i = 0; i < addresses.size(); ++i) {
martijna23c8962016-03-04 18:18:51320 const IPAddress& address = addresses[i].address();
[email protected]ec666ab22013-04-17 20:05:59321 switch (addresses[i].GetFamily()) {
322 case ADDRESS_FAMILY_IPV4:
martijna23c8962016-03-04 18:18:51323 if (address.bytes()[0] != 127)
[email protected]ec666ab22013-04-17 20:05:59324 return false;
325 break;
326 case ADDRESS_FAMILY_IPV6:
327 return false;
328 default:
329 NOTREACHED();
330 return false;
331 }
332 }
333 return true;
334}
335
tfarinada9e1362017-03-14 16:49:06336// Returns true if it can determine that only loopback addresses are configured.
337// i.e. if only 127.0.0.1 and ::1 are routable.
338// Also returns false if it cannot determine this.
339bool HaveOnlyLoopbackAddresses() {
Francois Doraya2d01ba2017-09-25 19:17:40340 base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::WILL_BLOCK);
Fabrice de Gans-Riberi7de47372018-05-08 20:23:47341#if defined(OS_WIN)
342 // TODO(wtc): implement with the GetAdaptersAddresses function.
343 NOTIMPLEMENTED();
344 return false;
345#elif defined(OS_ANDROID)
tfarinada9e1362017-03-14 16:49:06346 return android::HaveOnlyLoopbackAddresses();
347#elif defined(OS_NACL)
348 NOTIMPLEMENTED();
349 return false;
Fabrice de Gans-Riberi7de47372018-05-08 20:23:47350#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
tfarinada9e1362017-03-14 16:49:06351 struct ifaddrs* interface_addr = NULL;
352 int rv = getifaddrs(&interface_addr);
353 if (rv != 0) {
354 DVLOG(1) << "getifaddrs() failed with errno = " << errno;
355 return false;
356 }
357
358 bool result = true;
359 for (struct ifaddrs* interface = interface_addr;
360 interface != NULL;
361 interface = interface->ifa_next) {
362 if (!(IFF_UP & interface->ifa_flags))
363 continue;
364 if (IFF_LOOPBACK & interface->ifa_flags)
365 continue;
366 const struct sockaddr* addr = interface->ifa_addr;
367 if (!addr)
368 continue;
369 if (addr->sa_family == AF_INET6) {
370 // Safe cast since this is AF_INET6.
371 const struct sockaddr_in6* addr_in6 =
372 reinterpret_cast<const struct sockaddr_in6*>(addr);
373 const struct in6_addr* sin6_addr = &addr_in6->sin6_addr;
374 if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || IN6_IS_ADDR_LINKLOCAL(sin6_addr))
375 continue;
376 }
377 if (addr->sa_family != AF_INET6 && addr->sa_family != AF_INET)
378 continue;
379
380 result = false;
381 break;
382 }
383 freeifaddrs(interface_addr);
384 return result;
tfarinada9e1362017-03-14 16:49:06385#endif // defined(various platforms)
386}
387
[email protected]cd565142012-06-12 16:21:45388// Creates NetLog parameters when the resolve failed.
danakj22f90e72016-04-16 01:55:40389std::unique_ptr<base::Value> NetLogProcTaskFailedCallback(
Avi Drissman13fc8932015-12-20 04:40:46390 uint32_t attempt_number,
eroman001c3742015-04-23 03:11:17391 int net_error,
392 int os_error,
393 NetLogCaptureMode /* capture_mode */) {
danakj22f90e72016-04-16 01:55:40394 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
[email protected]cd565142012-06-12 16:21:45395 if (attempt_number)
396 dict->SetInteger("attempt_number", attempt_number);
[email protected]21526002010-05-16 19:42:46397
[email protected]cd565142012-06-12 16:21:45398 dict->SetInteger("net_error", net_error);
[email protected]13024882011-05-18 23:19:16399
[email protected]cd565142012-06-12 16:21:45400 if (os_error) {
401 dict->SetInteger("os_error", os_error);
Fabrice de Gans-Riberi7de47372018-05-08 20:23:47402#if defined(OS_WIN)
[email protected]cd565142012-06-12 16:21:45403 // Map the error code to a human-readable string.
wezb9820d42016-06-22 23:41:04404 LPWSTR error_string = nullptr;
Peter Kastingbe940e92014-11-20 23:14:08405 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
406 0, // Use the internal message table.
407 os_error,
408 0, // Use default language.
409 (LPWSTR)&error_string,
410 0, // Buffer size.
411 0); // Arguments (unused).
[email protected]ad65a3e2013-12-25 18:18:01412 dict->SetString("os_error_string", base::WideToUTF8(error_string));
[email protected]cd565142012-06-12 16:21:45413 LocalFree(error_string);
Fabrice de Gans-Riberi7de47372018-05-08 20:23:47414#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
415 dict->SetString("os_error_string", gai_strerror(os_error));
[email protected]21526002010-05-16 19:42:46416#endif
[email protected]21526002010-05-16 19:42:46417 }
418
dchengc7eeda422015-12-26 03:56:48419 return std::move(dict);
[email protected]cd565142012-06-12 16:21:45420}
[email protected]a9813302012-04-28 09:29:28421
[email protected]cd565142012-06-12 16:21:45422// Creates NetLog parameters when the DnsTask failed.
danakj22f90e72016-04-16 01:55:40423std::unique_ptr<base::Value> NetLogDnsTaskFailedCallback(
estade5e5529d2015-05-21 20:59:11424 int net_error,
425 int dns_error,
426 NetLogCaptureMode /* capture_mode */) {
danakj22f90e72016-04-16 01:55:40427 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
[email protected]cd565142012-06-12 16:21:45428 dict->SetInteger("net_error", net_error);
429 if (dns_error)
430 dict->SetInteger("dns_error", dns_error);
dchengc7eeda422015-12-26 03:56:48431 return std::move(dict);
thestiga74ad2b2016-07-11 20:52:36432}
[email protected]ee094b82010-08-24 15:55:51433
[email protected]cd565142012-06-12 16:21:45434// Creates NetLog parameters containing the information in a RequestInfo object,
Eric Orth70992982018-07-24 00:25:00435// along with the associated NetLogSource. Use NetLogRequestCallback() if the
436// request information is not specified via RequestInfo.
danakj22f90e72016-04-16 01:55:40437std::unique_ptr<base::Value> NetLogRequestInfoCallback(
estade5e5529d2015-05-21 20:59:11438 const HostResolver::RequestInfo* info,
439 NetLogCaptureMode /* capture_mode */) {
danakj22f90e72016-04-16 01:55:40440 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
[email protected]b3601bc22012-02-21 21:23:20441
[email protected]cd565142012-06-12 16:21:45442 dict->SetString("host", info->host_port_pair().ToString());
443 dict->SetInteger("address_family",
444 static_cast<int>(info->address_family()));
445 dict->SetBoolean("allow_cached_response", info->allow_cached_response());
446 dict->SetBoolean("is_speculative", info->is_speculative());
dchengc7eeda422015-12-26 03:56:48447 return std::move(dict);
[email protected]cd565142012-06-12 16:21:45448}
[email protected]b3601bc22012-02-21 21:23:20449
Eric Orth70992982018-07-24 00:25:00450// Creates NetLog parameters containing the information of the request. Use
451// NetLogRequestInfoCallback if the request is specified via RequestInfo.
452std::unique_ptr<base::Value> NetLogRequestCallback(
453 const HostPortPair& host,
454 NetLogCaptureMode /* capture_mode */) {
455 auto dict = std::make_unique<base::DictionaryValue>();
456
457 dict->SetString("host", host.ToString());
458 dict->SetInteger("address_family",
459 static_cast<int>(ADDRESS_FAMILY_UNSPECIFIED));
460 dict->SetBoolean("allow_cached_response", true);
461 dict->SetBoolean("is_speculative", false);
462 return std::move(dict);
463}
464
[email protected]cd565142012-06-12 16:21:45465// Creates NetLog parameters for the creation of a HostResolverImpl::Job.
danakj22f90e72016-04-16 01:55:40466std::unique_ptr<base::Value> NetLogJobCreationCallback(
mikecironef22f9812016-10-04 03:40:19467 const NetLogSource& source,
estade5e5529d2015-05-21 20:59:11468 const std::string* host,
469 NetLogCaptureMode /* capture_mode */) {
Eric Orth70992982018-07-24 00:25:00470 auto dict = std::make_unique<base::DictionaryValue>();
estade5e5529d2015-05-21 20:59:11471 source.AddToEventParameters(dict.get());
[email protected]cd565142012-06-12 16:21:45472 dict->SetString("host", *host);
dchengc7eeda422015-12-26 03:56:48473 return std::move(dict);
[email protected]cd565142012-06-12 16:21:45474}
[email protected]a9813302012-04-28 09:29:28475
[email protected]cd565142012-06-12 16:21:45476// Creates NetLog parameters for HOST_RESOLVER_IMPL_JOB_ATTACH/DETACH events.
danakj22f90e72016-04-16 01:55:40477std::unique_ptr<base::Value> NetLogJobAttachCallback(
mikecironef22f9812016-10-04 03:40:19478 const NetLogSource& source,
estade5e5529d2015-05-21 20:59:11479 RequestPriority priority,
480 NetLogCaptureMode /* capture_mode */) {
danakj22f90e72016-04-16 01:55:40481 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
estade5e5529d2015-05-21 20:59:11482 source.AddToEventParameters(dict.get());
[email protected]3b04d1f22013-10-16 00:23:56483 dict->SetString("priority", RequestPriorityToString(priority));
dchengc7eeda422015-12-26 03:56:48484 return std::move(dict);
[email protected]cd565142012-06-12 16:21:45485}
[email protected]b3601bc22012-02-21 21:23:20486
[email protected]cd565142012-06-12 16:21:45487// Creates NetLog parameters for the DNS_CONFIG_CHANGED event.
danakj22f90e72016-04-16 01:55:40488std::unique_ptr<base::Value> NetLogDnsConfigCallback(
estade5e5529d2015-05-21 20:59:11489 const DnsConfig* config,
490 NetLogCaptureMode /* capture_mode */) {
tfhef3618f2016-01-11 23:07:08491 return config->ToValue();
[email protected]cd565142012-06-12 16:21:45492}
[email protected]b4481b222012-03-16 17:13:11493
danakj22f90e72016-04-16 01:55:40494std::unique_ptr<base::Value> NetLogIPv6AvailableCallback(
estade5e5529d2015-05-21 20:59:11495 bool ipv6_available,
496 bool cached,
497 NetLogCaptureMode /* capture_mode */) {
danakj22f90e72016-04-16 01:55:40498 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
sergeyub8cdc212015-05-14 18:50:37499 dict->SetBoolean("ipv6_available", ipv6_available);
500 dict->SetBoolean("cached", cached);
dchengc7eeda422015-12-26 03:56:48501 return std::move(dict);
sergeyub8cdc212015-05-14 18:50:37502}
503
[email protected]0f292de02012-02-01 22:28:20504// The logging routines are defined here because some requests are resolved
505// without a Request object.
506
Eric Orth70992982018-07-24 00:25:00507// Logs when a request has just been started. Overloads for whether or not the
508// request information is specified via a RequestInfo object.
tfarina428341112016-09-22 13:38:20509void LogStartRequest(const NetLogWithSource& source_net_log,
[email protected]0f292de02012-02-01 22:28:20510 const HostResolver::RequestInfo& info) {
mikecirone8b85c432016-09-08 19:11:00511 source_net_log.BeginEvent(NetLogEventType::HOST_RESOLVER_IMPL_REQUEST,
512 base::Bind(&NetLogRequestInfoCallback, &info));
[email protected]0f292de02012-02-01 22:28:20513}
Eric Orth70992982018-07-24 00:25:00514void LogStartRequest(const NetLogWithSource& source_net_log,
515 const HostPortPair& host) {
516 source_net_log.BeginEvent(NetLogEventType::HOST_RESOLVER_IMPL_REQUEST,
517 base::BindRepeating(&NetLogRequestCallback, host));
518}
[email protected]0f292de02012-02-01 22:28:20519
520// Logs when a request has just completed (before its callback is run).
Eric Orth70992982018-07-24 00:25:00521void LogFinishRequest(const NetLogWithSource& source_net_log, int net_error) {
xunjieli26f90452014-11-10 16:23:02522 source_net_log.EndEventWithNetErrorCode(
mikecirone8b85c432016-09-08 19:11:00523 NetLogEventType::HOST_RESOLVER_IMPL_REQUEST, net_error);
[email protected]0f292de02012-02-01 22:28:20524}
525
526// Logs when a request has been cancelled.
Eric Orth70992982018-07-24 00:25:00527void LogCancelRequest(const NetLogWithSource& source_net_log) {
mikecirone8b85c432016-09-08 19:11:00528 source_net_log.AddEvent(NetLogEventType::CANCELLED);
529 source_net_log.EndEvent(NetLogEventType::HOST_RESOLVER_IMPL_REQUEST);
[email protected]0f292de02012-02-01 22:28:20530}
531
[email protected]b59ff372009-07-15 22:04:32532//-----------------------------------------------------------------------------
533
[email protected]0f292de02012-02-01 22:28:20534// Keeps track of the highest priority.
535class PriorityTracker {
536 public:
[email protected]8c98d002012-07-18 19:02:27537 explicit PriorityTracker(RequestPriority initial_priority)
538 : highest_priority_(initial_priority), total_count_(0) {
[email protected]0f292de02012-02-01 22:28:20539 memset(counts_, 0, sizeof(counts_));
540 }
541
542 RequestPriority highest_priority() const {
543 return highest_priority_;
544 }
545
546 size_t total_count() const {
547 return total_count_;
548 }
549
550 void Add(RequestPriority req_priority) {
551 ++total_count_;
552 ++counts_[req_priority];
[email protected]31ae7ab2012-04-24 21:09:05553 if (highest_priority_ < req_priority)
[email protected]0f292de02012-02-01 22:28:20554 highest_priority_ = req_priority;
555 }
556
557 void Remove(RequestPriority req_priority) {
558 DCHECK_GT(total_count_, 0u);
559 DCHECK_GT(counts_[req_priority], 0u);
560 --total_count_;
561 --counts_[req_priority];
562 size_t i;
thestiga74ad2b2016-07-11 20:52:36563 for (i = highest_priority_; i > MINIMUM_PRIORITY && !counts_[i]; --i) {
564 }
[email protected]0f292de02012-02-01 22:28:20565 highest_priority_ = static_cast<RequestPriority>(i);
566
[email protected]31ae7ab2012-04-24 21:09:05567 // In absence of requests, default to MINIMUM_PRIORITY.
568 if (total_count_ == 0)
569 DCHECK_EQ(MINIMUM_PRIORITY, highest_priority_);
[email protected]0f292de02012-02-01 22:28:20570 }
571
572 private:
573 RequestPriority highest_priority_;
574 size_t total_count_;
575 size_t counts_[NUM_PRIORITIES];
576};
577
juliatuttle9fb7aeb2016-06-06 20:16:33578void MakeNotStale(HostCache::EntryStaleness* stale_info) {
579 if (!stale_info)
580 return;
581 stale_info->expired_by = base::TimeDelta::FromSeconds(-1);
582 stale_info->network_changes = 0;
583 stale_info->stale_hits = 0;
584}
585
[email protected]c54a8912012-10-22 22:09:43586} // namespace
[email protected]0f292de02012-02-01 22:28:20587
588//-----------------------------------------------------------------------------
589
tfarina9ed7f8c52016-02-19 17:50:18590bool ResolveLocalHostname(base::StringPiece host,
591 uint16_t port,
592 AddressList* address_list) {
tfarina9ed7f8c52016-02-19 17:50:18593 address_list->clear();
594
595 bool is_local6;
596 if (!IsLocalHostname(host, &is_local6))
597 return false;
598
martijna23c8962016-03-04 18:18:51599 address_list->push_back(IPEndPoint(IPAddress::IPv6Localhost(), port));
tfarina9ed7f8c52016-02-19 17:50:18600 if (!is_local6) {
martijna23c8962016-03-04 18:18:51601 address_list->push_back(IPEndPoint(IPAddress::IPv4Localhost(), port));
tfarina9ed7f8c52016-02-19 17:50:18602 }
603
604 return true;
605}
606
[email protected]daae1322013-09-05 18:26:50607const unsigned HostResolverImpl::kMaximumDnsFailures = 16;
608
Eric Roman91aab1e62018-04-24 20:31:32609// Holds the callback and request parameters for an outstanding request.
610//
611// The RequestImpl is owned by the end user of host resolution. Deletion prior
612// to the request having completed means the request was cancelled by the
613// caller.
614//
615// Both the RequestImpl and its associated Job hold non-owning pointers to each
616// other. Care must be taken to clear the corresponding pointer when
617// cancellation is initiated by the Job (OnJobCancelled) vs by the end user
618// (~RequestImpl).
David Benjamina5677192018-04-23 23:25:42619class HostResolverImpl::RequestImpl
Eric Orth70992982018-07-24 00:25:00620 : public HostResolver::ResolveHostRequest,
David Benjamina5677192018-04-23 23:25:42621 public base::LinkNode<HostResolverImpl::RequestImpl> {
[email protected]b59ff372009-07-15 22:04:32622 public:
tfarina428341112016-09-22 13:38:20623 RequestImpl(const NetLogWithSource& source_net_log,
Eric Orth70992982018-07-24 00:25:00624 const HostPortPair& request_host,
Eric Orth00fe5a62018-08-15 22:20:00625 const base::Optional<ResolveHostParameters>& optional_parameters,
Eric Orth70992982018-07-24 00:25:00626 base::WeakPtr<HostResolverImpl> resolver)
[email protected]ee094b82010-08-24 15:55:51627 : source_net_log_(source_net_log),
Eric Orth70992982018-07-24 00:25:00628 request_host_(request_host),
Eric Orth00fe5a62018-08-15 22:20:00629 parameters_(optional_parameters ? optional_parameters.value()
630 : ResolveHostParameters()),
Eric Orthdc35748e2018-08-23 22:41:48631 host_resolver_flags_(ParametersToHostResolverFlags(parameters_)),
Eric Orth00fe5a62018-08-15 22:20:00632 priority_(parameters_.initial_priority),
Eric Orth70992982018-07-24 00:25:00633 job_(nullptr),
634 resolver_(resolver),
635 complete_(false) {}
[email protected]b59ff372009-07-15 22:04:32636
maksim.sisov31452af2016-07-27 06:38:10637 ~RequestImpl() override;
638
Eric Orth70992982018-07-24 00:25:00639 int Start(CompletionOnceCallback callback) override {
640 DCHECK(callback);
641 // Start() may only be called once per request.
642 DCHECK(!job_);
643 DCHECK(!complete_);
644 DCHECK(!callback_);
645 // Parent HostResolver must still be alive to call Start().
646 DCHECK(resolver_);
maksim.sisov31452af2016-07-27 06:38:10647
Eric Orth70992982018-07-24 00:25:00648 int rv = resolver_->Resolve(this);
649 DCHECK(!complete_);
650 if (rv == ERR_IO_PENDING) {
651 DCHECK(job_);
652 callback_ = std::move(callback);
653 } else {
654 DCHECK(!job_);
655 complete_ = true;
656 }
657 resolver_ = nullptr;
658
659 return rv;
660 }
661
662 const base::Optional<AddressList>& GetAddressResults() const override {
663 DCHECK(complete_);
664 return address_results_;
665 }
666
667 void set_address_results(const AddressList& address_results) {
668 // Should only be called at most once and before request is marked
669 // completed.
670 DCHECK(!complete_);
671 DCHECK(!address_results_);
Eric Orthb30bc172018-08-17 21:09:57672 DCHECK(!parameters_.is_speculative);
Eric Orth70992982018-07-24 00:25:00673
674 address_results_ = address_results;
675 }
676
677 void ChangeRequestPriority(RequestPriority priority);
678
679 void AssignJob(Job* job) {
680 DCHECK(job);
681 DCHECK(!job_);
682
683 job_ = job;
684 }
685
686 // Unassigns the Job without calling completion callback.
maksim.sisov31452af2016-07-27 06:38:10687 void OnJobCancelled(Job* job) {
688 DCHECK_EQ(job_, job);
wezb9820d42016-06-22 23:41:04689 job_ = nullptr;
Eric Orth70992982018-07-24 00:25:00690 DCHECK(!complete_);
691 DCHECK(callback_);
[email protected]aa22b242011-11-16 18:58:29692 callback_.Reset();
Eric Orth70992982018-07-24 00:25:00693
694 // No results should be set.
695 DCHECK(!address_results_);
[email protected]b59ff372009-07-15 22:04:32696 }
697
Eric Orth70992982018-07-24 00:25:00698 // Cleans up Job assignment, marks request completed, and calls the completion
699 // callback.
700 void OnJobCompleted(Job* job, int error) {
maksim.sisov31452af2016-07-27 06:38:10701 DCHECK_EQ(job_, job);
maksim.sisov31452af2016-07-27 06:38:10702 job_ = nullptr;
Eric Orth70992982018-07-24 00:25:00703
704 DCHECK(!complete_);
705 complete_ = true;
706
707 DCHECK(callback_);
Bence Béky0f26a5812018-06-13 03:18:40708 std::move(callback_).Run(error);
[email protected]b59ff372009-07-15 22:04:32709 }
710
Eric Orth70992982018-07-24 00:25:00711 Job* job() const { return job_; }
[email protected]b59ff372009-07-15 22:04:32712
[email protected]0f292de02012-02-01 22:28:20713 // NetLog for the source, passed in HostResolver::Resolve.
tfarina428341112016-09-22 13:38:20714 const NetLogWithSource& source_net_log() { return source_net_log_; }
[email protected]ee094b82010-08-24 15:55:51715
Eric Orth70992982018-07-24 00:25:00716 const HostPortPair& request_host() const { return request_host_; }
717
Eric Orth00fe5a62018-08-15 22:20:00718 const ResolveHostParameters& parameters() const { return parameters_; }
719
Eric Orth322af3e42018-08-20 18:12:59720 HostResolverFlags host_resolver_flags() const { return host_resolver_flags_; }
721
[email protected]5109c1952013-08-20 18:44:10722 RequestPriority priority() const { return priority_; }
juliatuttlec53b19a72016-05-05 13:51:31723 void set_priority(RequestPriority priority) { priority_ = priority; }
[email protected]5109c1952013-08-20 18:44:10724
Eric Orth70992982018-07-24 00:25:00725 bool complete() const { return complete_; }
726
727 base::TimeTicks request_time() const {
728 DCHECK(!request_time_.is_null());
729 return request_time_;
730 }
731 void set_request_time(base::TimeTicks request_time) {
732 DCHECK(request_time_.is_null());
733 DCHECK(!request_time.is_null());
734 request_time_ = request_time;
735 }
[email protected]51b9a6b2012-06-25 21:50:29736
[email protected]b59ff372009-07-15 22:04:32737 private:
tfarina428341112016-09-22 13:38:20738 const NetLogWithSource source_net_log_;
[email protected]54e13772009-08-14 03:01:09739
Eric Orth70992982018-07-24 00:25:00740 const HostPortPair request_host_;
Eric Orth00fe5a62018-08-15 22:20:00741 const ResolveHostParameters parameters_;
Eric Orth322af3e42018-08-20 18:12:59742 const HostResolverFlags host_resolver_flags_;
[email protected]5109c1952013-08-20 18:44:10743
juliatuttlec53b19a72016-05-05 13:51:31744 RequestPriority priority_;
[email protected]b59ff372009-07-15 22:04:32745
[email protected]0f292de02012-02-01 22:28:20746 // The resolve job that this request is dependent on.
[email protected]b59ff372009-07-15 22:04:32747 Job* job_;
Eric Orth70992982018-07-24 00:25:00748 base::WeakPtr<HostResolverImpl> resolver_;
[email protected]b59ff372009-07-15 22:04:32749
750 // The user's callback to invoke when the request completes.
Bence Béky0f26a5812018-06-13 03:18:40751 CompletionOnceCallback callback_;
[email protected]b59ff372009-07-15 22:04:32752
Eric Orth70992982018-07-24 00:25:00753 bool complete_;
754 base::Optional<AddressList> address_results_;
[email protected]b59ff372009-07-15 22:04:32755
Eric Orth70992982018-07-24 00:25:00756 base::TimeTicks request_time_;
[email protected]51b9a6b2012-06-25 21:50:29757
maksim.sisov31452af2016-07-27 06:38:10758 DISALLOW_COPY_AND_ASSIGN(RequestImpl);
[email protected]b59ff372009-07-15 22:04:32759};
760
Eric Orth70992982018-07-24 00:25:00761// Wraps a RequestImpl to implement Request objects from the legacy Resolve()
762// API. The wrapped request must not yet have been started.
763//
764// TODO(crbug.com/821021): Delete this class once all usage has been
765// converted to the new CreateRequest() API.
766class HostResolverImpl::LegacyRequestImpl : public HostResolver::Request {
767 public:
768 explicit LegacyRequestImpl(std::unique_ptr<RequestImpl> inner_request)
769 : inner_request_(std::move(inner_request)) {
770 DCHECK(!inner_request_->job());
771 DCHECK(!inner_request_->complete());
772 }
773
774 ~LegacyRequestImpl() override {}
775
776 void ChangeRequestPriority(RequestPriority priority) override {
777 inner_request_->ChangeRequestPriority(priority);
778 }
779
780 int Start() {
781 return inner_request_->Start(base::BindOnce(
782 &LegacyRequestImpl::LegacyApiCallback, base::Unretained(this)));
783 }
784
785 // Do not call to assign the callback until we are running an async job (after
786 // Start() returns ERR_IO_PENDING) and before completion. Until then, the
787 // legacy HostResolverImpl::Resolve() needs to hang onto |callback| to ensure
788 // it stays alive for the duration of the method call, as some callers may be
789 // binding objects, eg the AddressList, with the callback.
790 void AssignCallback(CompletionOnceCallback callback,
791 AddressList* addresses_result_ptr) {
792 DCHECK(callback);
793 DCHECK(addresses_result_ptr);
794 DCHECK(inner_request_->job());
795 DCHECK(!inner_request_->complete());
796
797 callback_ = std::move(callback);
798 addresses_result_ptr_ = addresses_result_ptr;
799 }
800
801 const RequestImpl& inner_request() const { return *inner_request_; }
802
803 private:
804 // Result callback to bridge results handled entirely via ResolveHostRequest
805 // to legacy API styles where AddressList was a separate method out parameter.
806 void LegacyApiCallback(int error) {
807 // Must call AssignCallback() before async results.
808 DCHECK(callback_);
809
Eric Orthb30bc172018-08-17 21:09:57810 if (error == OK && !inner_request_->parameters().is_speculative) {
Eric Orth70992982018-07-24 00:25:00811 // Legacy API does not allow non-address results (eg TXT), so AddressList
812 // is always expected to be present on OK.
813 DCHECK(inner_request_->GetAddressResults());
814 *addresses_result_ptr_ = inner_request_->GetAddressResults().value();
815 }
816 addresses_result_ptr_ = nullptr;
817 std::move(callback_).Run(error);
818 }
819
820 const std::unique_ptr<RequestImpl> inner_request_;
821
822 CompletionOnceCallback callback_;
823 // This is a caller-provided pointer and should not be used once |callback_|
824 // is invoked.
825 AddressList* addresses_result_ptr_;
826
827 DISALLOW_COPY_AND_ASSIGN(LegacyRequestImpl);
828};
829
[email protected]1e9bbd22010-10-15 16:42:45830//------------------------------------------------------------------------------
831
Francois Doraya2d01ba2017-09-25 19:17:40832// Calls HostResolverProc in TaskScheduler. Performs retries if necessary.
[email protected]0f292de02012-02-01 22:28:20833//
Miriam Gershenson02592182018-03-22 17:42:37834// In non-test code, the HostResolverProc is always SystemHostResolverProc,
835// which calls a platform API that implements host resolution.
836//
[email protected]0f292de02012-02-01 22:28:20837// Whenever we try to resolve the host, we post a delayed task to check if host
838// resolution (OnLookupComplete) is completed or not. If the original attempt
839// hasn't completed, then we start another attempt for host resolution. We take
840// the results from the first attempt that finishes and ignore the results from
841// all other attempts.
842//
843// TODO(szym): Move to separate source file for testing and mocking.
844//
Eric Orth9a037562018-07-03 21:24:38845class HostResolverImpl::ProcTask {
[email protected]b59ff372009-07-15 22:04:32846 public:
Eric Orth9a037562018-07-03 21:24:38847 typedef base::OnceCallback<void(int net_error, const AddressList& addr_list)>
848 Callback;
[email protected]b59ff372009-07-15 22:04:32849
[email protected]0f292de02012-02-01 22:28:20850 ProcTask(const Key& key,
851 const ProcTaskParams& params,
Eric Orth9a037562018-07-03 21:24:38852 Callback callback,
Miriam Gershensone42adb22017-10-16 16:19:38853 scoped_refptr<base::TaskRunner> proc_task_runner,
Misha Efimovb99e7da2018-05-30 16:59:02854 const NetLogWithSource& job_net_log,
855 const base::TickClock* tick_clock)
[email protected]0f292de02012-02-01 22:28:20856 : key_(key),
857 params_(params),
Eric Orth9a037562018-07-03 21:24:38858 callback_(std::move(callback)),
mmenke91c17162016-06-02 16:03:23859 network_task_runner_(base::ThreadTaskRunnerHandle::Get()),
Miriam Gershensone42adb22017-10-16 16:19:38860 proc_task_runner_(std::move(proc_task_runner)),
[email protected]0f292de02012-02-01 22:28:20861 attempt_number_(0),
Misha Efimovb99e7da2018-05-30 16:59:02862 net_log_(job_net_log),
Eric Orth9a037562018-07-03 21:24:38863 tick_clock_(tick_clock),
864 weak_ptr_factory_(this) {
865 DCHECK(callback_);
[email protected]90499482013-06-01 00:39:50866 if (!params_.resolver_proc.get())
[email protected]0f292de02012-02-01 22:28:20867 params_.resolver_proc = HostResolverProc::GetDefault();
868 // If default is unset, use the system proc.
[email protected]90499482013-06-01 00:39:50869 if (!params_.resolver_proc.get())
[email protected]1ee9afa12013-04-16 14:18:06870 params_.resolver_proc = new SystemHostResolverProc();
[email protected]b59ff372009-07-15 22:04:32871 }
872
Eric Orth9a037562018-07-03 21:24:38873 // Cancels this ProcTask. Any outstanding resolve attempts running on worker
874 // thread will continue running, but they will post back to the network thread
875 // before checking their WeakPtrs to find that this task is cancelled.
876 ~ProcTask() {
877 DCHECK(network_task_runner_->BelongsToCurrentThread());
878
879 // If this is cancellation, log the EndEvent (otherwise this was logged in
880 // OnLookupComplete()).
881 if (!was_completed())
882 net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_IMPL_PROC_TASK);
883 }
884
[email protected]b59ff372009-07-15 22:04:32885 void Start() {
mmenke91c17162016-06-02 16:03:23886 DCHECK(network_task_runner_->BelongsToCurrentThread());
Eric Orth9a037562018-07-03 21:24:38887 DCHECK(!was_completed());
mikecirone8b85c432016-09-08 19:11:00888 net_log_.BeginEvent(NetLogEventType::HOST_RESOLVER_IMPL_PROC_TASK);
[email protected]189163e2011-05-11 01:48:54889 StartLookupAttempt();
890 }
[email protected]252b699b2010-02-05 21:38:06891
Eric Orth9a037562018-07-03 21:24:38892 bool was_completed() const {
mmenke91c17162016-06-02 16:03:23893 DCHECK(network_task_runner_->BelongsToCurrentThread());
[email protected]0f292de02012-02-01 22:28:20894 return callback_.is_null();
895 }
896
[email protected]0f292de02012-02-01 22:28:20897 private:
Eric Orth9a037562018-07-03 21:24:38898 using AttemptCompletionCallback = base::OnceCallback<
899 void(const AddressList& results, int error, const int os_error)>;
[email protected]a9813302012-04-28 09:29:28900
[email protected]189163e2011-05-11 01:48:54901 void StartLookupAttempt() {
mmenke91c17162016-06-02 16:03:23902 DCHECK(network_task_runner_->BelongsToCurrentThread());
Eric Orth9a037562018-07-03 21:24:38903 DCHECK(!was_completed());
Misha Efimovb99e7da2018-05-30 16:59:02904 base::TimeTicks start_time = tick_clock_->NowTicks();
[email protected]189163e2011-05-11 01:48:54905 ++attempt_number_;
906 // Dispatch the lookup attempt to a worker thread.
Eric Orth9a037562018-07-03 21:24:38907 AttemptCompletionCallback completion_callback = base::BindOnce(
908 &ProcTask::OnLookupAttemptComplete, weak_ptr_factory_.GetWeakPtr(),
909 start_time, attempt_number_, tick_clock_);
Miriam Gershensone42adb22017-10-16 16:19:38910 proc_task_runner_->PostTask(
Francois Doraya2d01ba2017-09-25 19:17:40911 FROM_HERE,
Eric Orth9a037562018-07-03 21:24:38912 base::BindOnce(&ProcTask::DoLookup, key_, params_.resolver_proc,
913 network_task_runner_, std::move(completion_callback)));
[email protected]13024882011-05-18 23:19:16914
mikecirone8b85c432016-09-08 19:11:00915 net_log_.AddEvent(NetLogEventType::HOST_RESOLVER_IMPL_ATTEMPT_STARTED,
tfarina5e24b242015-10-27 13:11:28916 NetLog::IntCallback("attempt_number", attempt_number_));
[email protected]13024882011-05-18 23:19:16917
mmenke91c17162016-06-02 16:03:23918 // If the results aren't received within a given time, RetryIfNotComplete
919 // will start a new attempt if none of the outstanding attempts have
920 // completed yet.
Eric Orth9a037562018-07-03 21:24:38921 // Use a WeakPtr to avoid keeping the ProcTask alive after completion or
922 // cancellation.
[email protected]0f292de02012-02-01 22:28:20923 if (attempt_number_ <= params_.max_retry_attempts) {
mmenke91c17162016-06-02 16:03:23924 network_task_runner_->PostDelayedTask(
Eric Orth9a037562018-07-03 21:24:38925 FROM_HERE,
926 base::BindOnce(&ProcTask::StartLookupAttempt,
927 weak_ptr_factory_.GetWeakPtr()),
928 params_.unresponsive_delay *
929 std::pow(params_.retry_factor, attempt_number_ - 1));
[email protected]06ef6d92011-05-19 04:24:58930 }
[email protected]b59ff372009-07-15 22:04:32931 }
932
Francois Doraya2d01ba2017-09-25 19:17:40933 // WARNING: This code runs in TaskScheduler with CONTINUE_ON_SHUTDOWN. The
934 // shutdown code cannot wait for it to finish, so this code must be very
935 // careful about using other objects (like MessageLoops, Singletons, etc).
Eric Orth9a037562018-07-03 21:24:38936 // During shutdown these objects may no longer exist.
937 static void DoLookup(
938 Key key,
939 scoped_refptr<HostResolverProc> resolver_proc,
940 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
941 AttemptCompletionCallback completion_callback) {
[email protected]189163e2011-05-11 01:48:54942 AddressList results;
943 int os_error = 0;
Eric Orth9a037562018-07-03 21:24:38944 int error =
945 resolver_proc->Resolve(key.hostname, key.address_family,
946 key.host_resolver_flags, &results, &os_error);
[email protected]b59ff372009-07-15 22:04:32947
Eric Orth9a037562018-07-03 21:24:38948 network_task_runner->PostTask(
949 FROM_HERE, base::BindOnce(std::move(completion_callback), results,
950 error, os_error));
[email protected]189163e2011-05-11 01:48:54951 }
952
Eric Orth9a037562018-07-03 21:24:38953 // Callback for when DoLookup() completes (runs on task runner thread). Now
954 // that we're back in the network thread, checks that |proc_task| is still
955 // valid, and if so, passes back to the object.
956 static void OnLookupAttemptComplete(base::WeakPtr<ProcTask> proc_task,
957 const base::TimeTicks& start_time,
958 const uint32_t attempt_number,
959 const base::TickClock* tick_clock,
960 const AddressList& results,
961 int error,
962 const int os_error) {
Luciano Pachecob4426082018-07-02 08:04:18963 TRACE_EVENT0(kNetTracingCategory, "ProcTask::OnLookupComplete");
Eric Orth9a037562018-07-03 21:24:38964
[email protected]49b70b222013-05-07 21:24:23965 // If results are empty, we should return an error.
966 bool empty_list_on_ok = (error == OK && results.empty());
[email protected]49b70b222013-05-07 21:24:23967 if (empty_list_on_ok)
968 error = ERR_NAME_NOT_RESOLVED;
[email protected]189163e2011-05-11 01:48:54969
[email protected]2d3b7762010-10-09 00:35:47970 // Ideally the following code would be part of host_resolver_proc.cc,
[email protected]b3601bc22012-02-21 21:23:20971 // however it isn't safe to call NetworkChangeNotifier from worker threads.
mmenke91c17162016-06-02 16:03:23972 // So do it here on the IO thread instead.
[email protected]189163e2011-05-11 01:48:54973 if (error != OK && NetworkChangeNotifier::IsOffline())
974 error = ERR_INTERNET_DISCONNECTED;
[email protected]2d3b7762010-10-09 00:35:47975
Eric Orth9a037562018-07-03 21:24:38976 RecordAttemptHistograms(start_time, attempt_number, error, os_error,
977 tick_clock);
Luciano Pachecob4426082018-07-02 08:04:18978
Eric Orth9a037562018-07-03 21:24:38979 if (!proc_task) {
980 RecordDiscardedAttemptHistograms(attempt_number);
Luciano Pachecob4426082018-07-02 08:04:18981 return;
Eric Orth9a037562018-07-03 21:24:38982 }
983
984 proc_task->OnLookupComplete(results, start_time, attempt_number, error,
985 os_error);
986 }
987
988 void OnLookupComplete(const AddressList& results,
989 const base::TimeTicks& start_time,
990 const uint32_t attempt_number,
991 int error,
992 const int os_error) {
993 DCHECK(network_task_runner_->BelongsToCurrentThread());
994 DCHECK(!was_completed());
995
996 // Invalidate WeakPtrs to cancel handling of all outstanding lookup attempts
997 // and retries.
998 weak_ptr_factory_.InvalidateWeakPtrs();
999
1000 RecordTaskHistograms(start_time, error, os_error, attempt_number);
Luciano Pachecob4426082018-07-02 08:04:181001
Eric Orthcb8862f2018-06-27 18:08:351002 NetLogParametersCallback net_log_callback;
Eric Orth9a037562018-07-03 21:24:381003 NetLogParametersCallback attempt_net_log_callback;
[email protected]0f292de02012-02-01 22:28:201004 if (error != OK) {
Eric Orth70992982018-07-24 00:25:001005 net_log_callback = base::BindRepeating(&NetLogProcTaskFailedCallback, 0,
1006 error, os_error);
1007 attempt_net_log_callback = base::BindRepeating(
1008 &NetLogProcTaskFailedCallback, attempt_number, error, os_error);
[email protected]ee094b82010-08-24 15:55:511009 } else {
Eric Orth9a037562018-07-03 21:24:381010 net_log_callback = results.CreateNetLogCallback();
1011 attempt_net_log_callback =
1012 NetLog::IntCallback("attempt_number", attempt_number);
[email protected]ee094b82010-08-24 15:55:511013 }
mikecirone8b85c432016-09-08 19:11:001014 net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_IMPL_PROC_TASK,
[email protected]cd565142012-06-12 16:21:451015 net_log_callback);
Eric Orth9a037562018-07-03 21:24:381016 net_log_.AddEvent(NetLogEventType::HOST_RESOLVER_IMPL_ATTEMPT_FINISHED,
1017 attempt_net_log_callback);
[email protected]ee094b82010-08-24 15:55:511018
Eric Orth9a037562018-07-03 21:24:381019 std::move(callback_).Run(error, results);
[email protected]b59ff372009-07-15 22:04:321020 }
1021
Miriam Gershenson61604662017-09-28 23:51:111022 void RecordTaskHistograms(const base::TimeTicks& start_time,
1023 const int error,
Eric Orth9a037562018-07-03 21:24:381024 const int os_error,
1025 const uint32_t attempt_number) const {
mmenke91c17162016-06-02 16:03:231026 DCHECK(network_task_runner_->BelongsToCurrentThread());
Misha Efimovb99e7da2018-05-30 16:59:021027 base::TimeDelta duration = tick_clock_->NowTicks() - start_time;
Eric Orth9a037562018-07-03 21:24:381028 if (error == OK) {
Miriam Gershenson61604662017-09-28 23:51:111029 UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ProcTask.SuccessTime", duration);
Eric Orth9a037562018-07-03 21:24:381030 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptFirstSuccess", attempt_number, 100);
1031 } else {
Miriam Gershenson61604662017-09-28 23:51:111032 UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ProcTask.FailureTime", duration);
Eric Orth9a037562018-07-03 21:24:381033 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptFirstFailure", attempt_number, 100);
1034 }
[email protected]7e96d792011-06-10 17:08:231035
Miriam Gershenson61604662017-09-28 23:51:111036 UMA_HISTOGRAM_CUSTOM_ENUMERATION(kOSErrorsForGetAddrinfoHistogramName,
1037 std::abs(os_error),
1038 GetAllGetAddrinfoOSErrors());
[email protected]1e9bbd22010-10-15 16:42:451039 }
1040
Eric Orth9a037562018-07-03 21:24:381041 static void RecordAttemptHistograms(const base::TimeTicks& start_time,
1042 const uint32_t attempt_number,
1043 const int error,
1044 const int os_error,
1045 const base::TickClock* tick_clock) {
1046 base::TimeDelta duration = tick_clock->NowTicks() - start_time;
1047 if (error == OK) {
Luciano Pachecob4426082018-07-02 08:04:181048 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptSuccess", attempt_number, 100);
Luciano Pachecob4426082018-07-02 08:04:181049 UMA_HISTOGRAM_LONG_TIMES_100("DNS.AttemptSuccessDuration", duration);
Eric Orth9a037562018-07-03 21:24:381050 } else {
1051 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptFailure", attempt_number, 100);
Luciano Pachecob4426082018-07-02 08:04:181052 UMA_HISTOGRAM_LONG_TIMES_100("DNS.AttemptFailDuration", duration);
Eric Orth9a037562018-07-03 21:24:381053 }
[email protected]189163e2011-05-11 01:48:541054 }
[email protected]1e9bbd22010-10-15 16:42:451055
Eric Orth9a037562018-07-03 21:24:381056 static void RecordDiscardedAttemptHistograms(const uint32_t attempt_number) {
1057 // Count those attempts which completed after the job was already canceled
1058 // OR after the job was already completed by an earlier attempt (so
1059 // cancelled in effect).
1060 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptDiscarded", attempt_number, 100);
1061 }
1062
[email protected]123ab1e32009-10-21 19:12:571063 Key key_;
[email protected]b59ff372009-07-15 22:04:321064
[email protected]0f292de02012-02-01 22:28:201065 // Holds an owning reference to the HostResolverProc that we are going to use.
[email protected]b59ff372009-07-15 22:04:321066 // This may not be the current resolver procedure by the time we call
1067 // ResolveAddrInfo, but that's OK... we'll use it anyways, and the owning
1068 // reference ensures that it remains valid until we are done.
[email protected]0f292de02012-02-01 22:28:201069 ProcTaskParams params_;
[email protected]b59ff372009-07-15 22:04:321070
[email protected]0f292de02012-02-01 22:28:201071 // The listener to the results of this ProcTask.
1072 Callback callback_;
1073
mmenke91c17162016-06-02 16:03:231074 // Used to post events onto the network thread.
1075 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
Miriam Gershensone42adb22017-10-16 16:19:381076 // Used to post blocking HostResolverProc tasks.
1077 scoped_refptr<base::TaskRunner> proc_task_runner_;
[email protected]189163e2011-05-11 01:48:541078
1079 // Keeps track of the number of attempts we have made so far to resolve the
1080 // host. Whenever we start an attempt to resolve the host, we increase this
1081 // number.
Avi Drissman13fc8932015-12-20 04:40:461082 uint32_t attempt_number_;
[email protected]189163e2011-05-11 01:48:541083
tfarina428341112016-09-22 13:38:201084 NetLogWithSource net_log_;
[email protected]ee094b82010-08-24 15:55:511085
Misha Efimovb99e7da2018-05-30 16:59:021086 const base::TickClock* tick_clock_;
1087
Eric Orth9a037562018-07-03 21:24:381088 // Used to loop back from the blocking lookup attempt tasks as well as from
1089 // delayed retry tasks. Invalidate WeakPtrs on completion and cancellation to
1090 // cancel handling of such posted tasks.
1091 base::WeakPtrFactory<ProcTask> weak_ptr_factory_;
1092
[email protected]0f292de02012-02-01 22:28:201093 DISALLOW_COPY_AND_ASSIGN(ProcTask);
[email protected]b59ff372009-07-15 22:04:321094};
1095
1096//-----------------------------------------------------------------------------
1097
Miriam Gershenson02592182018-03-22 17:42:371098// Resolves the hostname using DnsTransaction, which is a full implementation of
1099// a DNS stub resolver. One DnsTransaction is created for each resolution
1100// needed, which for AF_UNSPEC resolutions includes both A and AAAA. The
1101// transactions are scheduled separately and started separately.
1102//
[email protected]b3601bc22012-02-21 21:23:201103// TODO(szym): This could be moved to separate source file as well.
[email protected]0adcb2b2012-08-15 21:30:461104class HostResolverImpl::DnsTask : public base::SupportsWeakPtr<DnsTask> {
[email protected]b3601bc22012-02-21 21:23:201105 public:
[email protected]daae1322013-09-05 18:26:501106 class Delegate {
1107 public:
1108 virtual void OnDnsTaskComplete(base::TimeTicks start_time,
1109 int net_error,
1110 const AddressList& addr_list,
1111 base::TimeDelta ttl) = 0;
1112
1113 // Called when the first of two jobs succeeds. If the first completed
1114 // transaction fails, this is not called. Also not called when the DnsTask
1115 // only needs to run one transaction.
1116 virtual void OnFirstDnsTransactionComplete() = 0;
1117
Brad Lassey786929ad2018-02-21 20:54:271118 virtual URLRequestContext* url_request_context() = 0;
1119 virtual RequestPriority priority() const = 0;
1120
[email protected]daae1322013-09-05 18:26:501121 protected:
Chris Watkins68b15032017-12-01 03:07:131122 Delegate() = default;
1123 virtual ~Delegate() = default;
[email protected]daae1322013-09-05 18:26:501124 };
[email protected]b3601bc22012-02-21 21:23:201125
[email protected]0adcb2b2012-08-15 21:30:461126 DnsTask(DnsClient* client,
[email protected]b3601bc22012-02-21 21:23:201127 const Key& key,
[email protected]daae1322013-09-05 18:26:501128 Delegate* delegate,
Misha Efimovb99e7da2018-05-30 16:59:021129 const NetLogWithSource& job_net_log,
1130 const base::TickClock* tick_clock)
[email protected]0adcb2b2012-08-15 21:30:461131 : client_(client),
[email protected]daae1322013-09-05 18:26:501132 key_(key),
1133 delegate_(delegate),
1134 net_log_(job_net_log),
1135 num_completed_transactions_(0),
Misha Efimovb99e7da2018-05-30 16:59:021136 tick_clock_(tick_clock),
1137 task_start_time_(tick_clock_->NowTicks()) {
[email protected]0adcb2b2012-08-15 21:30:461138 DCHECK(client);
[email protected]daae1322013-09-05 18:26:501139 DCHECK(delegate_);
[email protected]1affed62013-08-21 03:24:501140 }
1141
[email protected]daae1322013-09-05 18:26:501142 bool needs_two_transactions() const {
1143 return key_.address_family == ADDRESS_FAMILY_UNSPECIFIED;
1144 }
1145
1146 bool needs_another_transaction() const {
1147 return needs_two_transactions() && !transaction_aaaa_;
1148 }
1149
1150 void StartFirstTransaction() {
1151 DCHECK_EQ(0u, num_completed_transactions_);
mikecirone8b85c432016-09-08 19:11:001152 net_log_.BeginEvent(NetLogEventType::HOST_RESOLVER_IMPL_DNS_TASK);
[email protected]daae1322013-09-05 18:26:501153 if (key_.address_family == ADDRESS_FAMILY_IPV6) {
1154 StartAAAA();
1155 } else {
1156 StartA();
1157 }
1158 }
1159
1160 void StartSecondTransaction() {
1161 DCHECK(needs_two_transactions());
1162 StartAAAA();
[email protected]70c04ab2013-08-22 16:05:121163 }
1164
Brad Lassey2e8f185d2018-05-21 22:25:211165 base::TimeDelta ttl() { return ttl_; }
1166
[email protected]70c04ab2013-08-22 16:05:121167 private:
[email protected]daae1322013-09-05 18:26:501168 void StartA() {
1169 DCHECK(!transaction_a_);
1170 DCHECK_NE(ADDRESS_FAMILY_IPV6, key_.address_family);
1171 transaction_a_ = CreateTransaction(ADDRESS_FAMILY_IPV4);
1172 transaction_a_->Start();
1173 }
1174
1175 void StartAAAA() {
1176 DCHECK(!transaction_aaaa_);
1177 DCHECK_NE(ADDRESS_FAMILY_IPV4, key_.address_family);
1178 transaction_aaaa_ = CreateTransaction(ADDRESS_FAMILY_IPV6);
1179 transaction_aaaa_->Start();
1180 }
1181
danakj22f90e72016-04-16 01:55:401182 std::unique_ptr<DnsTransaction> CreateTransaction(AddressFamily family) {
[email protected]daae1322013-09-05 18:26:501183 DCHECK_NE(ADDRESS_FAMILY_UNSPECIFIED, family);
Brad Lassey786929ad2018-02-21 20:54:271184 std::unique_ptr<DnsTransaction> trans =
1185 client_->GetTransactionFactory()->CreateTransaction(
1186 key_.hostname,
1187 family == ADDRESS_FAMILY_IPV6 ? dns_protocol::kTypeAAAA
1188 : dns_protocol::kTypeA,
Brad Lasseydba0a84b2018-02-23 22:18:531189 base::BindOnce(&DnsTask::OnTransactionComplete,
Misha Efimovb99e7da2018-05-30 16:59:021190 base::Unretained(this), tick_clock_->NowTicks()),
Brad Lassey786929ad2018-02-21 20:54:271191 net_log_);
1192 trans->SetRequestContext(delegate_->url_request_context());
1193 trans->SetRequestPriority(delegate_->priority());
1194 return trans;
[email protected]daae1322013-09-05 18:26:501195 }
1196
1197 void OnTransactionComplete(const base::TimeTicks& start_time,
[email protected]1def74c2012-03-22 20:07:001198 DnsTransaction* transaction,
[email protected]b3601bc22012-02-21 21:23:201199 int net_error,
1200 const DnsResponse* response) {
[email protected]add76532012-03-30 14:47:471201 DCHECK(transaction);
Misha Efimovb99e7da2018-05-30 16:59:021202 base::TimeDelta duration = tick_clock_->NowTicks() - start_time;
Brad Lassey2e8f185d2018-05-21 22:25:211203 if (net_error != OK && !(net_error == ERR_NAME_NOT_RESOLVED && response &&
1204 response->IsValid())) {
Miriam Gershenson4e7c9ecf2017-09-26 23:17:211205 UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.TransactionFailure", duration);
[email protected]0adcb2b2012-08-15 21:30:461206 OnFailure(net_error, DnsResponse::DNS_PARSE_OK);
1207 return;
[email protected]6c411902012-08-14 22:36:361208 }
[email protected]0adcb2b2012-08-15 21:30:461209
Miriam Gershenson4e7c9ecf2017-09-26 23:17:211210 UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.TransactionSuccess", duration);
[email protected]02cd6982013-01-10 20:12:511211 switch (transaction->GetType()) {
1212 case dns_protocol::kTypeA:
Miriam Gershenson4e7c9ecf2017-09-26 23:17:211213 UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.TransactionSuccess_A", duration);
[email protected]02cd6982013-01-10 20:12:511214 break;
1215 case dns_protocol::kTypeAAAA:
Miriam Gershenson4e7c9ecf2017-09-26 23:17:211216 UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.TransactionSuccess_AAAA",
1217 duration);
[email protected]02cd6982013-01-10 20:12:511218 break;
1219 }
[email protected]daae1322013-09-05 18:26:501220
[email protected]0adcb2b2012-08-15 21:30:461221 AddressList addr_list;
1222 base::TimeDelta ttl;
1223 DnsResponse::Result result = response->ParseToAddressList(&addr_list, &ttl);
1224 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ParseToAddressList",
1225 result,
1226 DnsResponse::DNS_PARSE_RESULT_MAX);
1227 if (result != DnsResponse::DNS_PARSE_OK) {
1228 // Fail even if the other query succeeds.
1229 OnFailure(ERR_DNS_MALFORMED_RESPONSE, result);
1230 return;
1231 }
1232
[email protected]daae1322013-09-05 18:26:501233 ++num_completed_transactions_;
1234 if (num_completed_transactions_ == 1) {
1235 ttl_ = ttl;
[email protected]0adcb2b2012-08-15 21:30:461236 } else {
[email protected]daae1322013-09-05 18:26:501237 ttl_ = std::min(ttl_, ttl);
[email protected]0adcb2b2012-08-15 21:30:461238 }
1239
[email protected]daae1322013-09-05 18:26:501240 if (transaction->GetType() == dns_protocol::kTypeA) {
1241 DCHECK_EQ(transaction_a_.get(), transaction);
1242 // Place IPv4 addresses after IPv6.
1243 addr_list_.insert(addr_list_.end(), addr_list.begin(), addr_list.end());
1244 } else {
1245 DCHECK_EQ(transaction_aaaa_.get(), transaction);
1246 // Place IPv6 addresses before IPv4.
1247 addr_list_.insert(addr_list_.begin(), addr_list.begin(), addr_list.end());
1248 }
1249
1250 if (needs_two_transactions() && num_completed_transactions_ == 1) {
1251 // No need to repeat the suffix search.
1252 key_.hostname = transaction->GetHostname();
1253 delegate_->OnFirstDnsTransactionComplete();
1254 return;
1255 }
1256
1257 if (addr_list_.empty()) {
[email protected]70c04ab2013-08-22 16:05:121258 // TODO(szym): Don't fallback to ProcTask in this case.
1259 OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK);
[email protected]0adcb2b2012-08-15 21:30:461260 return;
1261 }
1262
[email protected]daae1322013-09-05 18:26:501263 // If there are multiple addresses, and at least one is IPv6, need to sort
1264 // them. Note that IPv6 addresses are always put before IPv4 ones, so it's
1265 // sufficient to just check the family of the first address.
1266 if (addr_list_.size() > 1 &&
1267 addr_list_[0].GetFamily() == ADDRESS_FAMILY_IPV6) {
1268 // Sort addresses if needed. Sort could complete synchronously.
[email protected]0adcb2b2012-08-15 21:30:461269 client_->GetAddressSorter()->Sort(
Bence Békyd5e474c2018-08-02 18:45:081270 addr_list_, base::BindOnce(&DnsTask::OnSortComplete, AsWeakPtr(),
1271 tick_clock_->NowTicks()));
[email protected]0adcb2b2012-08-15 21:30:461272 } else {
[email protected]daae1322013-09-05 18:26:501273 OnSuccess(addr_list_);
[email protected]0adcb2b2012-08-15 21:30:461274 }
1275 }
1276
1277 void OnSortComplete(base::TimeTicks start_time,
[email protected]0adcb2b2012-08-15 21:30:461278 bool success,
1279 const AddressList& addr_list) {
1280 if (!success) {
Miriam Gershenson4e7c9ecf2017-09-26 23:17:211281 UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.SortFailure",
Misha Efimovb99e7da2018-05-30 16:59:021282 tick_clock_->NowTicks() - start_time);
[email protected]0adcb2b2012-08-15 21:30:461283 OnFailure(ERR_DNS_SORT_ERROR, DnsResponse::DNS_PARSE_OK);
1284 return;
1285 }
1286
Miriam Gershenson4e7c9ecf2017-09-26 23:17:211287 UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.SortSuccess",
Misha Efimovb99e7da2018-05-30 16:59:021288 tick_clock_->NowTicks() - start_time);
[email protected]0adcb2b2012-08-15 21:30:461289
1290 // AddressSorter prunes unusable destinations.
1291 if (addr_list.empty()) {
1292 LOG(WARNING) << "Address list empty after RFC3484 sort";
1293 OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK);
1294 return;
1295 }
1296
[email protected]daae1322013-09-05 18:26:501297 OnSuccess(addr_list);
[email protected]0adcb2b2012-08-15 21:30:461298 }
1299
1300 void OnFailure(int net_error, DnsResponse::Result result) {
1301 DCHECK_NE(OK, net_error);
[email protected]cd565142012-06-12 16:21:451302 net_log_.EndEvent(
mikecirone8b85c432016-09-08 19:11:001303 NetLogEventType::HOST_RESOLVER_IMPL_DNS_TASK,
[email protected]cd565142012-06-12 16:21:451304 base::Bind(&NetLogDnsTaskFailedCallback, net_error, result));
Brad Lassey2e8f185d2018-05-21 22:25:211305 base::TimeDelta ttl = ttl_ < base::TimeDelta::FromSeconds(
1306 std::numeric_limits<uint32_t>::max()) &&
1307 num_completed_transactions_ > 0
1308 ? ttl_
1309 : base::TimeDelta::FromSeconds(0);
Miriam Gershenson66024d72017-12-05 04:30:321310 delegate_->OnDnsTaskComplete(task_start_time_, net_error, AddressList(),
Brad Lassey2e8f185d2018-05-21 22:25:211311 ttl);
[email protected]b3601bc22012-02-21 21:23:201312 }
1313
[email protected]daae1322013-09-05 18:26:501314 void OnSuccess(const AddressList& addr_list) {
mikecirone8b85c432016-09-08 19:11:001315 net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_IMPL_DNS_TASK,
[email protected]0adcb2b2012-08-15 21:30:461316 addr_list.CreateNetLogCallback());
[email protected]daae1322013-09-05 18:26:501317 delegate_->OnDnsTaskComplete(task_start_time_, OK, addr_list, ttl_);
[email protected]0adcb2b2012-08-15 21:30:461318 }
1319
1320 DnsClient* client_;
[email protected]daae1322013-09-05 18:26:501321 Key key_;
1322
[email protected]b3601bc22012-02-21 21:23:201323 // The listener to the results of this DnsTask.
[email protected]daae1322013-09-05 18:26:501324 Delegate* delegate_;
tfarina428341112016-09-22 13:38:201325 const NetLogWithSource net_log_;
[email protected]b3601bc22012-02-21 21:23:201326
danakj22f90e72016-04-16 01:55:401327 std::unique_ptr<DnsTransaction> transaction_a_;
1328 std::unique_ptr<DnsTransaction> transaction_aaaa_;
[email protected]0adcb2b2012-08-15 21:30:461329
[email protected]daae1322013-09-05 18:26:501330 unsigned num_completed_transactions_;
1331
1332 // These are updated as each transaction completes.
1333 base::TimeDelta ttl_;
1334 // IPv6 addresses must appear first in the list.
1335 AddressList addr_list_;
1336
Misha Efimovb99e7da2018-05-30 16:59:021337 const base::TickClock* tick_clock_;
[email protected]daae1322013-09-05 18:26:501338 base::TimeTicks task_start_time_;
[email protected]0adcb2b2012-08-15 21:30:461339
1340 DISALLOW_COPY_AND_ASSIGN(DnsTask);
[email protected]b3601bc22012-02-21 21:23:201341};
1342
1343//-----------------------------------------------------------------------------
1344
[email protected]0f292de02012-02-01 22:28:201345// Aggregates all Requests for the same Key. Dispatched via PriorityDispatch.
[email protected]daae1322013-09-05 18:26:501346class HostResolverImpl::Job : public PrioritizedDispatcher::Job,
1347 public HostResolverImpl::DnsTask::Delegate {
[email protected]68ad3ee2010-01-30 03:45:391348 public:
[email protected]0f292de02012-02-01 22:28:201349 // Creates new job for |key| where |request_net_log| is bound to the
[email protected]16ee26d2012-03-08 03:34:351350 // request that spawned it.
[email protected]12faa4c2012-11-06 04:44:181351 Job(const base::WeakPtr<HostResolverImpl>& resolver,
[email protected]0f292de02012-02-01 22:28:201352 const Key& key,
[email protected]8c98d002012-07-18 19:02:271353 RequestPriority priority,
Miriam Gershensone42adb22017-10-16 16:19:381354 scoped_refptr<base::TaskRunner> proc_task_runner,
Misha Efimovb99e7da2018-05-30 16:59:021355 const NetLogWithSource& source_net_log,
1356 const base::TickClock* tick_clock)
[email protected]12faa4c2012-11-06 04:44:181357 : resolver_(resolver),
[email protected]0f292de02012-02-01 22:28:201358 key_(key),
[email protected]8c98d002012-07-18 19:02:271359 priority_tracker_(priority),
Miriam Gershensone42adb22017-10-16 16:19:381360 proc_task_runner_(std::move(proc_task_runner)),
[email protected]0f292de02012-02-01 22:28:201361 had_non_speculative_request_(false),
[email protected]daae1322013-09-05 18:26:501362 num_occupied_job_slots_(0),
[email protected]1d932852012-06-19 19:40:331363 dns_task_error_(OK),
Misha Efimovb99e7da2018-05-30 16:59:021364 tick_clock_(tick_clock),
1365 creation_time_(tick_clock_->NowTicks()),
[email protected]51b9a6b2012-06-25 21:50:291366 priority_change_time_(creation_time_),
tfarina428341112016-09-22 13:38:201367 net_log_(
1368 NetLogWithSource::Make(source_net_log.net_log(),
mikecirone8b85c432016-09-08 19:11:001369 NetLogSourceType::HOST_RESOLVER_IMPL_JOB)) {
1370 source_net_log.AddEvent(NetLogEventType::HOST_RESOLVER_IMPL_CREATE_JOB);
[email protected]0f292de02012-02-01 22:28:201371
mikecirone8b85c432016-09-08 19:11:001372 net_log_.BeginEvent(NetLogEventType::HOST_RESOLVER_IMPL_JOB,
1373 base::Bind(&NetLogJobCreationCallback,
1374 source_net_log.source(), &key_.hostname));
[email protected]68ad3ee2010-01-30 03:45:391375 }
1376
dchengb03027d2014-10-21 12:00:201377 ~Job() override {
[email protected]b3601bc22012-02-21 21:23:201378 if (is_running()) {
1379 // |resolver_| was destroyed with this Job still in flight.
1380 // Clean-up, record in the log, but don't run any callbacks.
Eric Orth9a037562018-07-03 21:24:381381 proc_task_ = nullptr;
[email protected]16ee26d2012-03-08 03:34:351382 // Clean up now for nice NetLog.
[email protected]daae1322013-09-05 18:26:501383 KillDnsTask();
mikecirone8b85c432016-09-08 19:11:001384 net_log_.EndEventWithNetErrorCode(NetLogEventType::HOST_RESOLVER_IMPL_JOB,
[email protected]b3601bc22012-02-21 21:23:201385 ERR_ABORTED);
1386 } else if (is_queued()) {
[email protected]57a48d32012-03-03 00:04:551387 // |resolver_| was destroyed without running this Job.
[email protected]16ee26d2012-03-08 03:34:351388 // TODO(szym): is there any benefit in having this distinction?
mikecirone8b85c432016-09-08 19:11:001389 net_log_.AddEvent(NetLogEventType::CANCELLED);
1390 net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_IMPL_JOB);
[email protected]68ad3ee2010-01-30 03:45:391391 }
[email protected]b3601bc22012-02-21 21:23:201392 // else CompleteRequests logged EndEvent.
David Benjamina5677192018-04-23 23:25:421393 while (!requests_.empty()) {
maksim.sisov31452af2016-07-27 06:38:101394 // Log any remaining Requests as cancelled.
David Benjamina5677192018-04-23 23:25:421395 RequestImpl* req = requests_.head()->value();
1396 req->RemoveFromList();
1397 DCHECK_EQ(this, req->job());
Eric Orth70992982018-07-24 00:25:001398 LogCancelRequest(req->source_net_log());
David Benjamina5677192018-04-23 23:25:421399 req->OnJobCancelled(this);
[email protected]b3601bc22012-02-21 21:23:201400 }
[email protected]68ad3ee2010-01-30 03:45:391401 }
1402
[email protected]daae1322013-09-05 18:26:501403 // Add this job to the dispatcher. If "at_head" is true, adds at the front
1404 // of the queue.
1405 void Schedule(bool at_head) {
1406 DCHECK(!is_queued());
1407 PrioritizedDispatcher::Handle handle;
1408 if (!at_head) {
[email protected]106ccd2c2014-06-17 09:21:001409 handle = resolver_->dispatcher_->Add(this, priority());
[email protected]daae1322013-09-05 18:26:501410 } else {
[email protected]106ccd2c2014-06-17 09:21:001411 handle = resolver_->dispatcher_->AddAtHead(this, priority());
[email protected]daae1322013-09-05 18:26:501412 }
1413 // The dispatcher could have started |this| in the above call to Add, which
1414 // could have called Schedule again. In that case |handle| will be null,
1415 // but |handle_| may have been set by the other nested call to Schedule.
1416 if (!handle.is_null()) {
1417 DCHECK(handle_.is_null());
1418 handle_ = handle;
1419 }
[email protected]16ee26d2012-03-08 03:34:351420 }
1421
maksim.sisov31452af2016-07-27 06:38:101422 void AddRequest(RequestImpl* request) {
Eric Orth70992982018-07-24 00:25:001423 DCHECK_EQ(key_.hostname, request->request_host().host());
1424
1425 request->AssignJob(this);
[email protected]0f292de02012-02-01 22:28:201426
maksim.sisov31452af2016-07-27 06:38:101427 priority_tracker_.Add(request->priority());
[email protected]0f292de02012-02-01 22:28:201428
maksim.sisov31452af2016-07-27 06:38:101429 request->source_net_log().AddEvent(
mikecirone8b85c432016-09-08 19:11:001430 NetLogEventType::HOST_RESOLVER_IMPL_JOB_ATTACH,
[email protected]cd565142012-06-12 16:21:451431 net_log_.source().ToEventParametersCallback());
[email protected]0f292de02012-02-01 22:28:201432
1433 net_log_.AddEvent(
mikecirone8b85c432016-09-08 19:11:001434 NetLogEventType::HOST_RESOLVER_IMPL_JOB_REQUEST_ATTACH,
maksim.sisov31452af2016-07-27 06:38:101435 base::Bind(&NetLogJobAttachCallback, request->source_net_log().source(),
[email protected]cd565142012-06-12 16:21:451436 priority()));
[email protected]0f292de02012-02-01 22:28:201437
Eric Orthb30bc172018-08-17 21:09:571438 if (!request->parameters().is_speculative)
[email protected]0f292de02012-02-01 22:28:201439 had_non_speculative_request_ = true;
[email protected]b3601bc22012-02-21 21:23:201440
David Benjamina5677192018-04-23 23:25:421441 requests_.Append(request);
[email protected]b3601bc22012-02-21 21:23:201442
[email protected]51b9a6b2012-06-25 21:50:291443 UpdatePriority();
[email protected]68ad3ee2010-01-30 03:45:391444 }
1445
maksim.sisov31452af2016-07-27 06:38:101446 void ChangeRequestPriority(RequestImpl* req, RequestPriority priority) {
Eric Orth70992982018-07-24 00:25:001447 DCHECK_EQ(key_.hostname, req->request_host().host());
juliatuttlec53b19a72016-05-05 13:51:311448
1449 priority_tracker_.Remove(req->priority());
1450 req->set_priority(priority);
1451 priority_tracker_.Add(req->priority());
1452 UpdatePriority();
1453 }
1454
maksim.sisov31452af2016-07-27 06:38:101455 // Detach cancelled request. If it was the last active Request, also finishes
1456 // this Job.
1457 void CancelRequest(RequestImpl* request) {
Eric Orth70992982018-07-24 00:25:001458 DCHECK_EQ(key_.hostname, request->request_host().host());
maksim.sisov31452af2016-07-27 06:38:101459 DCHECK(!requests_.empty());
[email protected]16ee26d2012-03-08 03:34:351460
Eric Orth70992982018-07-24 00:25:001461 LogCancelRequest(request->source_net_log());
[email protected]16ee26d2012-03-08 03:34:351462
maksim.sisov31452af2016-07-27 06:38:101463 priority_tracker_.Remove(request->priority());
1464 net_log_.AddEvent(
mikecirone8b85c432016-09-08 19:11:001465 NetLogEventType::HOST_RESOLVER_IMPL_JOB_REQUEST_DETACH,
maksim.sisov31452af2016-07-27 06:38:101466 base::Bind(&NetLogJobAttachCallback, request->source_net_log().source(),
1467 priority()));
[email protected]b3601bc22012-02-21 21:23:201468
[email protected]16ee26d2012-03-08 03:34:351469 if (num_active_requests() > 0) {
[email protected]51b9a6b2012-06-25 21:50:291470 UpdatePriority();
David Benjamina5677192018-04-23 23:25:421471 request->RemoveFromList();
[email protected]16ee26d2012-03-08 03:34:351472 } else {
1473 // If we were called from a Request's callback within CompleteRequests,
1474 // that Request could not have been cancelled, so num_active_requests()
1475 // could not be 0. Therefore, we are not in CompleteRequests().
[email protected]1339a2a22012-10-17 08:39:431476 CompleteRequestsWithError(OK /* cancelled */);
[email protected]b3601bc22012-02-21 21:23:201477 }
[email protected]68ad3ee2010-01-30 03:45:391478 }
1479
[email protected]7af985a2012-12-14 22:40:421480 // Called from AbortAllInProgressJobs. Completes all requests and destroys
1481 // the job. This currently assumes the abort is due to a network change.
olli.raulaa21e9eb72015-12-17 08:18:111482 // TODO This should not delete |this|.
[email protected]0f292de02012-02-01 22:28:201483 void Abort() {
[email protected]0f292de02012-02-01 22:28:201484 DCHECK(is_running());
[email protected]7af985a2012-12-14 22:40:421485 CompleteRequestsWithError(ERR_NETWORK_CHANGED);
[email protected]b3601bc22012-02-21 21:23:201486 }
1487
[email protected]f0f602bd2012-11-15 18:01:021488 // If DnsTask present, abort it and fall back to ProcTask.
1489 void AbortDnsTask() {
1490 if (dns_task_) {
[email protected]daae1322013-09-05 18:26:501491 KillDnsTask();
[email protected]f0f602bd2012-11-15 18:01:021492 dns_task_error_ = OK;
1493 StartProcTask();
1494 }
1495 }
1496
[email protected]16ee26d2012-03-08 03:34:351497 // Called by HostResolverImpl when this job is evicted due to queue overflow.
1498 // Completes all requests and destroys the job.
1499 void OnEvicted() {
1500 DCHECK(!is_running());
1501 DCHECK(is_queued());
1502 handle_.Reset();
1503
mikecirone8b85c432016-09-08 19:11:001504 net_log_.AddEvent(NetLogEventType::HOST_RESOLVER_IMPL_JOB_EVICTED);
[email protected]16ee26d2012-03-08 03:34:351505
1506 // This signals to CompleteRequests that this job never ran.
[email protected]1339a2a22012-10-17 08:39:431507 CompleteRequestsWithError(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE);
[email protected]16ee26d2012-03-08 03:34:351508 }
1509
[email protected]78eac2a2012-03-14 19:09:271510 // Attempts to serve the job from HOSTS. Returns true if succeeded and
1511 // this Job was destroyed.
1512 bool ServeFromHosts() {
1513 DCHECK_GT(num_active_requests(), 0u);
1514 AddressList addr_list;
Eric Orth70992982018-07-24 00:25:001515 if (resolver_->ServeFromHosts(
1516 key(), requests_.head()->value()->request_host().port(),
1517 &addr_list)) {
[email protected]78eac2a2012-03-14 19:09:271518 // This will destroy the Job.
Rob Percival94f21ad2017-11-14 10:20:241519 CompleteRequests(
1520 MakeCacheEntry(OK, addr_list, HostCache::Entry::SOURCE_HOSTS),
Eric Orth9871aafa2018-10-02 19:59:181521 base::TimeDelta(), true /* allow_cache */);
[email protected]78eac2a2012-03-14 19:09:271522 return true;
1523 }
1524 return false;
1525 }
1526
tanay.c6ddd5f6f2015-08-25 06:34:571527 const Key& key() const { return key_; }
[email protected]b4481b222012-03-16 17:13:111528
1529 bool is_queued() const {
1530 return !handle_.is_null();
1531 }
1532
1533 bool is_running() const {
Eric Orth9871aafa2018-10-02 19:59:181534 return is_dns_running() || is_mdns_running() || is_proc_running();
[email protected]b4481b222012-03-16 17:13:111535 }
1536
[email protected]16ee26d2012-03-08 03:34:351537 private:
[email protected]daae1322013-09-05 18:26:501538 void KillDnsTask() {
1539 if (dns_task_) {
1540 ReduceToOneJobSlot();
1541 dns_task_.reset();
1542 }
1543 }
1544
1545 // Reduce the number of job slots occupied and queued in the dispatcher
1546 // to one. If the second Job slot is queued in the dispatcher, cancels the
1547 // queued job. Otherwise, the second Job has been started by the
1548 // PrioritizedDispatcher, so signals it is complete.
1549 void ReduceToOneJobSlot() {
1550 DCHECK_GE(num_occupied_job_slots_, 1u);
1551 if (is_queued()) {
[email protected]106ccd2c2014-06-17 09:21:001552 resolver_->dispatcher_->Cancel(handle_);
[email protected]daae1322013-09-05 18:26:501553 handle_.Reset();
1554 } else if (num_occupied_job_slots_ > 1) {
[email protected]106ccd2c2014-06-17 09:21:001555 resolver_->dispatcher_->OnJobFinished();
[email protected]daae1322013-09-05 18:26:501556 --num_occupied_job_slots_;
1557 }
1558 DCHECK_EQ(1u, num_occupied_job_slots_);
1559 }
1560
eroman0cd87b62016-12-14 19:13:451561 // MakeCacheEntry() and MakeCacheEntryWithTTL() are helpers to build a
1562 // HostCache::Entry(). The address list is omited from the cache entry
1563 // for errors.
1564 HostCache::Entry MakeCacheEntry(int net_error,
Rob Percival94f21ad2017-11-14 10:20:241565 const AddressList& addr_list,
1566 HostCache::Entry::Source source) const {
eroman0cd87b62016-12-14 19:13:451567 return HostCache::Entry(
1568 net_error,
Rob Percival94f21ad2017-11-14 10:20:241569 net_error == OK ? MakeAddressListForRequest(addr_list) : AddressList(),
1570 source);
eroman0cd87b62016-12-14 19:13:451571 }
1572
1573 HostCache::Entry MakeCacheEntryWithTTL(int net_error,
1574 const AddressList& addr_list,
Rob Percival94f21ad2017-11-14 10:20:241575 HostCache::Entry::Source source,
eroman0cd87b62016-12-14 19:13:451576 base::TimeDelta ttl) const {
1577 return HostCache::Entry(
1578 net_error,
1579 net_error == OK ? MakeAddressListForRequest(addr_list) : AddressList(),
Rob Percival94f21ad2017-11-14 10:20:241580 source, ttl);
eroman0cd87b62016-12-14 19:13:451581 }
1582
juliatuttlec53b19a72016-05-05 13:51:311583 AddressList MakeAddressListForRequest(const AddressList& list) const {
1584 if (requests_.empty())
1585 return list;
Eric Orth70992982018-07-24 00:25:001586 return AddressList::CopyWithPort(
1587 list, requests_.head()->value()->request_host().port());
juliatuttlec53b19a72016-05-05 13:51:311588 }
1589
[email protected]51b9a6b2012-06-25 21:50:291590 void UpdatePriority() {
1591 if (is_queued()) {
1592 if (priority() != static_cast<RequestPriority>(handle_.priority()))
Misha Efimovb99e7da2018-05-30 16:59:021593 priority_change_time_ = tick_clock_->NowTicks();
[email protected]106ccd2c2014-06-17 09:21:001594 handle_ = resolver_->dispatcher_->ChangePriority(handle_, priority());
[email protected]51b9a6b2012-06-25 21:50:291595 }
1596 }
1597
[email protected]16ee26d2012-03-08 03:34:351598 // PriorityDispatch::Job:
dchengb03027d2014-10-21 12:00:201599 void Start() override {
[email protected]daae1322013-09-05 18:26:501600 DCHECK_LE(num_occupied_job_slots_, 1u);
1601
[email protected]70c04ab2013-08-22 16:05:121602 handle_.Reset();
[email protected]daae1322013-09-05 18:26:501603 ++num_occupied_job_slots_;
1604
1605 if (num_occupied_job_slots_ == 2) {
1606 StartSecondDnsTransaction();
1607 return;
1608 }
1609
1610 DCHECK(!is_running());
[email protected]0f292de02012-02-01 22:28:201611
mikecirone8b85c432016-09-08 19:11:001612 net_log_.AddEvent(NetLogEventType::HOST_RESOLVER_IMPL_JOB_STARTED);
[email protected]0f292de02012-02-01 22:28:201613
Misha Efimovb99e7da2018-05-30 16:59:021614 start_time_ = tick_clock_->NowTicks();
Miriam Gershenson61604662017-09-28 23:51:111615 base::TimeDelta queue_time = start_time_ - creation_time_;
1616 base::TimeDelta queue_time_after_change =
1617 start_time_ - priority_change_time_;
[email protected]51b9a6b2012-06-25 21:50:291618
Miriam Gershenson90d05e02017-09-28 19:29:281619 DNS_HISTOGRAM_BY_PRIORITY("Net.DNS.JobQueueTime", priority(), queue_time);
1620 DNS_HISTOGRAM_BY_PRIORITY("Net.DNS.JobQueueTimeAfterChange", priority(),
1621 queue_time_after_change);
[email protected]51b9a6b2012-06-25 21:50:291622
Eric Orthdc35748e2018-08-23 22:41:481623 switch (key_.host_resolver_source) {
1624 case HostResolverSource::ANY:
1625 if (resolver_->HaveDnsConfig() &&
Eric Orth9871aafa2018-10-02 19:59:181626 !ResemblesMulticastDNSName(key_.hostname) &&
1627 !(key_.host_resolver_flags & HOST_RESOLVER_CANONNAME)) {
Eric Orthdc35748e2018-08-23 22:41:481628 StartDnsTask();
1629 } else {
1630 StartProcTask();
1631 }
1632 break;
1633 case HostResolverSource::SYSTEM:
1634 StartProcTask();
1635 break;
1636 case HostResolverSource::DNS:
1637 // DNS source should not be requested unless the resolver is configured
1638 // to handle it.
1639 DCHECK(resolver_->HaveDnsConfig());
1640
1641 StartDnsTask();
1642 break;
Eric Orth9871aafa2018-10-02 19:59:181643 case HostResolverSource::MULTICAST_DNS:
1644 StartMdnsTask();
1645 break;
Eric Orthdc35748e2018-08-23 22:41:481646 }
[email protected]443714fad2013-09-19 04:52:011647
[email protected]1d932852012-06-19 19:40:331648 // Caution: Job::Start must not complete synchronously.
[email protected]b3601bc22012-02-21 21:23:201649 }
1650
[email protected]b3601bc22012-02-21 21:23:201651 // TODO(szym): Since DnsTransaction does not consume threads, we can increase
Francois Doraya2d01ba2017-09-25 19:17:401652 // the limits on |dispatcher_|. But in order to keep the number of
1653 // TaskScheduler threads low, we will need to use an "inner"
1654 // PrioritizedDispatcher with tighter limits.
[email protected]b3601bc22012-02-21 21:23:201655 void StartProcTask() {
Eric Orth9871aafa2018-10-02 19:59:181656 DCHECK(!is_running());
Eric Orth9a037562018-07-03 21:24:381657 proc_task_ = std::make_unique<ProcTask>(
Misha Efimovb99e7da2018-05-30 16:59:021658 key_, resolver_->proc_params_,
Eric Orth70992982018-07-24 00:25:001659 base::BindOnce(&Job::OnProcTaskComplete, base::Unretained(this),
1660 tick_clock_->NowTicks()),
Misha Efimovb99e7da2018-05-30 16:59:021661 proc_task_runner_, net_log_, tick_clock_);
[email protected]0f292de02012-02-01 22:28:201662
[email protected]0f292de02012-02-01 22:28:201663 // Start() could be called from within Resolve(), hence it must NOT directly
1664 // call OnProcTaskComplete, for example, on synchronous failure.
1665 proc_task_->Start();
[email protected]68ad3ee2010-01-30 03:45:391666 }
1667
[email protected]0f292de02012-02-01 22:28:201668 // Called by ProcTask when it completes.
[email protected]e3bd4822012-10-23 18:01:371669 void OnProcTaskComplete(base::TimeTicks start_time,
1670 int net_error,
1671 const AddressList& addr_list) {
[email protected]b3601bc22012-02-21 21:23:201672 DCHECK(is_proc_running());
[email protected]68ad3ee2010-01-30 03:45:391673
[email protected]1d932852012-06-19 19:40:331674 if (dns_task_error_ != OK) {
Misha Efimovb99e7da2018-05-30 16:59:021675 base::TimeDelta duration = tick_clock_->NowTicks() - start_time;
[email protected]1def74c2012-03-22 20:07:001676 if (net_error == OK) {
Miriam Gershenson4e7c9ecf2017-09-26 23:17:211677 UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.FallbackSuccess", duration);
[email protected]1d932852012-06-19 19:40:331678 if ((dns_task_error_ == ERR_NAME_NOT_RESOLVED) &&
1679 ResemblesNetBIOSName(key_.hostname)) {
1680 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_SUSPECT_NETBIOS);
1681 } else {
1682 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_PROC_SUCCESS);
1683 }
Ilya Sherman0eb39802017-12-08 20:58:181684 base::UmaHistogramSparse("Net.DNS.DnsTask.Errors",
1685 std::abs(dns_task_error_));
[email protected]1ffdda82012-12-12 23:04:221686 resolver_->OnDnsTaskResolve(dns_task_error_);
[email protected]1def74c2012-03-22 20:07:001687 } else {
Miriam Gershenson4e7c9ecf2017-09-26 23:17:211688 UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.FallbackFail", duration);
[email protected]1def74c2012-03-22 20:07:001689 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_FAIL);
1690 }
1691 }
1692
eroman1efc237c2016-12-14 00:00:451693 if (ContainsIcannNameCollisionIp(addr_list))
1694 net_error = ERR_ICANN_NAME_COLLISION;
1695
[email protected]1339a2a22012-10-17 08:39:431696 base::TimeDelta ttl =
1697 base::TimeDelta::FromSeconds(kNegativeCacheEntryTTLSeconds);
[email protected]b3601bc22012-02-21 21:23:201698 if (net_error == OK)
1699 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds);
[email protected]68ad3ee2010-01-30 03:45:391700
Rob Percival94f21ad2017-11-14 10:20:241701 // Source unknown because the system resolver could have gotten it from a
1702 // hosts file, its own cache, a DNS lookup or somewhere else.
[email protected]895123222012-10-25 15:21:171703 // Don't store the |ttl| in cache since it's not obtained from the server.
Rob Percival94f21ad2017-11-14 10:20:241704 CompleteRequests(
1705 MakeCacheEntry(net_error, addr_list, HostCache::Entry::SOURCE_UNKNOWN),
Eric Orth9871aafa2018-10-02 19:59:181706 ttl, true /* allow_cache */);
[email protected]b3601bc22012-02-21 21:23:201707 }
1708
1709 void StartDnsTask() {
[email protected]78eac2a2012-03-14 19:09:271710 DCHECK(resolver_->HaveDnsConfig());
[email protected]daae1322013-09-05 18:26:501711 dns_task_.reset(new DnsTask(resolver_->dns_client_.get(), key_, this,
Misha Efimovb99e7da2018-05-30 16:59:021712 net_log_, tick_clock_));
[email protected]b3601bc22012-02-21 21:23:201713
[email protected]daae1322013-09-05 18:26:501714 dns_task_->StartFirstTransaction();
1715 // Schedule a second transaction, if needed.
1716 if (dns_task_->needs_two_transactions())
1717 Schedule(true);
1718 }
1719
1720 void StartSecondDnsTransaction() {
1721 DCHECK(dns_task_->needs_two_transactions());
1722 dns_task_->StartSecondTransaction();
[email protected]16c2bd72013-06-28 01:19:221723 }
1724
1725 // Called if DnsTask fails. It is posted from StartDnsTask, so Job may be
1726 // deleted before this callback. In this case dns_task is deleted as well,
1727 // so we use it as indicator whether Job is still valid.
1728 void OnDnsTaskFailure(const base::WeakPtr<DnsTask>& dns_task,
1729 base::TimeDelta duration,
1730 int net_error) {
Miriam Gershenson61604662017-09-28 23:51:111731 UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.DnsTask.FailureTime", duration);
[email protected]16c2bd72013-06-28 01:19:221732
wezb9820d42016-06-22 23:41:041733 if (!dns_task)
[email protected]16c2bd72013-06-28 01:19:221734 return;
1735
Miriam Gershenson19faef812018-02-07 23:56:441736 if (duration < base::TimeDelta::FromMilliseconds(10)) {
1737 base::UmaHistogramSparse("Net.DNS.DnsTask.ErrorBeforeFallback.Fast",
1738 std::abs(net_error));
1739 } else {
1740 base::UmaHistogramSparse("Net.DNS.DnsTask.ErrorBeforeFallback.Slow",
1741 std::abs(net_error));
1742 }
[email protected]16c2bd72013-06-28 01:19:221743 dns_task_error_ = net_error;
1744
1745 // TODO(szym): Run ServeFromHosts now if nsswitch.conf says so.
1746 // http://crbug.com/117655
1747
1748 // TODO(szym): Some net errors indicate lack of connectivity. Starting
1749 // ProcTask in that case is a waste of time.
1750 if (resolver_->fallback_to_proctask_) {
[email protected]daae1322013-09-05 18:26:501751 KillDnsTask();
[email protected]16c2bd72013-06-28 01:19:221752 StartProcTask();
1753 } else {
1754 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_FAIL);
Brad Lassey2e8f185d2018-05-21 22:25:211755 // If the ttl is max, we didn't get one from the record, so set it to 0
1756 base::TimeDelta ttl =
1757 dns_task->ttl() < base::TimeDelta::FromSeconds(
1758 std::numeric_limits<uint32_t>::max())
1759 ? dns_task->ttl()
1760 : base::TimeDelta::FromSeconds(0);
1761 CompleteRequests(
1762 HostCache::Entry(net_error, AddressList(),
1763 HostCache::Entry::Source::SOURCE_UNKNOWN, ttl),
Eric Orth9871aafa2018-10-02 19:59:181764 ttl, true /* allow_cache */);
[email protected]b3601bc22012-02-21 21:23:201765 }
1766 }
1767
[email protected]daae1322013-09-05 18:26:501768 // HostResolverImpl::DnsTask::Delegate implementation:
1769
dchengb03027d2014-10-21 12:00:201770 void OnDnsTaskComplete(base::TimeTicks start_time,
1771 int net_error,
1772 const AddressList& addr_list,
1773 base::TimeDelta ttl) override {
[email protected]b3601bc22012-02-21 21:23:201774 DCHECK(is_dns_running());
[email protected]b3601bc22012-02-21 21:23:201775
Misha Efimovb99e7da2018-05-30 16:59:021776 base::TimeDelta duration = tick_clock_->NowTicks() - start_time;
[email protected]b3601bc22012-02-21 21:23:201777 if (net_error != OK) {
[email protected]16c2bd72013-06-28 01:19:221778 OnDnsTaskFailure(dns_task_->AsWeakPtr(), duration, net_error);
[email protected]b3601bc22012-02-21 21:23:201779 return;
1780 }
Miriam Gershenson61604662017-09-28 23:51:111781
1782 UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.DnsTask.SuccessTime", duration);
[email protected]b3601bc22012-02-21 21:23:201783
[email protected]1def74c2012-03-22 20:07:001784 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_DNS_SUCCESS);
[email protected]1339a2a22012-10-17 08:39:431785 RecordTTL(ttl);
[email protected]0adcb2b2012-08-15 21:30:461786
[email protected]1ffdda82012-12-12 23:04:221787 resolver_->OnDnsTaskResolve(OK);
[email protected]f0f602bd2012-11-15 18:01:021788
[email protected]895123222012-10-25 15:21:171789 base::TimeDelta bounded_ttl =
1790 std::max(ttl, base::TimeDelta::FromSeconds(kMinimumTTLSeconds));
1791
eroman0cd87b62016-12-14 19:13:451792 if (ContainsIcannNameCollisionIp(addr_list)) {
1793 CompleteRequestsWithError(ERR_ICANN_NAME_COLLISION);
1794 } else {
Rob Percival94f21ad2017-11-14 10:20:241795 CompleteRequests(MakeCacheEntryWithTTL(net_error, addr_list,
1796 HostCache::Entry::SOURCE_DNS, ttl),
Eric Orth9871aafa2018-10-02 19:59:181797 bounded_ttl, true /* allow_cache */);
eroman0cd87b62016-12-14 19:13:451798 }
[email protected]b3601bc22012-02-21 21:23:201799 }
1800
dchengb03027d2014-10-21 12:00:201801 void OnFirstDnsTransactionComplete() override {
[email protected]daae1322013-09-05 18:26:501802 DCHECK(dns_task_->needs_two_transactions());
1803 DCHECK_EQ(dns_task_->needs_another_transaction(), is_queued());
1804 // No longer need to occupy two dispatcher slots.
1805 ReduceToOneJobSlot();
1806
1807 // We already have a job slot at the dispatcher, so if the second
1808 // transaction hasn't started, reuse it now instead of waiting in the queue
1809 // for the second slot.
1810 if (dns_task_->needs_another_transaction())
1811 dns_task_->StartSecondTransaction();
1812 }
1813
Eric Orth9871aafa2018-10-02 19:59:181814 void StartMdnsTask() {
1815 DCHECK(!is_running());
1816
1817 // No flags are supported for MDNS except
1818 // HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6 (which is not actually an
1819 // input flag).
1820 DCHECK_EQ(0, key_.host_resolver_flags &
1821 ~HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6);
1822
1823 std::vector<HostResolver::DnsQueryType> query_types;
1824 switch (key_.address_family) {
1825 case ADDRESS_FAMILY_UNSPECIFIED:
1826 query_types.push_back(HostResolver::DnsQueryType::A);
1827 query_types.push_back(HostResolver::DnsQueryType::AAAA);
1828 break;
1829 case ADDRESS_FAMILY_IPV4:
1830 query_types.push_back(HostResolver::DnsQueryType::A);
1831 break;
1832 case ADDRESS_FAMILY_IPV6:
1833 query_types.push_back(HostResolver::DnsQueryType::AAAA);
1834 break;
1835 }
1836
1837 mdns_task_ = std::make_unique<HostResolverMdnsTask>(
1838 resolver_->GetOrCreateMdnsClient(), key_.hostname, query_types);
1839 mdns_task_->Start(
1840 base::BindOnce(&Job::OnMdnsTaskComplete, base::Unretained(this)));
1841 }
1842
1843 void OnMdnsTaskComplete(int error) {
1844 DCHECK(is_mdns_running());
1845 // TODO(crbug.com/846423): Consider adding MDNS-specific logging.
1846
1847 if (error != OK) {
1848 CompleteRequestsWithError(error);
1849 } else if (ContainsIcannNameCollisionIp(mdns_task_->result_addresses())) {
1850 CompleteRequestsWithError(ERR_ICANN_NAME_COLLISION);
1851 } else {
1852 // MDNS uses a separate cache, so skip saving result to cache.
1853 // TODO(crbug.com/846423): Consider merging caches.
1854 CompleteRequestsWithoutCache(error, mdns_task_->result_addresses());
1855 }
1856 }
1857
Brad Lassey786929ad2018-02-21 20:54:271858 URLRequestContext* url_request_context() override {
1859 return resolver_->url_request_context_;
1860 }
1861
Miriam Gershenson61604662017-09-28 23:51:111862 void RecordJobHistograms(int error) {
Miriam Gershensonc282ab42017-11-20 23:19:581863 // Used in UMA_HISTOGRAM_ENUMERATION. Do not renumber entries or reuse
1864 // deprecated values.
1865 enum Category {
1866 RESOLVE_SUCCESS = 0,
1867 RESOLVE_FAIL = 1,
1868 RESOLVE_SPECULATIVE_SUCCESS = 2,
1869 RESOLVE_SPECULATIVE_FAIL = 3,
1870 RESOLVE_ABORT = 4,
1871 RESOLVE_SPECULATIVE_ABORT = 5,
Miriam Gershenson61604662017-09-28 23:51:111872 RESOLVE_MAX, // Bounding value.
1873 };
1874 Category category = RESOLVE_MAX; // Illegal value for later DCHECK only.
1875
Misha Efimovb99e7da2018-05-30 16:59:021876 base::TimeDelta duration = tick_clock_->NowTicks() - start_time_;
Miriam Gershenson61604662017-09-28 23:51:111877 if (error == OK) {
1878 if (had_non_speculative_request_) {
1879 category = RESOLVE_SUCCESS;
1880 UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime", duration);
1881 switch (key_.address_family) {
1882 case ADDRESS_FAMILY_IPV4:
1883 UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.IPV4",
1884 duration);
1885 break;
1886 case ADDRESS_FAMILY_IPV6:
1887 UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.IPV6",
1888 duration);
1889 break;
1890 case ADDRESS_FAMILY_UNSPECIFIED:
1891 UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.UNSPEC",
1892 duration);
1893 break;
1894 }
1895 } else {
1896 category = RESOLVE_SPECULATIVE_SUCCESS;
Miriam Gershenson61604662017-09-28 23:51:111897 }
Miriam Gershensonc282ab42017-11-20 23:19:581898 } else if (error == ERR_NETWORK_CHANGED ||
1899 error == ERR_HOST_RESOLVER_QUEUE_TOO_LARGE) {
1900 category = had_non_speculative_request_ ? RESOLVE_ABORT
1901 : RESOLVE_SPECULATIVE_ABORT;
Miriam Gershenson61604662017-09-28 23:51:111902 } else {
1903 if (had_non_speculative_request_) {
1904 category = RESOLVE_FAIL;
1905 UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime", duration);
1906 switch (key_.address_family) {
1907 case ADDRESS_FAMILY_IPV4:
Miriam Gershensonc282ab42017-11-20 23:19:581908 UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime.IPV4",
Miriam Gershenson61604662017-09-28 23:51:111909 duration);
1910 break;
1911 case ADDRESS_FAMILY_IPV6:
Miriam Gershensonc282ab42017-11-20 23:19:581912 UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime.IPV6",
Miriam Gershenson61604662017-09-28 23:51:111913 duration);
1914 break;
1915 case ADDRESS_FAMILY_UNSPECIFIED:
Miriam Gershensonc282ab42017-11-20 23:19:581916 UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime.UNSPEC",
Miriam Gershenson61604662017-09-28 23:51:111917 duration);
1918 break;
1919 }
1920 } else {
1921 category = RESOLVE_SPECULATIVE_FAIL;
Miriam Gershenson61604662017-09-28 23:51:111922 }
1923 }
1924 DCHECK_LT(static_cast<int>(category),
1925 static_cast<int>(RESOLVE_MAX)); // Be sure it was set.
1926 UMA_HISTOGRAM_ENUMERATION("Net.DNS.ResolveCategory", category, RESOLVE_MAX);
Miriam Gershensonaaf139582017-11-27 16:06:061927
1928 if (category == RESOLVE_FAIL || category == RESOLVE_ABORT) {
1929 if (duration < base::TimeDelta::FromMilliseconds(10))
Ilya Sherman0eb39802017-12-08 20:58:181930 base::UmaHistogramSparse("Net.DNS.ResolveError.Fast", std::abs(error));
Miriam Gershensonaaf139582017-11-27 16:06:061931 else
Ilya Sherman0eb39802017-12-08 20:58:181932 base::UmaHistogramSparse("Net.DNS.ResolveError.Slow", std::abs(error));
Miriam Gershensonaaf139582017-11-27 16:06:061933 }
Miriam Gershenson61604662017-09-28 23:51:111934 }
1935
[email protected]16ee26d2012-03-08 03:34:351936 // Performs Job's last rites. Completes all Requests. Deletes this.
Eric Orth9871aafa2018-10-02 19:59:181937 //
1938 // If not |allow_cache|, result will not be stored in the host cache, even if
1939 // result would otherwise allow doing so.
[email protected]895123222012-10-25 15:21:171940 void CompleteRequests(const HostCache::Entry& entry,
Eric Orth9871aafa2018-10-02 19:59:181941 base::TimeDelta ttl,
1942 bool allow_cache) {
[email protected]11fbca0b2013-06-02 23:37:211943 CHECK(resolver_.get());
[email protected]b3601bc22012-02-21 21:23:201944
[email protected]16ee26d2012-03-08 03:34:351945 // This job must be removed from resolver's |jobs_| now to make room for a
1946 // new job with the same key in case one of the OnComplete callbacks decides
Eric Orth18544ae2018-06-11 22:57:161947 // to spawn one. Consequently, if the job was owned by |jobs_|, the job
1948 // deletes itself when CompleteRequests is done.
1949 std::unique_ptr<Job> self_deleter = resolver_->RemoveJob(this);
[email protected]16ee26d2012-03-08 03:34:351950
[email protected]16ee26d2012-03-08 03:34:351951 if (is_running()) {
Eric Orth9a037562018-07-03 21:24:381952 proc_task_ = nullptr;
[email protected]daae1322013-09-05 18:26:501953 KillDnsTask();
Eric Orth9871aafa2018-10-02 19:59:181954 mdns_task_ = nullptr;
[email protected]16ee26d2012-03-08 03:34:351955
1956 // Signal dispatcher that a slot has opened.
[email protected]106ccd2c2014-06-17 09:21:001957 resolver_->dispatcher_->OnJobFinished();
[email protected]16ee26d2012-03-08 03:34:351958 } else if (is_queued()) {
[email protected]106ccd2c2014-06-17 09:21:001959 resolver_->dispatcher_->Cancel(handle_);
[email protected]16ee26d2012-03-08 03:34:351960 handle_.Reset();
1961 }
1962
1963 if (num_active_requests() == 0) {
mikecirone8b85c432016-09-08 19:11:001964 net_log_.AddEvent(NetLogEventType::CANCELLED);
1965 net_log_.EndEventWithNetErrorCode(NetLogEventType::HOST_RESOLVER_IMPL_JOB,
[email protected]16ee26d2012-03-08 03:34:351966 OK);
1967 return;
1968 }
[email protected]b3601bc22012-02-21 21:23:201969
mikecirone8b85c432016-09-08 19:11:001970 net_log_.EndEventWithNetErrorCode(NetLogEventType::HOST_RESOLVER_IMPL_JOB,
juliatuttle317860e2016-05-12 14:47:221971 entry.error());
[email protected]68ad3ee2010-01-30 03:45:391972
[email protected]78eac2a2012-03-14 19:09:271973 DCHECK(!requests_.empty());
1974
eroman1efc237c2016-12-14 00:00:451975 if (entry.error() == OK || entry.error() == ERR_ICANN_NAME_COLLISION) {
[email protected]d7b9a2b2012-05-31 22:31:191976 // Record this histogram here, when we know the system has a valid DNS
1977 // configuration.
[email protected]539df6c2012-06-19 21:21:291978 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HaveDnsConfig",
1979 resolver_->received_dns_config_);
[email protected]d7b9a2b2012-05-31 22:31:191980 }
[email protected]16ee26d2012-03-08 03:34:351981
juliatuttle317860e2016-05-12 14:47:221982 bool did_complete = (entry.error() != ERR_NETWORK_CHANGED) &&
1983 (entry.error() != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE);
Eric Orth9871aafa2018-10-02 19:59:181984 if (did_complete && allow_cache)
[email protected]1339a2a22012-10-17 08:39:431985 resolver_->CacheResult(key_, entry, ttl);
Miriam Gershensonc282ab42017-11-20 23:19:581986
1987 RecordJobHistograms(entry.error());
[email protected]16ee26d2012-03-08 03:34:351988
maksim.sisov31452af2016-07-27 06:38:101989 // Complete all of the requests that were attached to the job and
1990 // detach them.
1991 while (!requests_.empty()) {
David Benjamina5677192018-04-23 23:25:421992 RequestImpl* req = requests_.head()->value();
1993 req->RemoveFromList();
[email protected]0f292de02012-02-01 22:28:201994 DCHECK_EQ(this, req->job());
1995 // Update the net log and notify registered observers.
Eric Orth70992982018-07-24 00:25:001996 LogFinishRequest(req->source_net_log(), entry.error());
[email protected]51b9a6b2012-06-25 21:50:291997 if (did_complete) {
1998 // Record effective total time from creation to completion.
Eric Orthb30bc172018-08-17 21:09:571999 RecordTotalTime(req->parameters().is_speculative,
2000 false /* from_cache */,
Misha Efimovb99e7da2018-05-30 16:59:022001 tick_clock_->NowTicks() - req->request_time());
[email protected]51b9a6b2012-06-25 21:50:292002 }
Eric Orthb30bc172018-08-17 21:09:572003 if (entry.error() == OK && !req->parameters().is_speculative) {
Eric Orth70992982018-07-24 00:25:002004 req->set_address_results(EnsurePortOnAddressList(
2005 entry.addresses(), req->request_host().port()));
2006 }
2007 req->OnJobCompleted(this, entry.error());
[email protected]0f292de02012-02-01 22:28:202008
2009 // Check if the resolver was destroyed as a result of running the
2010 // callback. If it was, we could continue, but we choose to bail.
[email protected]11fbca0b2013-06-02 23:37:212011 if (!resolver_.get())
[email protected]0f292de02012-02-01 22:28:202012 return;
2013 }
2014 }
2015
Eric Orth9871aafa2018-10-02 19:59:182016 void CompleteRequestsWithoutCache(int error, const AddressList& addresses) {
2017 CompleteRequests(
2018 MakeCacheEntry(error, addresses, HostCache::Entry::SOURCE_UNKNOWN),
2019 base::TimeDelta(), false /* allow_cache */);
2020 }
2021
[email protected]1339a2a22012-10-17 08:39:432022 // Convenience wrapper for CompleteRequests in case of failure.
2023 void CompleteRequestsWithError(int net_error) {
Rob Percival94f21ad2017-11-14 10:20:242024 CompleteRequests(HostCache::Entry(net_error, AddressList(),
2025 HostCache::Entry::SOURCE_UNKNOWN),
Eric Orth9871aafa2018-10-02 19:59:182026 base::TimeDelta(), true /* allow_cache */);
[email protected]1339a2a22012-10-17 08:39:432027 }
2028
Brad Lassey786929ad2018-02-21 20:54:272029 RequestPriority priority() const override {
[email protected]b4481b222012-03-16 17:13:112030 return priority_tracker_.highest_priority();
2031 }
2032
2033 // Number of non-canceled requests in |requests_|.
2034 size_t num_active_requests() const {
2035 return priority_tracker_.total_count();
2036 }
2037
wezb9820d42016-06-22 23:41:042038 bool is_dns_running() const { return !!dns_task_; }
[email protected]b4481b222012-03-16 17:13:112039
Eric Orth9871aafa2018-10-02 19:59:182040 bool is_mdns_running() const { return !!mdns_task_; }
2041
wezb9820d42016-06-22 23:41:042042 bool is_proc_running() const { return !!proc_task_; }
[email protected]b4481b222012-03-16 17:13:112043
[email protected]0f292de02012-02-01 22:28:202044 base::WeakPtr<HostResolverImpl> resolver_;
2045
2046 Key key_;
2047
2048 // Tracks the highest priority across |requests_|.
2049 PriorityTracker priority_tracker_;
2050
Miriam Gershensone42adb22017-10-16 16:19:382051 // Task runner used for HostResolverProc.
2052 scoped_refptr<base::TaskRunner> proc_task_runner_;
2053
[email protected]0f292de02012-02-01 22:28:202054 bool had_non_speculative_request_;
2055
[email protected]daae1322013-09-05 18:26:502056 // Number of slots occupied by this Job in resolver's PrioritizedDispatcher.
2057 unsigned num_occupied_job_slots_;
2058
[email protected]1d932852012-06-19 19:40:332059 // Result of DnsTask.
2060 int dns_task_error_;
[email protected]1def74c2012-03-22 20:07:002061
Misha Efimovb99e7da2018-05-30 16:59:022062 const base::TickClock* tick_clock_;
[email protected]51b9a6b2012-06-25 21:50:292063 const base::TimeTicks creation_time_;
2064 base::TimeTicks priority_change_time_;
Miriam Gershenson61604662017-09-28 23:51:112065 base::TimeTicks start_time_;
[email protected]51b9a6b2012-06-25 21:50:292066
tfarina428341112016-09-22 13:38:202067 NetLogWithSource net_log_;
[email protected]0f292de02012-02-01 22:28:202068
[email protected]b3601bc22012-02-21 21:23:202069 // Resolves the host using a HostResolverProc.
Eric Orth9a037562018-07-03 21:24:382070 std::unique_ptr<ProcTask> proc_task_;
[email protected]0f292de02012-02-01 22:28:202071
[email protected]b3601bc22012-02-21 21:23:202072 // Resolves the host using a DnsTransaction.
danakj22f90e72016-04-16 01:55:402073 std::unique_ptr<DnsTask> dns_task_;
[email protected]b3601bc22012-02-21 21:23:202074
Eric Orth9871aafa2018-10-02 19:59:182075 // Resolves the host using MDnsClient.
2076 std::unique_ptr<HostResolverMdnsTask> mdns_task_;
2077
[email protected]0f292de02012-02-01 22:28:202078 // All Requests waiting for the result of this Job. Some can be canceled.
David Benjamina5677192018-04-23 23:25:422079 base::LinkedList<RequestImpl> requests_;
[email protected]0f292de02012-02-01 22:28:202080
[email protected]16ee26d2012-03-08 03:34:352081 // A handle used in |HostResolverImpl::dispatcher_|.
[email protected]0f292de02012-02-01 22:28:202082 PrioritizedDispatcher::Handle handle_;
[email protected]68ad3ee2010-01-30 03:45:392083};
2084
2085//-----------------------------------------------------------------------------
2086
[email protected]0f292de02012-02-01 22:28:202087HostResolverImpl::ProcTaskParams::ProcTaskParams(
[email protected]e95d3aca2010-01-11 22:47:432088 HostResolverProc* resolver_proc,
[email protected]0f292de02012-02-01 22:28:202089 size_t max_retry_attempts)
2090 : resolver_proc(resolver_proc),
2091 max_retry_attempts(max_retry_attempts),
ttuttlecf1158bf2016-03-18 16:37:442092 unresponsive_delay(
2093 base::TimeDelta::FromMilliseconds(kDnsDefaultUnresponsiveDelayMs)),
[email protected]0f292de02012-02-01 22:28:202094 retry_factor(2) {
[email protected]106ccd2c2014-06-17 09:21:002095 // Maximum of 4 retry attempts for host resolution.
2096 static const size_t kDefaultMaxRetryAttempts = 4u;
2097 if (max_retry_attempts == HostResolver::kDefaultRetryAttempts)
2098 max_retry_attempts = kDefaultMaxRetryAttempts;
[email protected]0f292de02012-02-01 22:28:202099}
2100
vmpstracd23b72016-02-26 21:08:552101HostResolverImpl::ProcTaskParams::ProcTaskParams(const ProcTaskParams& other) =
2102 default;
2103
Chris Watkins68b15032017-12-01 03:07:132104HostResolverImpl::ProcTaskParams::~ProcTaskParams() = default;
[email protected]0f292de02012-02-01 22:28:202105
Francois Doraya2d01ba2017-09-25 19:17:402106HostResolverImpl::HostResolverImpl(const Options& options, NetLog* net_log)
mmenke91c17162016-06-02 16:03:232107 : max_queued_jobs_(0),
2108 proc_params_(NULL, options.max_retry_attempts),
2109 net_log_(net_log),
2110 received_dns_config_(false),
2111 num_dns_failures_(0),
mgershaf9a9232017-04-13 20:19:032112 assume_ipv6_failure_on_wifi_(false),
mmenke91c17162016-06-02 16:03:232113 use_local_ipv6_(false),
2114 last_ipv6_probe_result_(true),
mmenke91c17162016-06-02 16:03:232115 additional_resolver_flags_(0),
2116 fallback_to_proctask_(true),
Brad Lassey73e67ee2018-05-31 00:11:592117 url_request_context_(nullptr),
Misha Efimovb99e7da2018-05-30 16:59:022118 tick_clock_(base::DefaultTickClock::GetInstance()),
mmenke91c17162016-06-02 16:03:232119 weak_ptr_factory_(this),
2120 probe_weak_ptr_factory_(this) {
2121 if (options.enable_caching)
2122 cache_ = HostCache::CreateDefaultCache();
2123
2124 PrioritizedDispatcher::Limits job_limits = options.GetDispatcherLimits();
2125 dispatcher_.reset(new PrioritizedDispatcher(job_limits));
2126 max_queued_jobs_ = job_limits.total_jobs * 100u;
2127
2128 DCHECK_GE(dispatcher_->num_priorities(), static_cast<size_t>(NUM_PRIORITIES));
2129
Miriam Gershensone42adb22017-10-16 16:19:382130 proc_task_runner_ = base::CreateTaskRunnerWithTraits(
Maks Orlovich5393c8682018-02-26 16:17:502131 {base::MayBlock(), priority_mode.Get(),
2132 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
Miriam Gershensone42adb22017-10-16 16:19:382133
mmenke91c17162016-06-02 16:03:232134#if defined(OS_WIN)
2135 EnsureWinsockInit();
2136#endif
Fabrice de Gans-Riberi7de47372018-05-08 20:23:472137#if (defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)) || \
2138 defined(OS_FUCHSIA)
mmenke91c17162016-06-02 16:03:232139 RunLoopbackProbeJob();
2140#endif
Paul Jensenf47bbab2018-09-14 16:34:042141 NetworkChangeNotifier::AddIPAddressObserver(this);
2142 NetworkChangeNotifier::AddConnectionTypeObserver(this);
mmenke91c17162016-06-02 16:03:232143 NetworkChangeNotifier::AddDNSObserver(this);
2144#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) && \
Fabrice de Gans-Riberi65421f62018-05-22 23:16:182145 !defined(OS_ANDROID)
mmenke91c17162016-06-02 16:03:232146 EnsureDnsReloaderInit();
2147#endif
2148
Paul Jensenf47bbab2018-09-14 16:34:042149 OnConnectionTypeChanged(NetworkChangeNotifier::GetConnectionType());
mmenke91c17162016-06-02 16:03:232150
2151 {
2152 DnsConfig dns_config;
2153 NetworkChangeNotifier::GetDnsConfig(&dns_config);
2154 received_dns_config_ = dns_config.IsValid();
2155 // Conservatively assume local IPv6 is needed when DnsConfig is not valid.
2156 use_local_ipv6_ = !dns_config.IsValid() || dns_config.use_local_ipv6;
2157 }
2158
2159 fallback_to_proctask_ = !ConfigureAsyncDnsNoFallbackFieldTrial();
2160}
2161
Eric Orth70992982018-07-24 00:25:002162HostResolverImpl::~HostResolverImpl() {
2163 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
2164 // Prevent the dispatcher from starting new jobs.
2165 dispatcher_->SetLimitsToZero();
2166 // It's now safe for Jobs to call KillDnsTask on destruction, because
2167 // OnJobComplete will not start any new jobs.
2168 jobs_.clear();
2169
Paul Jensenf47bbab2018-09-14 16:34:042170 NetworkChangeNotifier::RemoveIPAddressObserver(this);
2171 NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
Eric Orth70992982018-07-24 00:25:002172 NetworkChangeNotifier::RemoveDNSObserver(this);
mmenke91c17162016-06-02 16:03:232173}
2174
Eric Orth70992982018-07-24 00:25:002175void HostResolverImpl::SetDnsClient(std::unique_ptr<DnsClient> dns_client) {
2176 // DnsClient and config must be updated before aborting DnsTasks, since doing
2177 // so may start new jobs.
2178 dns_client_ = std::move(dns_client);
2179 if (dns_client_ && !dns_client_->GetConfig() &&
2180 num_dns_failures_ < kMaximumDnsFailures) {
2181 DnsConfig dns_config;
2182 NetworkChangeNotifier::GetDnsConfig(&dns_config);
2183 dns_config.dns_over_https_servers = dns_over_https_servers_;
2184 dns_client_->SetConfig(dns_config);
2185 num_dns_failures_ = 0;
2186 if (dns_client_->GetConfig())
2187 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", true);
2188 }
2189
2190 AbortDnsTasks();
Findite5a94e02018-07-13 21:56:212191}
2192
Eric Orth70992982018-07-24 00:25:002193std::unique_ptr<HostResolver::ResolveHostRequest>
Eric Orth00fe5a62018-08-15 22:20:002194HostResolverImpl::CreateRequest(
2195 const HostPortPair& host,
2196 const NetLogWithSource& net_log,
2197 const base::Optional<ResolveHostParameters>& optional_parameters) {
2198 return std::make_unique<RequestImpl>(net_log, host, optional_parameters,
Eric Orth00fe5a62018-08-15 22:20:002199 weak_ptr_factory_.GetWeakPtr());
Eric Orth70992982018-07-24 00:25:002200}
2201
2202int HostResolverImpl::Resolve(const RequestInfo& info,
2203 RequestPriority priority,
2204 AddressList* addresses,
2205 CompletionOnceCallback callback,
2206 std::unique_ptr<Request>* out_req,
2207 const NetLogWithSource& source_net_log) {
2208 DCHECK(addresses);
2209 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
2210 DCHECK(callback);
2211 DCHECK(out_req);
2212
2213 auto request = std::make_unique<RequestImpl>(
Eric Orth00fe5a62018-08-15 22:20:002214 source_net_log, info.host_port_pair(),
2215 RequestInfoToResolveHostParameters(info, priority),
Eric Orthb30bc172018-08-17 21:09:572216 weak_ptr_factory_.GetWeakPtr());
Eric Orth70992982018-07-24 00:25:002217 auto wrapped_request =
2218 std::make_unique<LegacyRequestImpl>(std::move(request));
2219
2220 int rv = wrapped_request->Start();
2221
Eric Orthb30bc172018-08-17 21:09:572222 if (rv == OK && !info.is_speculative()) {
Eric Orth70992982018-07-24 00:25:002223 DCHECK(wrapped_request->inner_request().GetAddressResults());
2224 *addresses = wrapped_request->inner_request().GetAddressResults().value();
2225 } else if (rv == ERR_IO_PENDING) {
2226 wrapped_request->AssignCallback(std::move(callback), addresses);
2227 *out_req = std::move(wrapped_request);
Eric Orthfac527992018-07-13 21:11:162228 }
2229
Eric Orth70992982018-07-24 00:25:002230 return rv;
[email protected]95a214c2011-08-04 21:50:402231}
2232
2233int HostResolverImpl::ResolveFromCache(const RequestInfo& info,
2234 AddressList* addresses,
tfarina428341112016-09-22 13:38:202235 const NetLogWithSource& source_net_log) {
gab47aa7da2017-06-02 16:09:432236 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]95a214c2011-08-04 21:50:402237 DCHECK(addresses);
2238
[email protected]95a214c2011-08-04 21:50:402239 // Update the net log and notify registered observers.
xunjieli26f90452014-11-10 16:23:022240 LogStartRequest(source_net_log, info);
[email protected]95a214c2011-08-04 21:50:402241
Matt Menke23b4bbf82017-07-20 19:11:292242 Key key;
Eric Orth70992982018-07-24 00:25:002243 int rv = ResolveLocally(
Eric Orth00fe5a62018-08-15 22:20:002244 info.host_port_pair(), AddressFamilyToDnsQueryType(info.address_family()),
Eric Orthdc35748e2018-08-23 22:41:482245 FlagsToSource(info.host_resolver_flags()), info.host_resolver_flags(),
2246 info.allow_cached_response(), false /* allow_stale */,
2247 nullptr /* stale_info */, source_net_log, addresses, &key);
[email protected]95a214c2011-08-04 21:50:402248
Eric Orth70992982018-07-24 00:25:002249 LogFinishRequest(source_net_log, rv);
2250 return rv;
2251}
2252
2253int HostResolverImpl::ResolveStaleFromCache(
2254 const RequestInfo& info,
2255 AddressList* addresses,
2256 HostCache::EntryStaleness* stale_info,
2257 const NetLogWithSource& source_net_log) {
2258 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
2259 DCHECK(addresses);
2260 DCHECK(stale_info);
2261
2262 // Update the net log and notify registered observers.
2263 LogStartRequest(source_net_log, info);
2264
2265 Key key;
Eric Orth00fe5a62018-08-15 22:20:002266 int rv = ResolveLocally(
2267 info.host_port_pair(), AddressFamilyToDnsQueryType(info.address_family()),
Eric Orthdc35748e2018-08-23 22:41:482268 FlagsToSource(info.host_resolver_flags()), info.host_resolver_flags(),
2269 info.allow_cached_response(), true /* allow_stale */, stale_info,
2270 source_net_log, addresses, &key);
Eric Orth70992982018-07-24 00:25:002271 LogFinishRequest(source_net_log, rv);
[email protected]95a214c2011-08-04 21:50:402272 return rv;
2273}
2274
[email protected]a8883e452012-11-17 05:58:062275void HostResolverImpl::SetDnsClientEnabled(bool enabled) {
gab47aa7da2017-06-02 16:09:432276 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]a8883e452012-11-17 05:58:062277#if defined(ENABLE_BUILT_IN_DNS)
2278 if (enabled && !dns_client_) {
2279 SetDnsClient(DnsClient::CreateClient(net_log_));
2280 } else if (!enabled && dns_client_) {
danakj22f90e72016-04-16 01:55:402281 SetDnsClient(std::unique_ptr<DnsClient>());
[email protected]a8883e452012-11-17 05:58:062282 }
2283#endif
2284}
2285
[email protected]489d1a82011-10-12 03:09:112286HostCache* HostResolverImpl::GetHostCache() {
2287 return cache_.get();
2288}
[email protected]95a214c2011-08-04 21:50:402289
Rob Percivalbc658a22017-12-13 08:24:422290bool HostResolverImpl::HasCached(base::StringPiece hostname,
2291 HostCache::Entry::Source* source_out,
2292 HostCache::EntryStaleness* stale_out) const {
2293 if (!cache_)
2294 return false;
2295
2296 return cache_->HasEntry(hostname, source_out, stale_out);
2297}
2298
danakj22f90e72016-04-16 01:55:402299std::unique_ptr<base::Value> HostResolverImpl::GetDnsConfigAsValue() const {
[email protected]17e92032012-03-29 00:56:242300 // Check if async DNS is disabled.
2301 if (!dns_client_.get())
tfhef3618f2016-01-11 23:07:082302 return nullptr;
[email protected]17e92032012-03-29 00:56:242303
2304 // Check if async DNS is enabled, but we currently have no configuration
2305 // for it.
2306 const DnsConfig* dns_config = dns_client_->GetConfig();
wezb9820d42016-06-22 23:41:042307 if (!dns_config)
Jeremy Roman0579ed62017-08-29 15:56:192308 return std::make_unique<base::DictionaryValue>();
[email protected]17e92032012-03-29 00:56:242309
2310 return dns_config->ToValue();
2311}
2312
Miriam Gershenson2839ef112017-08-30 03:25:372313size_t HostResolverImpl::LastRestoredCacheSize() const {
2314 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
2315
2316 return cache_ ? cache_->last_restore_size() : 0;
2317}
2318
2319size_t HostResolverImpl::CacheSize() const {
2320 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
2321
2322 return cache_ ? cache_->size() : 0;
2323}
2324
mgershaf9a9232017-04-13 20:19:032325void HostResolverImpl::SetNoIPv6OnWifi(bool no_ipv6_on_wifi) {
gab47aa7da2017-06-02 16:09:432326 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
mgershaf9a9232017-04-13 20:19:032327 assume_ipv6_failure_on_wifi_ = no_ipv6_on_wifi;
2328}
2329
2330bool HostResolverImpl::GetNoIPv6OnWifi() {
2331 return assume_ipv6_failure_on_wifi_;
2332}
2333
Brad Lassey786929ad2018-02-21 20:54:272334void HostResolverImpl::SetRequestContext(URLRequestContext* context) {
2335 if (context != url_request_context_) {
2336 url_request_context_ = context;
2337 }
2338}
2339
dalykb34631f2018-08-24 19:59:482340void HostResolverImpl::AddDnsOverHttpsServer(std::string uri_template,
2341 bool use_post) {
2342 dns_over_https_servers_.emplace_back(uri_template, use_post);
Eric Orth70992982018-07-24 00:25:002343 if (dns_client_.get() && dns_client_->GetConfig())
2344 UpdateDNSConfig(true);
Misha Efimovb99e7da2018-05-30 16:59:022345}
2346
Brad Lassey786929ad2018-02-21 20:54:272347void HostResolverImpl::ClearDnsOverHttpsServers() {
2348 if (dns_over_https_servers_.size() == 0)
2349 return;
2350
2351 dns_over_https_servers_.clear();
2352
2353 if (dns_client_.get() && dns_client_->GetConfig())
2354 UpdateDNSConfig(true);
2355}
2356
Matt Menkeb67c0a8e2018-06-14 22:41:042357const std::vector<DnsConfig::DnsOverHttpsServerConfig>*
2358HostResolverImpl::GetDnsOverHttpsServersForTesting() const {
2359 if (dns_over_https_servers_.empty())
2360 return nullptr;
2361 return &dns_over_https_servers_;
2362}
2363
Eric Orth70992982018-07-24 00:25:002364void HostResolverImpl::SetTickClockForTesting(
2365 const base::TickClock* tick_clock) {
2366 tick_clock_ = tick_clock;
2367 cache_->set_tick_clock_for_testing(tick_clock);
2368}
2369
2370void HostResolverImpl::SetMaxQueuedJobsForTesting(size_t value) {
2371 DCHECK_EQ(0u, dispatcher_->num_queued_jobs());
2372 DCHECK_GE(value, 0u);
2373 max_queued_jobs_ = value;
2374}
2375
2376void HostResolverImpl::SetHaveOnlyLoopbackAddresses(bool result) {
2377 if (result) {
2378 additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY;
2379 } else {
2380 additional_resolver_flags_ &= ~HOST_RESOLVER_LOOPBACK_ONLY;
2381 }
2382}
2383
Eric Orth9871aafa2018-10-02 19:59:182384void HostResolverImpl::SetMdnsSocketFactoryForTesting(
2385 std::unique_ptr<MDnsSocketFactory> socket_factory) {
2386 DCHECK(!mdns_client_);
2387 mdns_socket_factory_ = std::move(socket_factory);
2388}
2389
2390void HostResolverImpl::SetMdnsClientForTesting(
2391 std::unique_ptr<MDnsClient> client) {
2392 mdns_client_ = std::move(client);
2393}
2394
Eric Orth70992982018-07-24 00:25:002395void HostResolverImpl::SetTaskRunnerForTesting(
2396 scoped_refptr<base::TaskRunner> task_runner) {
2397 proc_task_runner_ = std::move(task_runner);
2398}
2399
2400int HostResolverImpl::Resolve(RequestImpl* request) {
2401 // Request should not yet have a scheduled Job.
2402 DCHECK(!request->job());
2403 // Request may only be resolved once.
2404 DCHECK(!request->complete());
Eric Orth9871aafa2018-10-02 19:59:182405 // MDNS requests do not support skipping cache.
2406 // TODO(crbug.com/846423): Either add support for skipping the MDNS cache, or
2407 // merge to use the normal host cache for MDNS requests.
2408 DCHECK(request->parameters().source != HostResolverSource::MULTICAST_DNS ||
2409 request->parameters().allow_cached_response);
Eric Orth70992982018-07-24 00:25:002410
2411 request->set_request_time(tick_clock_->NowTicks());
2412
2413 LogStartRequest(request->source_net_log(), request->request_host());
2414
2415 AddressList addresses;
2416 Key key;
Eric Orth00fe5a62018-08-15 22:20:002417 int rv = ResolveLocally(
2418 request->request_host(), request->parameters().dns_query_type,
Eric Orthdc35748e2018-08-23 22:41:482419 request->parameters().source, request->host_resolver_flags(),
2420 request->parameters().allow_cached_response, false /* allow_stale */,
2421 nullptr /* stale_info */, request->source_net_log(), &addresses, &key);
Eric Orthb30bc172018-08-17 21:09:572422 if (rv == OK && !request->parameters().is_speculative) {
Eric Orth70992982018-07-24 00:25:002423 request->set_address_results(
2424 EnsurePortOnAddressList(addresses, request->request_host().port()));
2425 }
2426 if (rv != ERR_DNS_CACHE_MISS) {
2427 LogFinishRequest(request->source_net_log(), rv);
Eric Orthb30bc172018-08-17 21:09:572428 RecordTotalTime(request->parameters().is_speculative, true /* from_cache */,
Eric Orth70992982018-07-24 00:25:002429 base::TimeDelta());
2430 return rv;
2431 }
2432
2433 rv = CreateAndStartJob(key, request);
2434 // At this point, expect only async or errors.
2435 DCHECK_NE(OK, rv);
2436
2437 return rv;
2438}
2439
2440int HostResolverImpl::ResolveLocally(const HostPortPair& host,
Eric Orth00fe5a62018-08-15 22:20:002441 DnsQueryType dns_query_type,
Eric Orthdc35748e2018-08-23 22:41:482442 HostResolverSource source,
Eric Orth70992982018-07-24 00:25:002443 HostResolverFlags flags,
2444 bool allow_cache,
2445 bool allow_stale,
2446 HostCache::EntryStaleness* stale_info,
2447 const NetLogWithSource& source_net_log,
2448 AddressList* addresses,
2449 Key* key) {
2450 IPAddress ip_address;
2451 IPAddress* ip_address_ptr = nullptr;
2452 if (ip_address.AssignFromIPLiteral(host.host())) {
2453 ip_address_ptr = &ip_address;
2454 } else {
2455 // Check that the caller supplied a valid hostname to resolve.
2456 if (!IsValidDNSDomain(host.host()))
2457 return ERR_NAME_NOT_RESOLVED;
2458 }
2459
2460 // Build a key that identifies the request in the cache and in the
2461 // outstanding jobs map.
Eric Orthdc35748e2018-08-23 22:41:482462 *key = GetEffectiveKeyForRequest(host.host(), dns_query_type, source, flags,
Eric Orth70992982018-07-24 00:25:002463 ip_address_ptr, source_net_log);
2464
2465 DCHECK(allow_stale == !!stale_info);
2466 // The result of |getaddrinfo| for empty hosts is inconsistent across systems.
2467 // On Windows it gives the default interface's address, whereas on Linux it
2468 // gives an error. We will make it fail on all platforms for consistency.
2469 if (host.host().empty() || host.host().size() > kMaxHostLength) {
2470 MakeNotStale(stale_info);
2471 return ERR_NAME_NOT_RESOLVED;
2472 }
2473
2474 int net_error = ERR_UNEXPECTED;
2475 if (ResolveAsIP(*key, host.port(), ip_address_ptr, &net_error, addresses)) {
2476 MakeNotStale(stale_info);
2477 return net_error;
2478 }
2479
2480 // Special-case localhost names, as per the recommendations in
2481 // https://tools.ietf.org/html/draft-west-let-localhost-be-localhost.
2482 if (ServeLocalhost(*key, host.port(), addresses)) {
2483 MakeNotStale(stale_info);
2484 return OK;
2485 }
2486
2487 if (allow_cache && ServeFromCache(*key, host.port(), &net_error, addresses,
2488 allow_stale, stale_info)) {
2489 source_net_log.AddEvent(NetLogEventType::HOST_RESOLVER_IMPL_CACHE_HIT,
2490 addresses->CreateNetLogCallback());
2491 // |ServeFromCache()| will set |*stale_info| as needed.
2492 return net_error;
2493 }
2494
2495 // TODO(szym): Do not do this if nsswitch.conf instructs not to.
2496 // http://crbug.com/117655
2497 if (ServeFromHosts(*key, host.port(), addresses)) {
2498 source_net_log.AddEvent(NetLogEventType::HOST_RESOLVER_IMPL_HOSTS_HIT,
2499 addresses->CreateNetLogCallback());
2500 MakeNotStale(stale_info);
2501 return OK;
2502 }
2503
2504 return ERR_DNS_CACHE_MISS;
2505}
2506
2507int HostResolverImpl::CreateAndStartJob(const Key& key, RequestImpl* request) {
2508 auto jobit = jobs_.find(key);
2509 Job* job;
2510 if (jobit == jobs_.end()) {
2511 auto new_job = std::make_unique<Job>(
2512 weak_ptr_factory_.GetWeakPtr(), key, request->priority(),
2513 proc_task_runner_, request->source_net_log(), tick_clock_);
2514 job = new_job.get();
2515 new_job->Schedule(false);
2516
2517 // Check for queue overflow.
2518 if (dispatcher_->num_queued_jobs() > max_queued_jobs_) {
2519 Job* evicted = static_cast<Job*>(dispatcher_->EvictOldestLowest());
2520 DCHECK(evicted);
2521 evicted->OnEvicted();
2522 if (evicted == new_job.get()) {
2523 LogFinishRequest(request->source_net_log(),
2524 ERR_HOST_RESOLVER_QUEUE_TOO_LARGE);
2525 return ERR_HOST_RESOLVER_QUEUE_TOO_LARGE;
2526 }
2527 }
2528 jobs_[key] = std::move(new_job);
2529 } else {
2530 job = jobit->second.get();
2531 }
2532
2533 // Can't complete synchronously. Attach request and job to each other.
2534 job->AddRequest(request);
2535 return ERR_IO_PENDING;
2536}
2537
[email protected]95a214c2011-08-04 21:50:402538bool HostResolverImpl::ResolveAsIP(const Key& key,
Eric Orth70992982018-07-24 00:25:002539 uint16_t host_port,
martijna23c8962016-03-04 18:18:512540 const IPAddress* ip_address,
[email protected]95a214c2011-08-04 21:50:402541 int* net_error,
2542 AddressList* addresses) {
2543 DCHECK(addresses);
2544 DCHECK(net_error);
martijna23c8962016-03-04 18:18:512545 if (ip_address == nullptr)
[email protected]95a214c2011-08-04 21:50:402546 return false;
2547
[email protected]95a214c2011-08-04 21:50:402548 *net_error = OK;
martijna23c8962016-03-04 18:18:512549 AddressFamily family = GetAddressFamily(*ip_address);
cbentzel1906f872015-06-05 16:25:252550 if (key.address_family != ADDRESS_FAMILY_UNSPECIFIED &&
2551 key.address_family != family) {
[email protected]1c7cf3f82014-08-07 21:33:482552 // Don't return IPv6 addresses for IPv4 queries, and vice versa.
[email protected]95a214c2011-08-04 21:50:402553 *net_error = ERR_NAME_NOT_RESOLVED;
2554 } else {
Eric Orth70992982018-07-24 00:25:002555 *addresses = AddressList::CreateFromIPAddress(*ip_address, host_port);
[email protected]7054e78f2012-05-07 21:44:562556 if (key.host_resolver_flags & HOST_RESOLVER_CANONNAME)
2557 addresses->SetDefaultCanonicalName();
[email protected]95a214c2011-08-04 21:50:402558 }
2559 return true;
2560}
2561
2562bool HostResolverImpl::ServeFromCache(const Key& key,
Eric Orth70992982018-07-24 00:25:002563 uint16_t host_port,
[email protected]95a214c2011-08-04 21:50:402564 int* net_error,
juliatuttle9fb7aeb2016-06-06 20:16:332565 AddressList* addresses,
2566 bool allow_stale,
2567 HostCache::EntryStaleness* stale_info) {
[email protected]95a214c2011-08-04 21:50:402568 DCHECK(addresses);
2569 DCHECK(net_error);
juliatuttle9fb7aeb2016-06-06 20:16:332570 DCHECK(allow_stale == !!stale_info);
Eric Orth70992982018-07-24 00:25:002571 if (!cache_.get())
[email protected]95a214c2011-08-04 21:50:402572 return false;
2573
juliatuttle9fb7aeb2016-06-06 20:16:332574 const HostCache::Entry* cache_entry;
2575 if (allow_stale)
Misha Efimovb99e7da2018-05-30 16:59:022576 cache_entry = cache_->LookupStale(key, tick_clock_->NowTicks(), stale_info);
juliatuttle9fb7aeb2016-06-06 20:16:332577 else
Misha Efimovb99e7da2018-05-30 16:59:022578 cache_entry = cache_->Lookup(key, tick_clock_->NowTicks());
[email protected]95a214c2011-08-04 21:50:402579 if (!cache_entry)
2580 return false;
2581
juliatuttle317860e2016-05-12 14:47:222582 *net_error = cache_entry->error();
[email protected]7054e78f2012-05-07 21:44:562583 if (*net_error == OK) {
[email protected]1339a2a22012-10-17 08:39:432584 if (cache_entry->has_ttl())
juliatuttle317860e2016-05-12 14:47:222585 RecordTTL(cache_entry->ttl());
Eric Orth70992982018-07-24 00:25:002586 *addresses = EnsurePortOnAddressList(cache_entry->addresses(), host_port);
[email protected]7054e78f2012-05-07 21:44:562587 }
[email protected]95a214c2011-08-04 21:50:402588 return true;
2589}
2590
[email protected]78eac2a2012-03-14 19:09:272591bool HostResolverImpl::ServeFromHosts(const Key& key,
Eric Orth70992982018-07-24 00:25:002592 uint16_t host_port,
[email protected]78eac2a2012-03-14 19:09:272593 AddressList* addresses) {
2594 DCHECK(addresses);
2595 if (!HaveDnsConfig())
2596 return false;
[email protected]05a79d42013-03-28 07:30:092597 addresses->clear();
2598
[email protected]cb507622012-03-23 16:17:062599 // HOSTS lookups are case-insensitive.
brettw8e2106d2015-08-11 19:30:222600 std::string hostname = base::ToLowerASCII(key.hostname);
[email protected]cb507622012-03-23 16:17:062601
[email protected]05a79d42013-03-28 07:30:092602 const DnsHosts& hosts = dns_client_->GetConfig()->hosts;
2603
[email protected]78eac2a2012-03-14 19:09:272604 // If |address_family| is ADDRESS_FAMILY_UNSPECIFIED other implementations
2605 // (glibc and c-ares) return the first matching line. We have more
2606 // flexibility, but lose implicit ordering.
[email protected]05a79d42013-03-28 07:30:092607 // We prefer IPv6 because "happy eyeballs" will fall back to IPv4 if
2608 // necessary.
2609 if (key.address_family == ADDRESS_FAMILY_IPV6 ||
2610 key.address_family == ADDRESS_FAMILY_UNSPECIFIED) {
2611 DnsHosts::const_iterator it = hosts.find(
2612 DnsHostsKey(hostname, ADDRESS_FAMILY_IPV6));
2613 if (it != hosts.end())
Eric Orth70992982018-07-24 00:25:002614 addresses->push_back(IPEndPoint(it->second, host_port));
[email protected]78eac2a2012-03-14 19:09:272615 }
2616
[email protected]05a79d42013-03-28 07:30:092617 if (key.address_family == ADDRESS_FAMILY_IPV4 ||
2618 key.address_family == ADDRESS_FAMILY_UNSPECIFIED) {
2619 DnsHosts::const_iterator it = hosts.find(
2620 DnsHostsKey(hostname, ADDRESS_FAMILY_IPV4));
2621 if (it != hosts.end())
Eric Orth70992982018-07-24 00:25:002622 addresses->push_back(IPEndPoint(it->second, host_port));
[email protected]05a79d42013-03-28 07:30:092623 }
2624
[email protected]ec666ab22013-04-17 20:05:592625 // If got only loopback addresses and the family was restricted, resolve
2626 // again, without restrictions. See SystemHostResolverCall for rationale.
2627 if ((key.host_resolver_flags &
2628 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6) &&
2629 IsAllIPv4Loopback(*addresses)) {
2630 Key new_key(key);
2631 new_key.address_family = ADDRESS_FAMILY_UNSPECIFIED;
2632 new_key.host_resolver_flags &=
2633 ~HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
Eric Orth70992982018-07-24 00:25:002634 return ServeFromHosts(new_key, host_port, addresses);
[email protected]ec666ab22013-04-17 20:05:592635 }
[email protected]05a79d42013-03-28 07:30:092636 return !addresses->empty();
[email protected]78eac2a2012-03-14 19:09:272637}
2638
estarkd1bc206e2015-06-20 00:44:392639bool HostResolverImpl::ServeLocalhost(const Key& key,
Eric Orth70992982018-07-24 00:25:002640 uint16_t host_port,
estarkd1bc206e2015-06-20 00:44:392641 AddressList* addresses) {
2642 AddressList resolved_addresses;
Eric Orth70992982018-07-24 00:25:002643 if (!ResolveLocalHostname(key.hostname, host_port, &resolved_addresses))
estarkd1bc206e2015-06-20 00:44:392644 return false;
2645
2646 addresses->clear();
2647
2648 for (const auto& address : resolved_addresses) {
2649 // Include the address if:
2650 // - caller didn't specify an address family, or
2651 // - caller specifically asked for the address family of this address, or
2652 // - this is an IPv6 address and caller specifically asked for IPv4 due
2653 // to lack of detected IPv6 support. (See SystemHostResolverCall for
2654 // rationale).
2655 if (key.address_family == ADDRESS_FAMILY_UNSPECIFIED ||
2656 key.address_family == address.GetFamily() ||
2657 (address.GetFamily() == ADDRESS_FAMILY_IPV6 &&
2658 key.address_family == ADDRESS_FAMILY_IPV4 &&
2659 (key.host_resolver_flags &
2660 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6))) {
2661 addresses->push_back(address);
2662 }
2663 }
2664
2665 return true;
2666}
2667
[email protected]16ee26d2012-03-08 03:34:352668void HostResolverImpl::CacheResult(const Key& key,
[email protected]1339a2a22012-10-17 08:39:432669 const HostCache::Entry& entry,
[email protected]16ee26d2012-03-08 03:34:352670 base::TimeDelta ttl) {
Miriam Gershensone3bc63022017-10-09 19:57:052671 // Don't cache an error unless it has a positive TTL.
2672 if (cache_.get() && (entry.error() == OK || ttl > base::TimeDelta()))
Misha Efimovb99e7da2018-05-30 16:59:022673 cache_->Set(key, entry, tick_clock_->NowTicks(), ttl);
[email protected]ef4c40c2010-09-01 14:42:032674}
2675
Eric Orth18544ae2018-06-11 22:57:162676std::unique_ptr<HostResolverImpl::Job> HostResolverImpl::RemoveJob(Job* job) {
[email protected]0f292de02012-02-01 22:28:202677 DCHECK(job);
Eric Orth18544ae2018-06-11 22:57:162678 std::unique_ptr<Job> retval;
avi9e72eb482016-12-09 21:10:542679 auto it = jobs_.find(job->key());
2680 if (it != jobs_.end() && it->second.get() == job) {
Eric Orth18544ae2018-06-11 22:57:162681 it->second.swap(retval);
[email protected]16ee26d2012-03-08 03:34:352682 jobs_.erase(it);
avi9e72eb482016-12-09 21:10:542683 }
Eric Orth18544ae2018-06-11 22:57:162684 return retval;
[email protected]b59ff372009-07-15 22:04:322685}
2686
[email protected]137af622010-02-05 02:14:352687HostResolverImpl::Key HostResolverImpl::GetEffectiveKeyForRequest(
Eric Orth70992982018-07-24 00:25:002688 const std::string& hostname,
Eric Orth00fe5a62018-08-15 22:20:002689 DnsQueryType dns_query_type,
Eric Orthdc35748e2018-08-23 22:41:482690 HostResolverSource source,
Eric Orth70992982018-07-24 00:25:002691 HostResolverFlags flags,
martijna23c8962016-03-04 18:18:512692 const IPAddress* ip_address,
tfarina428341112016-09-22 13:38:202693 const NetLogWithSource& net_log) {
Eric Orth70992982018-07-24 00:25:002694 HostResolverFlags effective_flags = flags | additional_resolver_flags_;
Eric Orth00fe5a62018-08-15 22:20:002695
2696 AddressFamily effective_address_family =
2697 DnsQueryTypeToAddressFamily(dns_query_type);
[email protected]9db6f702013-04-10 18:10:512698
mgersh3eba057d2017-02-28 18:50:562699 if (effective_address_family == ADDRESS_FAMILY_UNSPECIFIED &&
2700 // When resolving IPv4 literals, there's no need to probe for IPv6.
2701 // When resolving IPv6 literals, there's no benefit to artificially
2702 // limiting our resolution based on a probe. Prior logic ensures
2703 // that this query is UNSPECIFIED (see effective_address_family
2704 // check above) so the code requesting the resolution should be amenable
2705 // to receiving a IPv6 resolution.
2706 !use_local_ipv6_ && ip_address == nullptr && !IsIPv6Reachable(net_log)) {
2707 effective_address_family = ADDRESS_FAMILY_IPV4;
2708 effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
[email protected]9db6f702013-04-10 18:10:512709 }
2710
Eric Orthdc35748e2018-08-23 22:41:482711 return Key(hostname, effective_address_family, effective_flags, source);
[email protected]137af622010-02-05 02:14:352712}
2713
tfarina428341112016-09-22 13:38:202714bool HostResolverImpl::IsIPv6Reachable(const NetLogWithSource& net_log) {
mgershaf9a9232017-04-13 20:19:032715 // Don't bother checking if the device is on WiFi and IPv6 is assumed to not
2716 // work on WiFi.
2717 if (assume_ipv6_failure_on_wifi_ &&
2718 NetworkChangeNotifier::GetConnectionType() ==
2719 NetworkChangeNotifier::CONNECTION_WIFI) {
2720 return false;
2721 }
2722
eroman1a17ef32016-12-14 01:06:092723 // Cache the result for kIPv6ProbePeriodMs (measured from after
2724 // IsGloballyReachable() completes).
sergeyub8cdc212015-05-14 18:50:372725 bool cached = true;
Misha Efimovb99e7da2018-05-30 16:59:022726 if ((tick_clock_->NowTicks() - last_ipv6_probe_time_).InMilliseconds() >
eroman1a17ef32016-12-14 01:06:092727 kIPv6ProbePeriodMs) {
martijna23c8962016-03-04 18:18:512728 last_ipv6_probe_result_ =
2729 IsGloballyReachable(IPAddress(kIPv6ProbeAddress), net_log);
Misha Efimovb99e7da2018-05-30 16:59:022730 last_ipv6_probe_time_ = tick_clock_->NowTicks();
sergeyub8cdc212015-05-14 18:50:372731 cached = false;
2732 }
mikecirone8b85c432016-09-08 19:11:002733 net_log.AddEvent(NetLogEventType::HOST_RESOLVER_IMPL_IPV6_REACHABILITY_CHECK,
sergeyub8cdc212015-05-14 18:50:372734 base::Bind(&NetLogIPv6AvailableCallback,
2735 last_ipv6_probe_result_, cached));
2736 return last_ipv6_probe_result_;
2737}
2738
mgershaf9a9232017-04-13 20:19:032739bool HostResolverImpl::IsGloballyReachable(const IPAddress& dest,
2740 const NetLogWithSource& net_log) {
mgershaf9a9232017-04-13 20:19:032741 std::unique_ptr<DatagramClientSocket> socket(
2742 ClientSocketFactory::GetDefaultFactory()->CreateDatagramClientSocket(
Sergey Ulanovcbdfc8852018-03-16 20:13:282743 DatagramSocket::DEFAULT_BIND, net_log.net_log(), net_log.source()));
mgershaf9a9232017-04-13 20:19:032744 int rv = socket->Connect(IPEndPoint(dest, 53));
2745 if (rv != OK)
2746 return false;
2747 IPEndPoint endpoint;
2748 rv = socket->GetLocalAddress(&endpoint);
2749 if (rv != OK)
2750 return false;
2751 DCHECK_EQ(ADDRESS_FAMILY_IPV6, endpoint.GetFamily());
2752 const IPAddress& address = endpoint.address();
2753
2754 bool is_link_local =
2755 (address.bytes()[0] == 0xFE) && ((address.bytes()[1] & 0xC0) == 0x80);
2756 if (is_link_local)
2757 return false;
2758
2759 const uint8_t kTeredoPrefix[] = {0x20, 0x01, 0, 0};
2760 if (IPAddressStartsWith(address, kTeredoPrefix))
2761 return false;
2762
2763 return true;
2764}
2765
mmenke91c17162016-06-02 16:03:232766void HostResolverImpl::RunLoopbackProbeJob() {
Francois Doraya2d01ba2017-09-25 19:17:402767 // Run this asynchronously as it can take 40-100ms and should not block
2768 // initialization.
2769 base::PostTaskWithTraitsAndReplyWithResult(
2770 FROM_HERE,
2771 {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
2772 base::BindOnce(&HaveOnlyLoopbackAddresses),
2773 base::BindOnce(&HostResolverImpl::SetHaveOnlyLoopbackAddresses,
2774 weak_ptr_factory_.GetWeakPtr()));
mmenke91c17162016-06-02 16:03:232775}
2776
[email protected]35ddc282010-09-21 23:42:062777void HostResolverImpl::AbortAllInProgressJobs() {
[email protected]b3601bc22012-02-21 21:23:202778 // In Abort, a Request callback could spawn new Jobs with matching keys, so
2779 // first collect and remove all running jobs from |jobs_|.
danakj22f90e72016-04-16 01:55:402780 std::vector<std::unique_ptr<Job>> jobs_to_abort;
avi9e72eb482016-12-09 21:10:542781 for (auto it = jobs_.begin(); it != jobs_.end();) {
2782 Job* job = it->second.get();
[email protected]0f292de02012-02-01 22:28:202783 if (job->is_running()) {
avi9e72eb482016-12-09 21:10:542784 jobs_to_abort.push_back(std::move(it->second));
[email protected]b3601bc22012-02-21 21:23:202785 jobs_.erase(it++);
[email protected]0f292de02012-02-01 22:28:202786 } else {
[email protected]b3601bc22012-02-21 21:23:202787 DCHECK(job->is_queued());
2788 ++it;
[email protected]0f292de02012-02-01 22:28:202789 }
[email protected]ef4c40c2010-09-01 14:42:032790 }
[email protected]b3601bc22012-02-21 21:23:202791
[email protected]daae1322013-09-05 18:26:502792 // Pause the dispatcher so it won't start any new dispatcher jobs while
2793 // aborting the old ones. This is needed so that it won't start the second
2794 // DnsTransaction for a job in |jobs_to_abort| if the DnsConfig just became
2795 // invalid.
[email protected]106ccd2c2014-06-17 09:21:002796 PrioritizedDispatcher::Limits limits = dispatcher_->GetLimits();
2797 dispatcher_->SetLimits(
[email protected]daae1322013-09-05 18:26:502798 PrioritizedDispatcher::Limits(limits.reserved_slots.size(), 0));
[email protected]70c04ab2013-08-22 16:05:122799
[email protected]57a48d32012-03-03 00:04:552800 // Life check to bail once |this| is deleted.
[email protected]4589a3a2012-09-20 20:57:072801 base::WeakPtr<HostResolverImpl> self = weak_ptr_factory_.GetWeakPtr();
[email protected]57a48d32012-03-03 00:04:552802
[email protected]16ee26d2012-03-08 03:34:352803 // Then Abort them.
[email protected]11fbca0b2013-06-02 23:37:212804 for (size_t i = 0; self.get() && i < jobs_to_abort.size(); ++i) {
[email protected]57a48d32012-03-03 00:04:552805 jobs_to_abort[i]->Abort();
[email protected]b3601bc22012-02-21 21:23:202806 }
[email protected]daae1322013-09-05 18:26:502807
2808 if (self)
[email protected]106ccd2c2014-06-17 09:21:002809 dispatcher_->SetLimits(limits);
[email protected]daae1322013-09-05 18:26:502810}
2811
2812void HostResolverImpl::AbortDnsTasks() {
2813 // Pause the dispatcher so it won't start any new dispatcher jobs while
2814 // aborting the old ones. This is needed so that it won't start the second
2815 // DnsTransaction for a job if the DnsConfig just changed.
[email protected]106ccd2c2014-06-17 09:21:002816 PrioritizedDispatcher::Limits limits = dispatcher_->GetLimits();
2817 dispatcher_->SetLimits(
[email protected]daae1322013-09-05 18:26:502818 PrioritizedDispatcher::Limits(limits.reserved_slots.size(), 0));
2819
avi9e72eb482016-12-09 21:10:542820 for (auto it = jobs_.begin(); it != jobs_.end(); ++it)
[email protected]daae1322013-09-05 18:26:502821 it->second->AbortDnsTask();
[email protected]106ccd2c2014-06-17 09:21:002822 dispatcher_->SetLimits(limits);
[email protected]ef4c40c2010-09-01 14:42:032823}
2824
[email protected]78eac2a2012-03-14 19:09:272825void HostResolverImpl::TryServingAllJobsFromHosts() {
2826 if (!HaveDnsConfig())
2827 return;
2828
2829 // TODO(szym): Do not do this if nsswitch.conf instructs not to.
2830 // http://crbug.com/117655
2831
2832 // Life check to bail once |this| is deleted.
[email protected]4589a3a2012-09-20 20:57:072833 base::WeakPtr<HostResolverImpl> self = weak_ptr_factory_.GetWeakPtr();
[email protected]78eac2a2012-03-14 19:09:272834
avi9e72eb482016-12-09 21:10:542835 for (auto it = jobs_.begin(); self.get() && it != jobs_.end();) {
2836 Job* job = it->second.get();
[email protected]78eac2a2012-03-14 19:09:272837 ++it;
2838 // This could remove |job| from |jobs_|, but iterator will remain valid.
2839 job->ServeFromHosts();
2840 }
2841}
2842
Paul Jensenf47bbab2018-09-14 16:34:042843void HostResolverImpl::OnIPAddressChanged() {
sergeyub8cdc212015-05-14 18:50:372844 last_ipv6_probe_time_ = base::TimeTicks();
[email protected]12faa4c2012-11-06 04:44:182845 // Abandon all ProbeJobs.
2846 probe_weak_ptr_factory_.InvalidateWeakPtrs();
Matt Menkeef8f5cf82017-07-20 22:50:172847 if (cache_.get())
mgersh5bb3b9d2017-02-13 21:27:102848 cache_->OnNetworkChange();
Fabrice de Gans-Riberi7de47372018-05-08 20:23:472849#if (defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)) || \
2850 defined(OS_FUCHSIA)
mmenke91c17162016-06-02 16:03:232851 RunLoopbackProbeJob();
[email protected]be1a48b2011-01-20 00:12:132852#endif
2853 AbortAllInProgressJobs();
2854 // |this| may be deleted inside AbortAllInProgressJobs().
2855}
2856
Paul Jensenf47bbab2018-09-14 16:34:042857void HostResolverImpl::OnConnectionTypeChanged(
ttuttlecf1158bf2016-03-18 16:37:442858 NetworkChangeNotifier::ConnectionType type) {
2859 proc_params_.unresponsive_delay =
2860 GetTimeDeltaForConnectionTypeFromFieldTrialOrDefault(
2861 "DnsUnresponsiveDelayMsByConnectionType",
2862 base::TimeDelta::FromMilliseconds(kDnsDefaultUnresponsiveDelayMs),
2863 type);
2864}
2865
pauljensen101ed372015-04-17 00:11:422866void HostResolverImpl::OnInitialDNSConfigRead() {
2867 UpdateDNSConfig(false);
2868}
2869
[email protected]bb0e34542012-08-31 19:52:402870void HostResolverImpl::OnDNSChanged() {
pauljensen101ed372015-04-17 00:11:422871 UpdateDNSConfig(true);
2872}
2873
2874void HostResolverImpl::UpdateDNSConfig(bool config_changed) {
[email protected]bb0e34542012-08-31 19:52:402875 DnsConfig dns_config;
2876 NetworkChangeNotifier::GetDnsConfig(&dns_config);
[email protected]ec666ab22013-04-17 20:05:592877
[email protected]b4481b222012-03-16 17:13:112878 if (net_log_) {
mikecirone8b85c432016-09-08 19:11:002879 net_log_->AddGlobalEntry(NetLogEventType::DNS_CONFIG_CHANGED,
2880 base::Bind(&NetLogDnsConfigCallback, &dns_config));
[email protected]b4481b222012-03-16 17:13:112881 }
2882
[email protected]01b3b9d2012-08-13 16:18:142883 // TODO(szym): Remove once http://crbug.com/137914 is resolved.
[email protected]d7b9a2b2012-05-31 22:31:192884 received_dns_config_ = dns_config.IsValid();
[email protected]c9fa8f312013-09-17 12:24:522885 // Conservatively assume local IPv6 is needed when DnsConfig is not valid.
2886 use_local_ipv6_ = !dns_config.IsValid() || dns_config.use_local_ipv6;
[email protected]78eac2a2012-03-14 19:09:272887
[email protected]a8883e452012-11-17 05:58:062888 num_dns_failures_ = 0;
2889
[email protected]01b3b9d2012-08-13 16:18:142890 // We want a new DnsSession in place, before we Abort running Jobs, so that
2891 // the newly started jobs use the new config.
[email protected]f0f602bd2012-11-15 18:01:022892 if (dns_client_.get()) {
Miriam Gershenson44aafc122017-10-18 19:29:252893 // Make sure that if the update is an initial read, not a change, there
Miriam Gershenson668e8442017-10-31 20:31:532894 // wasn't already a DnsConfig or it's the same one.
2895 DCHECK(config_changed || !dns_client_->GetConfig() ||
2896 dns_client_->GetConfig()->Equals(dns_config));
Brad Lassey786929ad2018-02-21 20:54:272897 dns_config.dns_over_https_servers = dns_over_https_servers_;
[email protected]d7b9a2b2012-05-31 22:31:192898 dns_client_->SetConfig(dns_config);
Miriam Gershenson44aafc122017-10-18 19:29:252899 if (dns_client_->GetConfig())
[email protected]f0f602bd2012-11-15 18:01:022900 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", true);
[email protected]f0f602bd2012-11-15 18:01:022901 }
[email protected]01b3b9d2012-08-13 16:18:142902
pauljensen101ed372015-04-17 00:11:422903 if (config_changed) {
2904 // If the DNS server has changed, existing cached info could be wrong so we
mgersh92b1af12017-03-29 15:49:232905 // have to expire our internal cache :( Note that OS level DNS caches, such
pauljensen101ed372015-04-17 00:11:422906 // as NSCD's cache should be dropped automatically by the OS when
2907 // resolv.conf changes so we don't need to do anything to clear that cache.
Matt Menkeef8f5cf82017-07-20 22:50:172908 if (cache_.get())
mgersh92b1af12017-03-29 15:49:232909 cache_->OnNetworkChange();
[email protected]01b3b9d2012-08-13 16:18:142910
pauljensen101ed372015-04-17 00:11:422911 // Life check to bail once |this| is deleted.
2912 base::WeakPtr<HostResolverImpl> self = weak_ptr_factory_.GetWeakPtr();
[email protected]f0f602bd2012-11-15 18:01:022913
pauljensen101ed372015-04-17 00:11:422914 // Existing jobs will have been sent to the original server so they need to
2915 // be aborted.
2916 AbortAllInProgressJobs();
[email protected]01b3b9d2012-08-13 16:18:142917
pauljensen101ed372015-04-17 00:11:422918 // |this| may be deleted inside AbortAllInProgressJobs().
2919 if (self.get())
2920 TryServingAllJobsFromHosts();
2921 }
[email protected]78eac2a2012-03-14 19:09:272922}
2923
2924bool HostResolverImpl::HaveDnsConfig() const {
[email protected]32b1dbcf2013-01-26 03:48:252925 // Use DnsClient only if it's fully configured and there is no override by
2926 // ScopedDefaultHostResolverProc.
2927 // The alternative is to use NetworkChangeNotifier to override DnsConfig,
2928 // but that would introduce construction order requirements for NCN and SDHRP.
wezb9820d42016-06-22 23:41:042929 return dns_client_ && dns_client_->GetConfig() &&
2930 (proc_params_.resolver_proc || !HostResolverProc::GetDefault());
[email protected]b3601bc22012-02-21 21:23:202931}
2932
[email protected]1ffdda82012-12-12 23:04:222933void HostResolverImpl::OnDnsTaskResolve(int net_error) {
[email protected]f0f602bd2012-11-15 18:01:022934 DCHECK(dns_client_);
[email protected]1ffdda82012-12-12 23:04:222935 if (net_error == OK) {
[email protected]f0f602bd2012-11-15 18:01:022936 num_dns_failures_ = 0;
2937 return;
2938 }
2939 ++num_dns_failures_;
2940 if (num_dns_failures_ < kMaximumDnsFailures)
2941 return;
[email protected]daae1322013-09-05 18:26:502942
2943 // Disable DnsClient until the next DNS change. Must be done before aborting
2944 // DnsTasks, since doing so may start new jobs.
[email protected]f0f602bd2012-11-15 18:01:022945 dns_client_->SetConfig(DnsConfig());
[email protected]daae1322013-09-05 18:26:502946
2947 // Switch jobs with active DnsTasks over to using ProcTasks.
2948 AbortDnsTasks();
2949
[email protected]f0f602bd2012-11-15 18:01:022950 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", false);
Ilya Sherman0eb39802017-12-08 20:58:182951 base::UmaHistogramSparse("AsyncDNS.DnsClientDisabledReason",
2952 std::abs(net_error));
[email protected]f0f602bd2012-11-15 18:01:022953}
2954
Eric Orth9871aafa2018-10-02 19:59:182955MDnsClient* HostResolverImpl::GetOrCreateMdnsClient() {
2956#if BUILDFLAG(ENABLE_MDNS)
2957 if (!mdns_client_) {
2958 if (!mdns_socket_factory_)
2959 mdns_socket_factory_ = std::make_unique<MDnsSocketFactoryImpl>(net_log_);
2960
2961 mdns_client_ = MDnsClient::CreateDefault();
2962 mdns_client_->StartListening(mdns_socket_factory_.get());
2963 }
2964
2965 DCHECK(mdns_client_->IsListening());
2966 return mdns_client_.get();
2967#else
2968 // Should not request MDNS resoltuion unless MDNS is enabled.
2969 NOTREACHED();
2970 return nullptr;
2971#endif
2972}
2973
maksim.sisov31452af2016-07-27 06:38:102974HostResolverImpl::RequestImpl::~RequestImpl() {
2975 if (job_)
2976 job_->CancelRequest(this);
2977}
2978
2979void HostResolverImpl::RequestImpl::ChangeRequestPriority(
2980 RequestPriority priority) {
2981 job_->ChangeRequestPriority(this, priority);
2982}
2983
[email protected]b59ff372009-07-15 22:04:322984} // namespace net