host_resolver_impl.cc revision 868fa2fe829687343ffae624259930155e16dbd8
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "net/dns/host_resolver_impl.h" 6 7#if defined(OS_WIN) 8#include <Winsock2.h> 9#elif defined(OS_POSIX) 10#include <netdb.h> 11#endif 12 13#include <cmath> 14#include <utility> 15#include <vector> 16 17#include "base/basictypes.h" 18#include "base/bind.h" 19#include "base/bind_helpers.h" 20#include "base/callback.h" 21#include "base/compiler_specific.h" 22#include "base/debug/debugger.h" 23#include "base/debug/stack_trace.h" 24#include "base/message_loop/message_loop_proxy.h" 25#include "base/metrics/field_trial.h" 26#include "base/metrics/histogram.h" 27#include "base/stl_util.h" 28#include "base/string_util.h" 29#include "base/strings/utf_string_conversions.h" 30#include "base/threading/worker_pool.h" 31#include "base/time.h" 32#include "base/values.h" 33#include "net/base/address_family.h" 34#include "net/base/address_list.h" 35#include "net/base/dns_reloader.h" 36#include "net/base/dns_util.h" 37#include "net/base/host_port_pair.h" 38#include "net/base/net_errors.h" 39#include "net/base/net_log.h" 40#include "net/base/net_util.h" 41#include "net/dns/address_sorter.h" 42#include "net/dns/dns_client.h" 43#include "net/dns/dns_config_service.h" 44#include "net/dns/dns_protocol.h" 45#include "net/dns/dns_response.h" 46#include "net/dns/dns_transaction.h" 47#include "net/dns/host_resolver_proc.h" 48#include "net/socket/client_socket_factory.h" 49#include "net/udp/datagram_client_socket.h" 50 51#if defined(OS_WIN) 52#include "net/base/winsock_init.h" 53#endif 54 55namespace net { 56 57namespace { 58 59// Limit the size of hostnames that will be resolved to combat issues in 60// some platform's resolvers. 61const size_t kMaxHostLength = 4096; 62 63// Default TTL for successful resolutions with ProcTask. 64const unsigned kCacheEntryTTLSeconds = 60; 65 66// Default TTL for unsuccessful resolutions with ProcTask. 67const unsigned kNegativeCacheEntryTTLSeconds = 0; 68 69// Minimum TTL for successful resolutions with DnsTask. 70const unsigned kMinimumTTLSeconds = kCacheEntryTTLSeconds; 71 72// Number of consecutive failures of DnsTask (with successful fallback) before 73// the DnsClient is disabled until the next DNS change. 74const unsigned kMaximumDnsFailures = 16; 75 76// We use a separate histogram name for each platform to facilitate the 77// display of error codes by their symbolic name (since each platform has 78// different mappings). 79const char kOSErrorsForGetAddrinfoHistogramName[] = 80#if defined(OS_WIN) 81 "Net.OSErrorsForGetAddrinfo_Win"; 82#elif defined(OS_MACOSX) 83 "Net.OSErrorsForGetAddrinfo_Mac"; 84#elif defined(OS_LINUX) 85 "Net.OSErrorsForGetAddrinfo_Linux"; 86#else 87 "Net.OSErrorsForGetAddrinfo"; 88#endif 89 90// Gets a list of the likely error codes that getaddrinfo() can return 91// (non-exhaustive). These are the error codes that we will track via 92// a histogram. 93std::vector<int> GetAllGetAddrinfoOSErrors() { 94 int os_errors[] = { 95#if defined(OS_POSIX) 96#if !defined(OS_FREEBSD) 97#if !defined(OS_ANDROID) 98 // EAI_ADDRFAMILY has been declared obsolete in Android's and 99 // FreeBSD's netdb.h. 100 EAI_ADDRFAMILY, 101#endif 102 // EAI_NODATA has been declared obsolete in FreeBSD's netdb.h. 103 EAI_NODATA, 104#endif 105 EAI_AGAIN, 106 EAI_BADFLAGS, 107 EAI_FAIL, 108 EAI_FAMILY, 109 EAI_MEMORY, 110 EAI_NONAME, 111 EAI_SERVICE, 112 EAI_SOCKTYPE, 113 EAI_SYSTEM, 114#elif defined(OS_WIN) 115 // See: http://msdn.microsoft.com/en-us/library/ms738520(VS.85).aspx 116 WSA_NOT_ENOUGH_MEMORY, 117 WSAEAFNOSUPPORT, 118 WSAEINVAL, 119 WSAESOCKTNOSUPPORT, 120 WSAHOST_NOT_FOUND, 121 WSANO_DATA, 122 WSANO_RECOVERY, 123 WSANOTINITIALISED, 124 WSATRY_AGAIN, 125 WSATYPE_NOT_FOUND, 126 // The following are not in doc, but might be to appearing in results :-(. 127 WSA_INVALID_HANDLE, 128#endif 129 }; 130 131 // Ensure all errors are positive, as histogram only tracks positive values. 132 for (size_t i = 0; i < arraysize(os_errors); ++i) { 133 os_errors[i] = std::abs(os_errors[i]); 134 } 135 136 return base::CustomHistogram::ArrayToCustomRanges(os_errors, 137 arraysize(os_errors)); 138} 139 140enum DnsResolveStatus { 141 RESOLVE_STATUS_DNS_SUCCESS = 0, 142 RESOLVE_STATUS_PROC_SUCCESS, 143 RESOLVE_STATUS_FAIL, 144 RESOLVE_STATUS_SUSPECT_NETBIOS, 145 RESOLVE_STATUS_MAX 146}; 147 148void UmaAsyncDnsResolveStatus(DnsResolveStatus result) { 149 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ResolveStatus", 150 result, 151 RESOLVE_STATUS_MAX); 152} 153 154bool ResemblesNetBIOSName(const std::string& hostname) { 155 return (hostname.size() < 16) && (hostname.find('.') == std::string::npos); 156} 157 158// True if |hostname| ends with either ".local" or ".local.". 159bool ResemblesMulticastDNSName(const std::string& hostname) { 160 DCHECK(!hostname.empty()); 161 const char kSuffix[] = ".local."; 162 const size_t kSuffixLen = sizeof(kSuffix) - 1; 163 const size_t kSuffixLenTrimmed = kSuffixLen - 1; 164 if (hostname[hostname.size() - 1] == '.') { 165 return hostname.size() > kSuffixLen && 166 !hostname.compare(hostname.size() - kSuffixLen, kSuffixLen, kSuffix); 167 } 168 return hostname.size() > kSuffixLenTrimmed && 169 !hostname.compare(hostname.size() - kSuffixLenTrimmed, kSuffixLenTrimmed, 170 kSuffix, kSuffixLenTrimmed); 171} 172 173// Attempts to connect a UDP socket to |dest|:80. 174bool IsGloballyReachable(const IPAddressNumber& dest) { 175 scoped_ptr<DatagramClientSocket> socket( 176 ClientSocketFactory::GetDefaultFactory()->CreateDatagramClientSocket( 177 DatagramSocket::DEFAULT_BIND, 178 RandIntCallback(), 179 NULL, 180 NetLog::Source())); 181 int rv = socket->Connect(IPEndPoint(dest, 80)); 182 if (rv != OK) 183 return false; 184 IPEndPoint endpoint; 185 rv = socket->GetLocalAddress(&endpoint); 186 if (rv != OK) 187 return false; 188 DCHECK(endpoint.GetFamily() == ADDRESS_FAMILY_IPV6); 189 const IPAddressNumber& address = endpoint.address(); 190 bool is_link_local = (address[0] == 0xFE) && ((address[1] & 0xC0) == 0x80); 191 if (is_link_local) 192 return false; 193 const uint8 kTeredoPrefix[] = { 0x20, 0x01, 0, 0 }; 194 bool is_teredo = std::equal(kTeredoPrefix, 195 kTeredoPrefix + arraysize(kTeredoPrefix), 196 address.begin()); 197 if (is_teredo) 198 return false; 199 return true; 200} 201 202// Provide a common macro to simplify code and readability. We must use a 203// macro as the underlying HISTOGRAM macro creates static variables. 204#define DNS_HISTOGRAM(name, time) UMA_HISTOGRAM_CUSTOM_TIMES(name, time, \ 205 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1), 100) 206 207// A macro to simplify code and readability. 208#define DNS_HISTOGRAM_BY_PRIORITY(basename, priority, time) \ 209 do { \ 210 switch (priority) { \ 211 case HIGHEST: DNS_HISTOGRAM(basename "_HIGHEST", time); break; \ 212 case MEDIUM: DNS_HISTOGRAM(basename "_MEDIUM", time); break; \ 213 case LOW: DNS_HISTOGRAM(basename "_LOW", time); break; \ 214 case LOWEST: DNS_HISTOGRAM(basename "_LOWEST", time); break; \ 215 case IDLE: DNS_HISTOGRAM(basename "_IDLE", time); break; \ 216 default: NOTREACHED(); break; \ 217 } \ 218 DNS_HISTOGRAM(basename, time); \ 219 } while (0) 220 221// Record time from Request creation until a valid DNS response. 222void RecordTotalTime(bool had_dns_config, 223 bool speculative, 224 base::TimeDelta duration) { 225 if (had_dns_config) { 226 if (speculative) { 227 DNS_HISTOGRAM("AsyncDNS.TotalTime_speculative", duration); 228 } else { 229 DNS_HISTOGRAM("AsyncDNS.TotalTime", duration); 230 } 231 } else { 232 if (speculative) { 233 DNS_HISTOGRAM("DNS.TotalTime_speculative", duration); 234 } else { 235 DNS_HISTOGRAM("DNS.TotalTime", duration); 236 } 237 } 238} 239 240void RecordTTL(base::TimeDelta ttl) { 241 UMA_HISTOGRAM_CUSTOM_TIMES("AsyncDNS.TTL", ttl, 242 base::TimeDelta::FromSeconds(1), 243 base::TimeDelta::FromDays(1), 100); 244} 245 246//----------------------------------------------------------------------------- 247 248AddressList EnsurePortOnAddressList(const AddressList& list, uint16 port) { 249 if (list.empty() || list.front().port() == port) 250 return list; 251 return AddressList::CopyWithPort(list, port); 252} 253 254// Returns true if |addresses| contains only IPv4 loopback addresses. 255bool IsAllIPv4Loopback(const AddressList& addresses) { 256 for (unsigned i = 0; i < addresses.size(); ++i) { 257 const IPAddressNumber& address = addresses[i].address(); 258 switch (addresses[i].GetFamily()) { 259 case ADDRESS_FAMILY_IPV4: 260 if (address[0] != 127) 261 return false; 262 break; 263 case ADDRESS_FAMILY_IPV6: 264 return false; 265 default: 266 NOTREACHED(); 267 return false; 268 } 269 } 270 return true; 271} 272 273// Creates NetLog parameters when the resolve failed. 274base::Value* NetLogProcTaskFailedCallback(uint32 attempt_number, 275 int net_error, 276 int os_error, 277 NetLog::LogLevel /* log_level */) { 278 DictionaryValue* dict = new DictionaryValue(); 279 if (attempt_number) 280 dict->SetInteger("attempt_number", attempt_number); 281 282 dict->SetInteger("net_error", net_error); 283 284 if (os_error) { 285 dict->SetInteger("os_error", os_error); 286#if defined(OS_POSIX) 287 dict->SetString("os_error_string", gai_strerror(os_error)); 288#elif defined(OS_WIN) 289 // Map the error code to a human-readable string. 290 LPWSTR error_string = NULL; 291 int size = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 292 FORMAT_MESSAGE_FROM_SYSTEM, 293 0, // Use the internal message table. 294 os_error, 295 0, // Use default language. 296 (LPWSTR)&error_string, 297 0, // Buffer size. 298 0); // Arguments (unused). 299 dict->SetString("os_error_string", WideToUTF8(error_string)); 300 LocalFree(error_string); 301#endif 302 } 303 304 return dict; 305} 306 307// Creates NetLog parameters when the DnsTask failed. 308base::Value* NetLogDnsTaskFailedCallback(int net_error, 309 int dns_error, 310 NetLog::LogLevel /* log_level */) { 311 DictionaryValue* dict = new DictionaryValue(); 312 dict->SetInteger("net_error", net_error); 313 if (dns_error) 314 dict->SetInteger("dns_error", dns_error); 315 return dict; 316}; 317 318// Creates NetLog parameters containing the information in a RequestInfo object, 319// along with the associated NetLog::Source. 320base::Value* NetLogRequestInfoCallback(const NetLog::Source& source, 321 const HostResolver::RequestInfo* info, 322 NetLog::LogLevel /* log_level */) { 323 DictionaryValue* dict = new DictionaryValue(); 324 source.AddToEventParameters(dict); 325 326 dict->SetString("host", info->host_port_pair().ToString()); 327 dict->SetInteger("address_family", 328 static_cast<int>(info->address_family())); 329 dict->SetBoolean("allow_cached_response", info->allow_cached_response()); 330 dict->SetBoolean("is_speculative", info->is_speculative()); 331 dict->SetInteger("priority", info->priority()); 332 return dict; 333} 334 335// Creates NetLog parameters for the creation of a HostResolverImpl::Job. 336base::Value* NetLogJobCreationCallback(const NetLog::Source& source, 337 const std::string* host, 338 NetLog::LogLevel /* log_level */) { 339 DictionaryValue* dict = new DictionaryValue(); 340 source.AddToEventParameters(dict); 341 dict->SetString("host", *host); 342 return dict; 343} 344 345// Creates NetLog parameters for HOST_RESOLVER_IMPL_JOB_ATTACH/DETACH events. 346base::Value* NetLogJobAttachCallback(const NetLog::Source& source, 347 RequestPriority priority, 348 NetLog::LogLevel /* log_level */) { 349 DictionaryValue* dict = new DictionaryValue(); 350 source.AddToEventParameters(dict); 351 dict->SetInteger("priority", priority); 352 return dict; 353} 354 355// Creates NetLog parameters for the DNS_CONFIG_CHANGED event. 356base::Value* NetLogDnsConfigCallback(const DnsConfig* config, 357 NetLog::LogLevel /* log_level */) { 358 return config->ToValue(); 359} 360 361// The logging routines are defined here because some requests are resolved 362// without a Request object. 363 364// Logs when a request has just been started. 365void LogStartRequest(const BoundNetLog& source_net_log, 366 const BoundNetLog& request_net_log, 367 const HostResolver::RequestInfo& info) { 368 source_net_log.BeginEvent( 369 NetLog::TYPE_HOST_RESOLVER_IMPL, 370 request_net_log.source().ToEventParametersCallback()); 371 372 request_net_log.BeginEvent( 373 NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, 374 base::Bind(&NetLogRequestInfoCallback, source_net_log.source(), &info)); 375} 376 377// Logs when a request has just completed (before its callback is run). 378void LogFinishRequest(const BoundNetLog& source_net_log, 379 const BoundNetLog& request_net_log, 380 const HostResolver::RequestInfo& info, 381 int net_error) { 382 request_net_log.EndEventWithNetErrorCode( 383 NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, net_error); 384 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL); 385} 386 387// Logs when a request has been cancelled. 388void LogCancelRequest(const BoundNetLog& source_net_log, 389 const BoundNetLog& request_net_log, 390 const HostResolverImpl::RequestInfo& info) { 391 request_net_log.AddEvent(NetLog::TYPE_CANCELLED); 392 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST); 393 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL); 394} 395 396//----------------------------------------------------------------------------- 397 398// Keeps track of the highest priority. 399class PriorityTracker { 400 public: 401 explicit PriorityTracker(RequestPriority initial_priority) 402 : highest_priority_(initial_priority), total_count_(0) { 403 memset(counts_, 0, sizeof(counts_)); 404 } 405 406 RequestPriority highest_priority() const { 407 return highest_priority_; 408 } 409 410 size_t total_count() const { 411 return total_count_; 412 } 413 414 void Add(RequestPriority req_priority) { 415 ++total_count_; 416 ++counts_[req_priority]; 417 if (highest_priority_ < req_priority) 418 highest_priority_ = req_priority; 419 } 420 421 void Remove(RequestPriority req_priority) { 422 DCHECK_GT(total_count_, 0u); 423 DCHECK_GT(counts_[req_priority], 0u); 424 --total_count_; 425 --counts_[req_priority]; 426 size_t i; 427 for (i = highest_priority_; i > MINIMUM_PRIORITY && !counts_[i]; --i); 428 highest_priority_ = static_cast<RequestPriority>(i); 429 430 // In absence of requests, default to MINIMUM_PRIORITY. 431 if (total_count_ == 0) 432 DCHECK_EQ(MINIMUM_PRIORITY, highest_priority_); 433 } 434 435 private: 436 RequestPriority highest_priority_; 437 size_t total_count_; 438 size_t counts_[NUM_PRIORITIES]; 439}; 440 441} // namespace 442 443//----------------------------------------------------------------------------- 444 445// Holds the data for a request that could not be completed synchronously. 446// It is owned by a Job. Canceled Requests are only marked as canceled rather 447// than removed from the Job's |requests_| list. 448class HostResolverImpl::Request { 449 public: 450 Request(const BoundNetLog& source_net_log, 451 const BoundNetLog& request_net_log, 452 const RequestInfo& info, 453 const CompletionCallback& callback, 454 AddressList* addresses) 455 : source_net_log_(source_net_log), 456 request_net_log_(request_net_log), 457 info_(info), 458 job_(NULL), 459 callback_(callback), 460 addresses_(addresses), 461 request_time_(base::TimeTicks::Now()) { 462 } 463 464 // Mark the request as canceled. 465 void MarkAsCanceled() { 466 job_ = NULL; 467 addresses_ = NULL; 468 callback_.Reset(); 469 } 470 471 bool was_canceled() const { 472 return callback_.is_null(); 473 } 474 475 void set_job(Job* job) { 476 DCHECK(job); 477 // Identify which job the request is waiting on. 478 job_ = job; 479 } 480 481 // Prepare final AddressList and call completion callback. 482 void OnComplete(int error, const AddressList& addr_list) { 483 DCHECK(!was_canceled()); 484 if (error == OK) 485 *addresses_ = EnsurePortOnAddressList(addr_list, info_.port()); 486 CompletionCallback callback = callback_; 487 MarkAsCanceled(); 488 callback.Run(error); 489 } 490 491 Job* job() const { 492 return job_; 493 } 494 495 // NetLog for the source, passed in HostResolver::Resolve. 496 const BoundNetLog& source_net_log() { 497 return source_net_log_; 498 } 499 500 // NetLog for this request. 501 const BoundNetLog& request_net_log() { 502 return request_net_log_; 503 } 504 505 const RequestInfo& info() const { 506 return info_; 507 } 508 509 base::TimeTicks request_time() const { 510 return request_time_; 511 } 512 513 private: 514 BoundNetLog source_net_log_; 515 BoundNetLog request_net_log_; 516 517 // The request info that started the request. 518 RequestInfo info_; 519 520 // The resolve job that this request is dependent on. 521 Job* job_; 522 523 // The user's callback to invoke when the request completes. 524 CompletionCallback callback_; 525 526 // The address list to save result into. 527 AddressList* addresses_; 528 529 const base::TimeTicks request_time_; 530 531 DISALLOW_COPY_AND_ASSIGN(Request); 532}; 533 534//------------------------------------------------------------------------------ 535 536// Calls HostResolverProc on the WorkerPool. Performs retries if necessary. 537// 538// Whenever we try to resolve the host, we post a delayed task to check if host 539// resolution (OnLookupComplete) is completed or not. If the original attempt 540// hasn't completed, then we start another attempt for host resolution. We take 541// the results from the first attempt that finishes and ignore the results from 542// all other attempts. 543// 544// TODO(szym): Move to separate source file for testing and mocking. 545// 546class HostResolverImpl::ProcTask 547 : public base::RefCountedThreadSafe<HostResolverImpl::ProcTask> { 548 public: 549 typedef base::Callback<void(int net_error, 550 const AddressList& addr_list)> Callback; 551 552 ProcTask(const Key& key, 553 const ProcTaskParams& params, 554 const Callback& callback, 555 const BoundNetLog& job_net_log) 556 : key_(key), 557 params_(params), 558 callback_(callback), 559 origin_loop_(base::MessageLoopProxy::current()), 560 attempt_number_(0), 561 completed_attempt_number_(0), 562 completed_attempt_error_(ERR_UNEXPECTED), 563 had_non_speculative_request_(false), 564 net_log_(job_net_log) { 565 if (!params_.resolver_proc.get()) 566 params_.resolver_proc = HostResolverProc::GetDefault(); 567 // If default is unset, use the system proc. 568 if (!params_.resolver_proc.get()) 569 params_.resolver_proc = new SystemHostResolverProc(); 570 } 571 572 void Start() { 573 DCHECK(origin_loop_->BelongsToCurrentThread()); 574 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK); 575 StartLookupAttempt(); 576 } 577 578 // Cancels this ProcTask. It will be orphaned. Any outstanding resolve 579 // attempts running on worker threads will continue running. Only once all the 580 // attempts complete will the final reference to this ProcTask be released. 581 void Cancel() { 582 DCHECK(origin_loop_->BelongsToCurrentThread()); 583 584 if (was_canceled() || was_completed()) 585 return; 586 587 callback_.Reset(); 588 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK); 589 } 590 591 void set_had_non_speculative_request() { 592 DCHECK(origin_loop_->BelongsToCurrentThread()); 593 had_non_speculative_request_ = true; 594 } 595 596 bool was_canceled() const { 597 DCHECK(origin_loop_->BelongsToCurrentThread()); 598 return callback_.is_null(); 599 } 600 601 bool was_completed() const { 602 DCHECK(origin_loop_->BelongsToCurrentThread()); 603 return completed_attempt_number_ > 0; 604 } 605 606 private: 607 friend class base::RefCountedThreadSafe<ProcTask>; 608 ~ProcTask() {} 609 610 void StartLookupAttempt() { 611 DCHECK(origin_loop_->BelongsToCurrentThread()); 612 base::TimeTicks start_time = base::TimeTicks::Now(); 613 ++attempt_number_; 614 // Dispatch the lookup attempt to a worker thread. 615 if (!base::WorkerPool::PostTask( 616 FROM_HERE, 617 base::Bind(&ProcTask::DoLookup, this, start_time, attempt_number_), 618 true)) { 619 NOTREACHED(); 620 621 // Since we could be running within Resolve() right now, we can't just 622 // call OnLookupComplete(). Instead we must wait until Resolve() has 623 // returned (IO_PENDING). 624 origin_loop_->PostTask( 625 FROM_HERE, 626 base::Bind(&ProcTask::OnLookupComplete, this, AddressList(), 627 start_time, attempt_number_, ERR_UNEXPECTED, 0)); 628 return; 629 } 630 631 net_log_.AddEvent( 632 NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_STARTED, 633 NetLog::IntegerCallback("attempt_number", attempt_number_)); 634 635 // If we don't get the results within a given time, RetryIfNotComplete 636 // will start a new attempt on a different worker thread if none of our 637 // outstanding attempts have completed yet. 638 if (attempt_number_ <= params_.max_retry_attempts) { 639 origin_loop_->PostDelayedTask( 640 FROM_HERE, 641 base::Bind(&ProcTask::RetryIfNotComplete, this), 642 params_.unresponsive_delay); 643 } 644 } 645 646 // WARNING: This code runs inside a worker pool. The shutdown code cannot 647 // wait for it to finish, so we must be very careful here about using other 648 // objects (like MessageLoops, Singletons, etc). During shutdown these objects 649 // may no longer exist. Multiple DoLookups() could be running in parallel, so 650 // any state inside of |this| must not mutate . 651 void DoLookup(const base::TimeTicks& start_time, 652 const uint32 attempt_number) { 653 AddressList results; 654 int os_error = 0; 655 // Running on the worker thread 656 int error = params_.resolver_proc->Resolve(key_.hostname, 657 key_.address_family, 658 key_.host_resolver_flags, 659 &results, 660 &os_error); 661 662 origin_loop_->PostTask( 663 FROM_HERE, 664 base::Bind(&ProcTask::OnLookupComplete, this, results, start_time, 665 attempt_number, error, os_error)); 666 } 667 668 // Makes next attempt if DoLookup() has not finished (runs on origin thread). 669 void RetryIfNotComplete() { 670 DCHECK(origin_loop_->BelongsToCurrentThread()); 671 672 if (was_completed() || was_canceled()) 673 return; 674 675 params_.unresponsive_delay *= params_.retry_factor; 676 StartLookupAttempt(); 677 } 678 679 // Callback for when DoLookup() completes (runs on origin thread). 680 void OnLookupComplete(const AddressList& results, 681 const base::TimeTicks& start_time, 682 const uint32 attempt_number, 683 int error, 684 const int os_error) { 685 DCHECK(origin_loop_->BelongsToCurrentThread()); 686 // If results are empty, we should return an error. 687 bool empty_list_on_ok = (error == OK && results.empty()); 688 UMA_HISTOGRAM_BOOLEAN("DNS.EmptyAddressListAndNoError", empty_list_on_ok); 689 if (empty_list_on_ok) 690 error = ERR_NAME_NOT_RESOLVED; 691 692 bool was_retry_attempt = attempt_number > 1; 693 694 // Ideally the following code would be part of host_resolver_proc.cc, 695 // however it isn't safe to call NetworkChangeNotifier from worker threads. 696 // So we do it here on the IO thread instead. 697 if (error != OK && NetworkChangeNotifier::IsOffline()) 698 error = ERR_INTERNET_DISCONNECTED; 699 700 // If this is the first attempt that is finishing later, then record data 701 // for the first attempt. Won't contaminate with retry attempt's data. 702 if (!was_retry_attempt) 703 RecordPerformanceHistograms(start_time, error, os_error); 704 705 RecordAttemptHistograms(start_time, attempt_number, error, os_error); 706 707 if (was_canceled()) 708 return; 709 710 NetLog::ParametersCallback net_log_callback; 711 if (error != OK) { 712 net_log_callback = base::Bind(&NetLogProcTaskFailedCallback, 713 attempt_number, 714 error, 715 os_error); 716 } else { 717 net_log_callback = NetLog::IntegerCallback("attempt_number", 718 attempt_number); 719 } 720 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_FINISHED, 721 net_log_callback); 722 723 if (was_completed()) 724 return; 725 726 // Copy the results from the first worker thread that resolves the host. 727 results_ = results; 728 completed_attempt_number_ = attempt_number; 729 completed_attempt_error_ = error; 730 731 if (was_retry_attempt) { 732 // If retry attempt finishes before 1st attempt, then get stats on how 733 // much time is saved by having spawned an extra attempt. 734 retry_attempt_finished_time_ = base::TimeTicks::Now(); 735 } 736 737 if (error != OK) { 738 net_log_callback = base::Bind(&NetLogProcTaskFailedCallback, 739 0, error, os_error); 740 } else { 741 net_log_callback = results_.CreateNetLogCallback(); 742 } 743 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, 744 net_log_callback); 745 746 callback_.Run(error, results_); 747 } 748 749 void RecordPerformanceHistograms(const base::TimeTicks& start_time, 750 const int error, 751 const int os_error) const { 752 DCHECK(origin_loop_->BelongsToCurrentThread()); 753 enum Category { // Used in HISTOGRAM_ENUMERATION. 754 RESOLVE_SUCCESS, 755 RESOLVE_FAIL, 756 RESOLVE_SPECULATIVE_SUCCESS, 757 RESOLVE_SPECULATIVE_FAIL, 758 RESOLVE_MAX, // Bounding value. 759 }; 760 int category = RESOLVE_MAX; // Illegal value for later DCHECK only. 761 762 base::TimeDelta duration = base::TimeTicks::Now() - start_time; 763 if (error == OK) { 764 if (had_non_speculative_request_) { 765 category = RESOLVE_SUCCESS; 766 DNS_HISTOGRAM("DNS.ResolveSuccess", duration); 767 } else { 768 category = RESOLVE_SPECULATIVE_SUCCESS; 769 DNS_HISTOGRAM("DNS.ResolveSpeculativeSuccess", duration); 770 } 771 772 // Log DNS lookups based on |address_family|. This will help us determine 773 // if IPv4 or IPv4/6 lookups are faster or slower. 774 switch(key_.address_family) { 775 case ADDRESS_FAMILY_IPV4: 776 DNS_HISTOGRAM("DNS.ResolveSuccess_FAMILY_IPV4", duration); 777 break; 778 case ADDRESS_FAMILY_IPV6: 779 DNS_HISTOGRAM("DNS.ResolveSuccess_FAMILY_IPV6", duration); 780 break; 781 case ADDRESS_FAMILY_UNSPECIFIED: 782 DNS_HISTOGRAM("DNS.ResolveSuccess_FAMILY_UNSPEC", duration); 783 break; 784 } 785 } else { 786 if (had_non_speculative_request_) { 787 category = RESOLVE_FAIL; 788 DNS_HISTOGRAM("DNS.ResolveFail", duration); 789 } else { 790 category = RESOLVE_SPECULATIVE_FAIL; 791 DNS_HISTOGRAM("DNS.ResolveSpeculativeFail", duration); 792 } 793 // Log DNS lookups based on |address_family|. This will help us determine 794 // if IPv4 or IPv4/6 lookups are faster or slower. 795 switch(key_.address_family) { 796 case ADDRESS_FAMILY_IPV4: 797 DNS_HISTOGRAM("DNS.ResolveFail_FAMILY_IPV4", duration); 798 break; 799 case ADDRESS_FAMILY_IPV6: 800 DNS_HISTOGRAM("DNS.ResolveFail_FAMILY_IPV6", duration); 801 break; 802 case ADDRESS_FAMILY_UNSPECIFIED: 803 DNS_HISTOGRAM("DNS.ResolveFail_FAMILY_UNSPEC", duration); 804 break; 805 } 806 UMA_HISTOGRAM_CUSTOM_ENUMERATION(kOSErrorsForGetAddrinfoHistogramName, 807 std::abs(os_error), 808 GetAllGetAddrinfoOSErrors()); 809 } 810 DCHECK_LT(category, static_cast<int>(RESOLVE_MAX)); // Be sure it was set. 811 812 UMA_HISTOGRAM_ENUMERATION("DNS.ResolveCategory", category, RESOLVE_MAX); 813 } 814 815 void RecordAttemptHistograms(const base::TimeTicks& start_time, 816 const uint32 attempt_number, 817 const int error, 818 const int os_error) const { 819 DCHECK(origin_loop_->BelongsToCurrentThread()); 820 bool first_attempt_to_complete = 821 completed_attempt_number_ == attempt_number; 822 bool is_first_attempt = (attempt_number == 1); 823 824 if (first_attempt_to_complete) { 825 // If this was first attempt to complete, then record the resolution 826 // status of the attempt. 827 if (completed_attempt_error_ == OK) { 828 UMA_HISTOGRAM_ENUMERATION( 829 "DNS.AttemptFirstSuccess", attempt_number, 100); 830 } else { 831 UMA_HISTOGRAM_ENUMERATION( 832 "DNS.AttemptFirstFailure", attempt_number, 100); 833 } 834 } 835 836 if (error == OK) 837 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptSuccess", attempt_number, 100); 838 else 839 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptFailure", attempt_number, 100); 840 841 // If first attempt didn't finish before retry attempt, then calculate stats 842 // on how much time is saved by having spawned an extra attempt. 843 if (!first_attempt_to_complete && is_first_attempt && !was_canceled()) { 844 DNS_HISTOGRAM("DNS.AttemptTimeSavedByRetry", 845 base::TimeTicks::Now() - retry_attempt_finished_time_); 846 } 847 848 if (was_canceled() || !first_attempt_to_complete) { 849 // Count those attempts which completed after the job was already canceled 850 // OR after the job was already completed by an earlier attempt (so in 851 // effect). 852 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptDiscarded", attempt_number, 100); 853 854 // Record if job is canceled. 855 if (was_canceled()) 856 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptCancelled", attempt_number, 100); 857 } 858 859 base::TimeDelta duration = base::TimeTicks::Now() - start_time; 860 if (error == OK) 861 DNS_HISTOGRAM("DNS.AttemptSuccessDuration", duration); 862 else 863 DNS_HISTOGRAM("DNS.AttemptFailDuration", duration); 864 } 865 866 // Set on the origin thread, read on the worker thread. 867 Key key_; 868 869 // Holds an owning reference to the HostResolverProc that we are going to use. 870 // This may not be the current resolver procedure by the time we call 871 // ResolveAddrInfo, but that's OK... we'll use it anyways, and the owning 872 // reference ensures that it remains valid until we are done. 873 ProcTaskParams params_; 874 875 // The listener to the results of this ProcTask. 876 Callback callback_; 877 878 // Used to post ourselves onto the origin thread. 879 scoped_refptr<base::MessageLoopProxy> origin_loop_; 880 881 // Keeps track of the number of attempts we have made so far to resolve the 882 // host. Whenever we start an attempt to resolve the host, we increase this 883 // number. 884 uint32 attempt_number_; 885 886 // The index of the attempt which finished first (or 0 if the job is still in 887 // progress). 888 uint32 completed_attempt_number_; 889 890 // The result (a net error code) from the first attempt to complete. 891 int completed_attempt_error_; 892 893 // The time when retry attempt was finished. 894 base::TimeTicks retry_attempt_finished_time_; 895 896 // True if a non-speculative request was ever attached to this job 897 // (regardless of whether or not it was later canceled. 898 // This boolean is used for histogramming the duration of jobs used to 899 // service non-speculative requests. 900 bool had_non_speculative_request_; 901 902 AddressList results_; 903 904 BoundNetLog net_log_; 905 906 DISALLOW_COPY_AND_ASSIGN(ProcTask); 907}; 908 909//----------------------------------------------------------------------------- 910 911// Wraps a call to TestIPv6Support to be executed on the WorkerPool as it takes 912// 40-100ms. 913// TODO(szym): Remove altogether, if IPv6ActiveProbe works. 914class HostResolverImpl::IPv6ProbeJob { 915 public: 916 IPv6ProbeJob(const base::WeakPtr<HostResolverImpl>& resolver, NetLog* net_log) 917 : resolver_(resolver), 918 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_IPV6_PROBE_JOB)), 919 result_(false, IPV6_SUPPORT_MAX, OK) { 920 DCHECK(resolver.get()); 921 net_log_.BeginEvent(NetLog::TYPE_IPV6_PROBE_RUNNING); 922 const bool kIsSlow = true; 923 base::WorkerPool::PostTaskAndReply( 924 FROM_HERE, 925 base::Bind(&IPv6ProbeJob::DoProbe, base::Unretained(this)), 926 base::Bind(&IPv6ProbeJob::OnProbeComplete, base::Owned(this)), 927 kIsSlow); 928 } 929 930 virtual ~IPv6ProbeJob() {} 931 932 private: 933 // Runs on worker thread. 934 void DoProbe() { 935 result_ = TestIPv6Support(); 936 } 937 938 void OnProbeComplete() { 939 net_log_.EndEvent(NetLog::TYPE_IPV6_PROBE_RUNNING, 940 base::Bind(&IPv6SupportResult::ToNetLogValue, 941 base::Unretained(&result_))); 942 if (!resolver_.get()) 943 return; 944 resolver_->IPv6ProbeSetDefaultAddressFamily( 945 result_.ipv6_supported ? ADDRESS_FAMILY_UNSPECIFIED 946 : ADDRESS_FAMILY_IPV4); 947 } 948 949 // Used/set only on origin thread. 950 base::WeakPtr<HostResolverImpl> resolver_; 951 952 BoundNetLog net_log_; 953 954 IPv6SupportResult result_; 955 956 DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); 957}; 958 959// Wraps a call to HaveOnlyLoopbackAddresses to be executed on the WorkerPool as 960// it takes 40-100ms and should not block initialization. 961class HostResolverImpl::LoopbackProbeJob { 962 public: 963 explicit LoopbackProbeJob(const base::WeakPtr<HostResolverImpl>& resolver) 964 : resolver_(resolver), 965 result_(false) { 966 DCHECK(resolver.get()); 967 const bool kIsSlow = true; 968 base::WorkerPool::PostTaskAndReply( 969 FROM_HERE, 970 base::Bind(&LoopbackProbeJob::DoProbe, base::Unretained(this)), 971 base::Bind(&LoopbackProbeJob::OnProbeComplete, base::Owned(this)), 972 kIsSlow); 973 } 974 975 virtual ~LoopbackProbeJob() {} 976 977 private: 978 // Runs on worker thread. 979 void DoProbe() { 980 result_ = HaveOnlyLoopbackAddresses(); 981 } 982 983 void OnProbeComplete() { 984 if (!resolver_.get()) 985 return; 986 resolver_->SetHaveOnlyLoopbackAddresses(result_); 987 } 988 989 // Used/set only on origin thread. 990 base::WeakPtr<HostResolverImpl> resolver_; 991 992 bool result_; 993 994 DISALLOW_COPY_AND_ASSIGN(LoopbackProbeJob); 995}; 996 997//----------------------------------------------------------------------------- 998 999// Resolves the hostname using DnsTransaction. 1000// TODO(szym): This could be moved to separate source file as well. 1001class HostResolverImpl::DnsTask : public base::SupportsWeakPtr<DnsTask> { 1002 public: 1003 typedef base::Callback<void(int net_error, 1004 const AddressList& addr_list, 1005 base::TimeDelta ttl)> Callback; 1006 1007 DnsTask(DnsClient* client, 1008 const Key& key, 1009 const Callback& callback, 1010 const BoundNetLog& job_net_log) 1011 : client_(client), 1012 family_(key.address_family), 1013 callback_(callback), 1014 net_log_(job_net_log) { 1015 DCHECK(client); 1016 DCHECK(!callback.is_null()); 1017 1018 // If unspecified, do IPv4 first, because suffix search will be faster. 1019 uint16 qtype = (family_ == ADDRESS_FAMILY_IPV6) ? 1020 dns_protocol::kTypeAAAA : 1021 dns_protocol::kTypeA; 1022 transaction_ = client_->GetTransactionFactory()->CreateTransaction( 1023 key.hostname, 1024 qtype, 1025 base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this), 1026 true /* first_query */, base::TimeTicks::Now()), 1027 net_log_); 1028 } 1029 1030 int Start() { 1031 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK); 1032 return transaction_->Start(); 1033 } 1034 1035 private: 1036 void OnTransactionComplete(bool first_query, 1037 const base::TimeTicks& start_time, 1038 DnsTransaction* transaction, 1039 int net_error, 1040 const DnsResponse* response) { 1041 DCHECK(transaction); 1042 base::TimeDelta duration = base::TimeTicks::Now() - start_time; 1043 // Run |callback_| last since the owning Job will then delete this DnsTask. 1044 if (net_error != OK) { 1045 DNS_HISTOGRAM("AsyncDNS.TransactionFailure", duration); 1046 OnFailure(net_error, DnsResponse::DNS_PARSE_OK); 1047 return; 1048 } 1049 1050 CHECK(response); 1051 DNS_HISTOGRAM("AsyncDNS.TransactionSuccess", duration); 1052 switch (transaction->GetType()) { 1053 case dns_protocol::kTypeA: 1054 DNS_HISTOGRAM("AsyncDNS.TransactionSuccess_A", duration); 1055 break; 1056 case dns_protocol::kTypeAAAA: 1057 DNS_HISTOGRAM("AsyncDNS.TransactionSuccess_AAAA", duration); 1058 break; 1059 } 1060 AddressList addr_list; 1061 base::TimeDelta ttl; 1062 DnsResponse::Result result = response->ParseToAddressList(&addr_list, &ttl); 1063 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ParseToAddressList", 1064 result, 1065 DnsResponse::DNS_PARSE_RESULT_MAX); 1066 if (result != DnsResponse::DNS_PARSE_OK) { 1067 // Fail even if the other query succeeds. 1068 OnFailure(ERR_DNS_MALFORMED_RESPONSE, result); 1069 return; 1070 } 1071 1072 bool needs_sort = false; 1073 if (first_query) { 1074 DCHECK(client_->GetConfig()) << 1075 "Transaction should have been aborted when config changed!"; 1076 if (family_ == ADDRESS_FAMILY_IPV6) { 1077 needs_sort = (addr_list.size() > 1); 1078 } else if (family_ == ADDRESS_FAMILY_UNSPECIFIED) { 1079 first_addr_list_ = addr_list; 1080 first_ttl_ = ttl; 1081 // Use fully-qualified domain name to avoid search. 1082 transaction_ = client_->GetTransactionFactory()->CreateTransaction( 1083 response->GetDottedName() + ".", 1084 dns_protocol::kTypeAAAA, 1085 base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this), 1086 false /* first_query */, base::TimeTicks::Now()), 1087 net_log_); 1088 net_error = transaction_->Start(); 1089 if (net_error != ERR_IO_PENDING) 1090 OnFailure(net_error, DnsResponse::DNS_PARSE_OK); 1091 return; 1092 } 1093 } else { 1094 DCHECK_EQ(ADDRESS_FAMILY_UNSPECIFIED, family_); 1095 bool has_ipv6_addresses = !addr_list.empty(); 1096 if (!first_addr_list_.empty()) { 1097 ttl = std::min(ttl, first_ttl_); 1098 // Place IPv4 addresses after IPv6. 1099 addr_list.insert(addr_list.end(), first_addr_list_.begin(), 1100 first_addr_list_.end()); 1101 } 1102 needs_sort = (has_ipv6_addresses && addr_list.size() > 1); 1103 } 1104 1105 if (addr_list.empty()) { 1106 // TODO(szym): Don't fallback to ProcTask in this case. 1107 OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK); 1108 return; 1109 } 1110 1111 if (needs_sort) { 1112 // Sort could complete synchronously. 1113 client_->GetAddressSorter()->Sort( 1114 addr_list, 1115 base::Bind(&DnsTask::OnSortComplete, 1116 AsWeakPtr(), 1117 base::TimeTicks::Now(), 1118 ttl)); 1119 } else { 1120 OnSuccess(addr_list, ttl); 1121 } 1122 } 1123 1124 void OnSortComplete(base::TimeTicks start_time, 1125 base::TimeDelta ttl, 1126 bool success, 1127 const AddressList& addr_list) { 1128 if (!success) { 1129 DNS_HISTOGRAM("AsyncDNS.SortFailure", 1130 base::TimeTicks::Now() - start_time); 1131 OnFailure(ERR_DNS_SORT_ERROR, DnsResponse::DNS_PARSE_OK); 1132 return; 1133 } 1134 1135 DNS_HISTOGRAM("AsyncDNS.SortSuccess", 1136 base::TimeTicks::Now() - start_time); 1137 1138 // AddressSorter prunes unusable destinations. 1139 if (addr_list.empty()) { 1140 LOG(WARNING) << "Address list empty after RFC3484 sort"; 1141 OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK); 1142 return; 1143 } 1144 1145 OnSuccess(addr_list, ttl); 1146 } 1147 1148 void OnFailure(int net_error, DnsResponse::Result result) { 1149 DCHECK_NE(OK, net_error); 1150 net_log_.EndEvent( 1151 NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, 1152 base::Bind(&NetLogDnsTaskFailedCallback, net_error, result)); 1153 callback_.Run(net_error, AddressList(), base::TimeDelta()); 1154 } 1155 1156 void OnSuccess(const AddressList& addr_list, base::TimeDelta ttl) { 1157 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, 1158 addr_list.CreateNetLogCallback()); 1159 callback_.Run(OK, addr_list, ttl); 1160 } 1161 1162 DnsClient* client_; 1163 AddressFamily family_; 1164 // The listener to the results of this DnsTask. 1165 Callback callback_; 1166 const BoundNetLog net_log_; 1167 1168 scoped_ptr<DnsTransaction> transaction_; 1169 1170 // Results from the first transaction. Used only if |family_| is unspecified. 1171 AddressList first_addr_list_; 1172 base::TimeDelta first_ttl_; 1173 1174 DISALLOW_COPY_AND_ASSIGN(DnsTask); 1175}; 1176 1177//----------------------------------------------------------------------------- 1178 1179// Aggregates all Requests for the same Key. Dispatched via PriorityDispatch. 1180class HostResolverImpl::Job : public PrioritizedDispatcher::Job { 1181 public: 1182 // Creates new job for |key| where |request_net_log| is bound to the 1183 // request that spawned it. 1184 Job(const base::WeakPtr<HostResolverImpl>& resolver, 1185 const Key& key, 1186 RequestPriority priority, 1187 const BoundNetLog& request_net_log) 1188 : resolver_(resolver), 1189 key_(key), 1190 priority_tracker_(priority), 1191 had_non_speculative_request_(false), 1192 had_dns_config_(false), 1193 dns_task_error_(OK), 1194 creation_time_(base::TimeTicks::Now()), 1195 priority_change_time_(creation_time_), 1196 net_log_(BoundNetLog::Make(request_net_log.net_log(), 1197 NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)) { 1198 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB); 1199 1200 net_log_.BeginEvent( 1201 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, 1202 base::Bind(&NetLogJobCreationCallback, 1203 request_net_log.source(), 1204 &key_.hostname)); 1205 } 1206 1207 virtual ~Job() { 1208 if (is_running()) { 1209 // |resolver_| was destroyed with this Job still in flight. 1210 // Clean-up, record in the log, but don't run any callbacks. 1211 if (is_proc_running()) { 1212 proc_task_->Cancel(); 1213 proc_task_ = NULL; 1214 } 1215 // Clean up now for nice NetLog. 1216 dns_task_.reset(NULL); 1217 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, 1218 ERR_ABORTED); 1219 } else if (is_queued()) { 1220 // |resolver_| was destroyed without running this Job. 1221 // TODO(szym): is there any benefit in having this distinction? 1222 net_log_.AddEvent(NetLog::TYPE_CANCELLED); 1223 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB); 1224 } 1225 // else CompleteRequests logged EndEvent. 1226 1227 // Log any remaining Requests as cancelled. 1228 for (RequestsList::const_iterator it = requests_.begin(); 1229 it != requests_.end(); ++it) { 1230 Request* req = *it; 1231 if (req->was_canceled()) 1232 continue; 1233 DCHECK_EQ(this, req->job()); 1234 LogCancelRequest(req->source_net_log(), req->request_net_log(), 1235 req->info()); 1236 } 1237 } 1238 1239 // Add this job to the dispatcher. 1240 void Schedule() { 1241 handle_ = resolver_->dispatcher_.Add(this, priority()); 1242 } 1243 1244 void AddRequest(scoped_ptr<Request> req) { 1245 DCHECK_EQ(key_.hostname, req->info().hostname()); 1246 1247 req->set_job(this); 1248 priority_tracker_.Add(req->info().priority()); 1249 1250 req->request_net_log().AddEvent( 1251 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, 1252 net_log_.source().ToEventParametersCallback()); 1253 1254 net_log_.AddEvent( 1255 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_ATTACH, 1256 base::Bind(&NetLogJobAttachCallback, 1257 req->request_net_log().source(), 1258 priority())); 1259 1260 // TODO(szym): Check if this is still needed. 1261 if (!req->info().is_speculative()) { 1262 had_non_speculative_request_ = true; 1263 if (proc_task_.get()) 1264 proc_task_->set_had_non_speculative_request(); 1265 } 1266 1267 requests_.push_back(req.release()); 1268 1269 UpdatePriority(); 1270 } 1271 1272 // Marks |req| as cancelled. If it was the last active Request, also finishes 1273 // this Job, marking it as cancelled, and deletes it. 1274 void CancelRequest(Request* req) { 1275 DCHECK_EQ(key_.hostname, req->info().hostname()); 1276 DCHECK(!req->was_canceled()); 1277 1278 // Don't remove it from |requests_| just mark it canceled. 1279 req->MarkAsCanceled(); 1280 LogCancelRequest(req->source_net_log(), req->request_net_log(), 1281 req->info()); 1282 1283 priority_tracker_.Remove(req->info().priority()); 1284 net_log_.AddEvent( 1285 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_DETACH, 1286 base::Bind(&NetLogJobAttachCallback, 1287 req->request_net_log().source(), 1288 priority())); 1289 1290 if (num_active_requests() > 0) { 1291 UpdatePriority(); 1292 } else { 1293 // If we were called from a Request's callback within CompleteRequests, 1294 // that Request could not have been cancelled, so num_active_requests() 1295 // could not be 0. Therefore, we are not in CompleteRequests(). 1296 CompleteRequestsWithError(OK /* cancelled */); 1297 } 1298 } 1299 1300 // Called from AbortAllInProgressJobs. Completes all requests and destroys 1301 // the job. This currently assumes the abort is due to a network change. 1302 void Abort() { 1303 DCHECK(is_running()); 1304 CompleteRequestsWithError(ERR_NETWORK_CHANGED); 1305 } 1306 1307 // If DnsTask present, abort it and fall back to ProcTask. 1308 void AbortDnsTask() { 1309 if (dns_task_) { 1310 dns_task_.reset(); 1311 dns_task_error_ = OK; 1312 StartProcTask(); 1313 } 1314 } 1315 1316 // Called by HostResolverImpl when this job is evicted due to queue overflow. 1317 // Completes all requests and destroys the job. 1318 void OnEvicted() { 1319 DCHECK(!is_running()); 1320 DCHECK(is_queued()); 1321 handle_.Reset(); 1322 1323 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED); 1324 1325 // This signals to CompleteRequests that this job never ran. 1326 CompleteRequestsWithError(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE); 1327 } 1328 1329 // Attempts to serve the job from HOSTS. Returns true if succeeded and 1330 // this Job was destroyed. 1331 bool ServeFromHosts() { 1332 DCHECK_GT(num_active_requests(), 0u); 1333 AddressList addr_list; 1334 if (resolver_->ServeFromHosts(key(), 1335 requests_.front()->info(), 1336 &addr_list)) { 1337 // This will destroy the Job. 1338 CompleteRequests( 1339 HostCache::Entry(OK, MakeAddressListForRequest(addr_list)), 1340 base::TimeDelta()); 1341 return true; 1342 } 1343 return false; 1344 } 1345 1346 const Key key() const { 1347 return key_; 1348 } 1349 1350 bool is_queued() const { 1351 return !handle_.is_null(); 1352 } 1353 1354 bool is_running() const { 1355 return is_dns_running() || is_proc_running(); 1356 } 1357 1358 private: 1359 void UpdatePriority() { 1360 if (is_queued()) { 1361 if (priority() != static_cast<RequestPriority>(handle_.priority())) 1362 priority_change_time_ = base::TimeTicks::Now(); 1363 handle_ = resolver_->dispatcher_.ChangePriority(handle_, priority()); 1364 } 1365 } 1366 1367 AddressList MakeAddressListForRequest(const AddressList& list) const { 1368 if (requests_.empty()) 1369 return list; 1370 return AddressList::CopyWithPort(list, requests_.front()->info().port()); 1371 } 1372 1373 // PriorityDispatch::Job: 1374 virtual void Start() OVERRIDE { 1375 DCHECK(!is_running()); 1376 handle_.Reset(); 1377 1378 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED); 1379 1380 had_dns_config_ = resolver_->HaveDnsConfig(); 1381 1382 base::TimeTicks now = base::TimeTicks::Now(); 1383 base::TimeDelta queue_time = now - creation_time_; 1384 base::TimeDelta queue_time_after_change = now - priority_change_time_; 1385 1386 if (had_dns_config_) { 1387 DNS_HISTOGRAM_BY_PRIORITY("AsyncDNS.JobQueueTime", priority(), 1388 queue_time); 1389 DNS_HISTOGRAM_BY_PRIORITY("AsyncDNS.JobQueueTimeAfterChange", priority(), 1390 queue_time_after_change); 1391 } else { 1392 DNS_HISTOGRAM_BY_PRIORITY("DNS.JobQueueTime", priority(), queue_time); 1393 DNS_HISTOGRAM_BY_PRIORITY("DNS.JobQueueTimeAfterChange", priority(), 1394 queue_time_after_change); 1395 } 1396 1397 // Caution: Job::Start must not complete synchronously. 1398 if (had_dns_config_ && !ResemblesMulticastDNSName(key_.hostname)) { 1399 StartDnsTask(); 1400 } else { 1401 StartProcTask(); 1402 } 1403 } 1404 1405 // TODO(szym): Since DnsTransaction does not consume threads, we can increase 1406 // the limits on |dispatcher_|. But in order to keep the number of WorkerPool 1407 // threads low, we will need to use an "inner" PrioritizedDispatcher with 1408 // tighter limits. 1409 void StartProcTask() { 1410 DCHECK(!is_dns_running()); 1411 proc_task_ = new ProcTask( 1412 key_, 1413 resolver_->proc_params_, 1414 base::Bind(&Job::OnProcTaskComplete, base::Unretained(this), 1415 base::TimeTicks::Now()), 1416 net_log_); 1417 1418 if (had_non_speculative_request_) 1419 proc_task_->set_had_non_speculative_request(); 1420 // Start() could be called from within Resolve(), hence it must NOT directly 1421 // call OnProcTaskComplete, for example, on synchronous failure. 1422 proc_task_->Start(); 1423 } 1424 1425 // Called by ProcTask when it completes. 1426 void OnProcTaskComplete(base::TimeTicks start_time, 1427 int net_error, 1428 const AddressList& addr_list) { 1429 DCHECK(is_proc_running()); 1430 1431 if (!resolver_->resolved_known_ipv6_hostname_ && 1432 net_error == OK && 1433 key_.address_family == ADDRESS_FAMILY_UNSPECIFIED) { 1434 if (key_.hostname == "www.google.com") { 1435 resolver_->resolved_known_ipv6_hostname_ = true; 1436 bool got_ipv6_address = false; 1437 for (size_t i = 0; i < addr_list.size(); ++i) { 1438 if (addr_list[i].GetFamily() == ADDRESS_FAMILY_IPV6) 1439 got_ipv6_address = true; 1440 } 1441 UMA_HISTOGRAM_BOOLEAN("Net.UnspecResolvedIPv6", got_ipv6_address); 1442 } 1443 } 1444 1445 if (dns_task_error_ != OK) { 1446 base::TimeDelta duration = base::TimeTicks::Now() - start_time; 1447 if (net_error == OK) { 1448 DNS_HISTOGRAM("AsyncDNS.FallbackSuccess", duration); 1449 if ((dns_task_error_ == ERR_NAME_NOT_RESOLVED) && 1450 ResemblesNetBIOSName(key_.hostname)) { 1451 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_SUSPECT_NETBIOS); 1452 } else { 1453 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_PROC_SUCCESS); 1454 } 1455 UMA_HISTOGRAM_CUSTOM_ENUMERATION("AsyncDNS.ResolveError", 1456 std::abs(dns_task_error_), 1457 GetAllErrorCodesForUma()); 1458 resolver_->OnDnsTaskResolve(dns_task_error_); 1459 } else { 1460 DNS_HISTOGRAM("AsyncDNS.FallbackFail", duration); 1461 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_FAIL); 1462 } 1463 } 1464 1465 base::TimeDelta ttl = 1466 base::TimeDelta::FromSeconds(kNegativeCacheEntryTTLSeconds); 1467 if (net_error == OK) 1468 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); 1469 1470 // Don't store the |ttl| in cache since it's not obtained from the server. 1471 CompleteRequests( 1472 HostCache::Entry(net_error, MakeAddressListForRequest(addr_list)), 1473 ttl); 1474 } 1475 1476 void StartDnsTask() { 1477 DCHECK(resolver_->HaveDnsConfig()); 1478 dns_task_.reset(new DnsTask( 1479 resolver_->dns_client_.get(), 1480 key_, 1481 base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this), 1482 base::TimeTicks::Now()), 1483 net_log_)); 1484 1485 int rv = dns_task_->Start(); 1486 if (rv != ERR_IO_PENDING) { 1487 DCHECK_NE(OK, rv); 1488 dns_task_error_ = rv; 1489 dns_task_.reset(); 1490 StartProcTask(); 1491 } 1492 } 1493 1494 // Called by DnsTask when it completes. 1495 void OnDnsTaskComplete(base::TimeTicks start_time, 1496 int net_error, 1497 const AddressList& addr_list, 1498 base::TimeDelta ttl) { 1499 DCHECK(is_dns_running()); 1500 1501 base::TimeDelta duration = base::TimeTicks::Now() - start_time; 1502 if (net_error != OK) { 1503 DNS_HISTOGRAM("AsyncDNS.ResolveFail", duration); 1504 1505 dns_task_error_ = net_error; 1506 dns_task_.reset(); 1507 1508 // TODO(szym): Run ServeFromHosts now if nsswitch.conf says so. 1509 // http://crbug.com/117655 1510 1511 // TODO(szym): Some net errors indicate lack of connectivity. Starting 1512 // ProcTask in that case is a waste of time. 1513 StartProcTask(); 1514 return; 1515 } 1516 DNS_HISTOGRAM("AsyncDNS.ResolveSuccess", duration); 1517 // Log DNS lookups based on |address_family|. 1518 switch(key_.address_family) { 1519 case ADDRESS_FAMILY_IPV4: 1520 DNS_HISTOGRAM("AsyncDNS.ResolveSuccess_FAMILY_IPV4", duration); 1521 break; 1522 case ADDRESS_FAMILY_IPV6: 1523 DNS_HISTOGRAM("AsyncDNS.ResolveSuccess_FAMILY_IPV6", duration); 1524 break; 1525 case ADDRESS_FAMILY_UNSPECIFIED: 1526 DNS_HISTOGRAM("AsyncDNS.ResolveSuccess_FAMILY_UNSPEC", duration); 1527 break; 1528 } 1529 1530 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_DNS_SUCCESS); 1531 RecordTTL(ttl); 1532 1533 resolver_->OnDnsTaskResolve(OK); 1534 1535 base::TimeDelta bounded_ttl = 1536 std::max(ttl, base::TimeDelta::FromSeconds(kMinimumTTLSeconds)); 1537 1538 CompleteRequests( 1539 HostCache::Entry(net_error, MakeAddressListForRequest(addr_list), ttl), 1540 bounded_ttl); 1541 } 1542 1543 // Performs Job's last rites. Completes all Requests. Deletes this. 1544 void CompleteRequests(const HostCache::Entry& entry, 1545 base::TimeDelta ttl) { 1546 CHECK(resolver_.get()); 1547 1548 // This job must be removed from resolver's |jobs_| now to make room for a 1549 // new job with the same key in case one of the OnComplete callbacks decides 1550 // to spawn one. Consequently, the job deletes itself when CompleteRequests 1551 // is done. 1552 scoped_ptr<Job> self_deleter(this); 1553 1554 resolver_->RemoveJob(this); 1555 1556 if (is_running()) { 1557 DCHECK(!is_queued()); 1558 if (is_proc_running()) { 1559 proc_task_->Cancel(); 1560 proc_task_ = NULL; 1561 } 1562 dns_task_.reset(); 1563 1564 // Signal dispatcher that a slot has opened. 1565 resolver_->dispatcher_.OnJobFinished(); 1566 } else if (is_queued()) { 1567 resolver_->dispatcher_.Cancel(handle_); 1568 handle_.Reset(); 1569 } 1570 1571 if (num_active_requests() == 0) { 1572 net_log_.AddEvent(NetLog::TYPE_CANCELLED); 1573 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, 1574 OK); 1575 return; 1576 } 1577 1578 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, 1579 entry.error); 1580 1581 DCHECK(!requests_.empty()); 1582 1583 if (entry.error == OK) { 1584 // Record this histogram here, when we know the system has a valid DNS 1585 // configuration. 1586 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HaveDnsConfig", 1587 resolver_->received_dns_config_); 1588 } 1589 1590 bool did_complete = (entry.error != ERR_NETWORK_CHANGED) && 1591 (entry.error != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE); 1592 if (did_complete) 1593 resolver_->CacheResult(key_, entry, ttl); 1594 1595 // Complete all of the requests that were attached to the job. 1596 for (RequestsList::const_iterator it = requests_.begin(); 1597 it != requests_.end(); ++it) { 1598 Request* req = *it; 1599 1600 if (req->was_canceled()) 1601 continue; 1602 1603 DCHECK_EQ(this, req->job()); 1604 // Update the net log and notify registered observers. 1605 LogFinishRequest(req->source_net_log(), req->request_net_log(), 1606 req->info(), entry.error); 1607 if (did_complete) { 1608 // Record effective total time from creation to completion. 1609 RecordTotalTime(had_dns_config_, req->info().is_speculative(), 1610 base::TimeTicks::Now() - req->request_time()); 1611 } 1612 req->OnComplete(entry.error, entry.addrlist); 1613 1614 // Check if the resolver was destroyed as a result of running the 1615 // callback. If it was, we could continue, but we choose to bail. 1616 if (!resolver_.get()) 1617 return; 1618 } 1619 } 1620 1621 // Convenience wrapper for CompleteRequests in case of failure. 1622 void CompleteRequestsWithError(int net_error) { 1623 CompleteRequests(HostCache::Entry(net_error, AddressList()), 1624 base::TimeDelta()); 1625 } 1626 1627 RequestPriority priority() const { 1628 return priority_tracker_.highest_priority(); 1629 } 1630 1631 // Number of non-canceled requests in |requests_|. 1632 size_t num_active_requests() const { 1633 return priority_tracker_.total_count(); 1634 } 1635 1636 bool is_dns_running() const { 1637 return dns_task_.get() != NULL; 1638 } 1639 1640 bool is_proc_running() const { 1641 return proc_task_.get() != NULL; 1642 } 1643 1644 base::WeakPtr<HostResolverImpl> resolver_; 1645 1646 Key key_; 1647 1648 // Tracks the highest priority across |requests_|. 1649 PriorityTracker priority_tracker_; 1650 1651 bool had_non_speculative_request_; 1652 1653 // Distinguishes measurements taken while DnsClient was fully configured. 1654 bool had_dns_config_; 1655 1656 // Result of DnsTask. 1657 int dns_task_error_; 1658 1659 const base::TimeTicks creation_time_; 1660 base::TimeTicks priority_change_time_; 1661 1662 BoundNetLog net_log_; 1663 1664 // Resolves the host using a HostResolverProc. 1665 scoped_refptr<ProcTask> proc_task_; 1666 1667 // Resolves the host using a DnsTransaction. 1668 scoped_ptr<DnsTask> dns_task_; 1669 1670 // All Requests waiting for the result of this Job. Some can be canceled. 1671 RequestsList requests_; 1672 1673 // A handle used in |HostResolverImpl::dispatcher_|. 1674 PrioritizedDispatcher::Handle handle_; 1675}; 1676 1677//----------------------------------------------------------------------------- 1678 1679HostResolverImpl::ProcTaskParams::ProcTaskParams( 1680 HostResolverProc* resolver_proc, 1681 size_t max_retry_attempts) 1682 : resolver_proc(resolver_proc), 1683 max_retry_attempts(max_retry_attempts), 1684 unresponsive_delay(base::TimeDelta::FromMilliseconds(6000)), 1685 retry_factor(2) { 1686} 1687 1688HostResolverImpl::ProcTaskParams::~ProcTaskParams() {} 1689 1690HostResolverImpl::HostResolverImpl( 1691 scoped_ptr<HostCache> cache, 1692 const PrioritizedDispatcher::Limits& job_limits, 1693 const ProcTaskParams& proc_params, 1694 NetLog* net_log) 1695 : cache_(cache.Pass()), 1696 dispatcher_(job_limits), 1697 max_queued_jobs_(job_limits.total_jobs * 100u), 1698 proc_params_(proc_params), 1699 net_log_(net_log), 1700 default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), 1701 weak_ptr_factory_(this), 1702 probe_weak_ptr_factory_(this), 1703 received_dns_config_(false), 1704 num_dns_failures_(0), 1705 ipv6_probe_monitoring_(false), 1706 resolved_known_ipv6_hostname_(false), 1707 additional_resolver_flags_(0) { 1708 1709 DCHECK_GE(dispatcher_.num_priorities(), static_cast<size_t>(NUM_PRIORITIES)); 1710 1711 // Maximum of 4 retry attempts for host resolution. 1712 static const size_t kDefaultMaxRetryAttempts = 4u; 1713 1714 if (proc_params_.max_retry_attempts == HostResolver::kDefaultRetryAttempts) 1715 proc_params_.max_retry_attempts = kDefaultMaxRetryAttempts; 1716 1717#if defined(OS_WIN) 1718 EnsureWinsockInit(); 1719#endif 1720#if defined(OS_POSIX) && !defined(OS_MACOSX) 1721 new LoopbackProbeJob(weak_ptr_factory_.GetWeakPtr()); 1722#endif 1723 NetworkChangeNotifier::AddIPAddressObserver(this); 1724 NetworkChangeNotifier::AddDNSObserver(this); 1725#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) && \ 1726 !defined(OS_ANDROID) 1727 EnsureDnsReloaderInit(); 1728#endif 1729 1730 // TODO(szym): Remove when received_dns_config_ is removed, once 1731 // http://crbug.com/137914 is resolved. 1732 { 1733 DnsConfig dns_config; 1734 NetworkChangeNotifier::GetDnsConfig(&dns_config); 1735 received_dns_config_ = dns_config.IsValid(); 1736 } 1737} 1738 1739HostResolverImpl::~HostResolverImpl() { 1740 // This will also cancel all outstanding requests. 1741 STLDeleteValues(&jobs_); 1742 1743 NetworkChangeNotifier::RemoveIPAddressObserver(this); 1744 NetworkChangeNotifier::RemoveDNSObserver(this); 1745} 1746 1747void HostResolverImpl::SetMaxQueuedJobs(size_t value) { 1748 DCHECK_EQ(0u, dispatcher_.num_queued_jobs()); 1749 DCHECK_GT(value, 0u); 1750 max_queued_jobs_ = value; 1751} 1752 1753int HostResolverImpl::Resolve(const RequestInfo& info, 1754 AddressList* addresses, 1755 const CompletionCallback& callback, 1756 RequestHandle* out_req, 1757 const BoundNetLog& source_net_log) { 1758 DCHECK(addresses); 1759 DCHECK(CalledOnValidThread()); 1760 DCHECK_EQ(false, callback.is_null()); 1761 1762 // Check that the caller supplied a valid hostname to resolve. 1763 std::string labeled_hostname; 1764 if (!DNSDomainFromDot(info.hostname(), &labeled_hostname)) 1765 return ERR_NAME_NOT_RESOLVED; 1766 1767 // Make a log item for the request. 1768 BoundNetLog request_net_log = BoundNetLog::Make(net_log_, 1769 NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST); 1770 1771 LogStartRequest(source_net_log, request_net_log, info); 1772 1773 // Build a key that identifies the request in the cache and in the 1774 // outstanding jobs map. 1775 Key key = GetEffectiveKeyForRequest(info); 1776 1777 int rv = ResolveHelper(key, info, addresses, request_net_log); 1778 if (rv != ERR_DNS_CACHE_MISS) { 1779 LogFinishRequest(source_net_log, request_net_log, info, rv); 1780 RecordTotalTime(HaveDnsConfig(), info.is_speculative(), base::TimeDelta()); 1781 return rv; 1782 } 1783 1784 // Next we need to attach our request to a "job". This job is responsible for 1785 // calling "getaddrinfo(hostname)" on a worker thread. 1786 1787 JobMap::iterator jobit = jobs_.find(key); 1788 Job* job; 1789 if (jobit == jobs_.end()) { 1790 job = new Job(weak_ptr_factory_.GetWeakPtr(), key, info.priority(), 1791 request_net_log); 1792 job->Schedule(); 1793 1794 // Check for queue overflow. 1795 if (dispatcher_.num_queued_jobs() > max_queued_jobs_) { 1796 Job* evicted = static_cast<Job*>(dispatcher_.EvictOldestLowest()); 1797 DCHECK(evicted); 1798 evicted->OnEvicted(); // Deletes |evicted|. 1799 if (evicted == job) { 1800 rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; 1801 LogFinishRequest(source_net_log, request_net_log, info, rv); 1802 return rv; 1803 } 1804 } 1805 jobs_.insert(jobit, std::make_pair(key, job)); 1806 } else { 1807 job = jobit->second; 1808 } 1809 1810 // Can't complete synchronously. Create and attach request. 1811 scoped_ptr<Request> req(new Request(source_net_log, 1812 request_net_log, 1813 info, 1814 callback, 1815 addresses)); 1816 if (out_req) 1817 *out_req = reinterpret_cast<RequestHandle>(req.get()); 1818 1819 job->AddRequest(req.Pass()); 1820 // Completion happens during Job::CompleteRequests(). 1821 return ERR_IO_PENDING; 1822} 1823 1824int HostResolverImpl::ResolveHelper(const Key& key, 1825 const RequestInfo& info, 1826 AddressList* addresses, 1827 const BoundNetLog& request_net_log) { 1828 // The result of |getaddrinfo| for empty hosts is inconsistent across systems. 1829 // On Windows it gives the default interface's address, whereas on Linux it 1830 // gives an error. We will make it fail on all platforms for consistency. 1831 if (info.hostname().empty() || info.hostname().size() > kMaxHostLength) 1832 return ERR_NAME_NOT_RESOLVED; 1833 1834 int net_error = ERR_UNEXPECTED; 1835 if (ResolveAsIP(key, info, &net_error, addresses)) 1836 return net_error; 1837 if (ServeFromCache(key, info, &net_error, addresses)) { 1838 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT); 1839 return net_error; 1840 } 1841 // TODO(szym): Do not do this if nsswitch.conf instructs not to. 1842 // http://crbug.com/117655 1843 if (ServeFromHosts(key, info, addresses)) { 1844 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_HOSTS_HIT); 1845 return OK; 1846 } 1847 return ERR_DNS_CACHE_MISS; 1848} 1849 1850int HostResolverImpl::ResolveFromCache(const RequestInfo& info, 1851 AddressList* addresses, 1852 const BoundNetLog& source_net_log) { 1853 DCHECK(CalledOnValidThread()); 1854 DCHECK(addresses); 1855 1856 // Make a log item for the request. 1857 BoundNetLog request_net_log = BoundNetLog::Make(net_log_, 1858 NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST); 1859 1860 // Update the net log and notify registered observers. 1861 LogStartRequest(source_net_log, request_net_log, info); 1862 1863 Key key = GetEffectiveKeyForRequest(info); 1864 1865 int rv = ResolveHelper(key, info, addresses, request_net_log); 1866 LogFinishRequest(source_net_log, request_net_log, info, rv); 1867 return rv; 1868} 1869 1870void HostResolverImpl::CancelRequest(RequestHandle req_handle) { 1871 DCHECK(CalledOnValidThread()); 1872 Request* req = reinterpret_cast<Request*>(req_handle); 1873 DCHECK(req); 1874 Job* job = req->job(); 1875 DCHECK(job); 1876 job->CancelRequest(req); 1877} 1878 1879void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) { 1880 DCHECK(CalledOnValidThread()); 1881 default_address_family_ = address_family; 1882 ipv6_probe_monitoring_ = false; 1883} 1884 1885AddressFamily HostResolverImpl::GetDefaultAddressFamily() const { 1886 return default_address_family_; 1887} 1888 1889// TODO(szym): Remove this API altogether if IPv6ActiveProbe works. 1890void HostResolverImpl::ProbeIPv6Support() { 1891 DCHECK(CalledOnValidThread()); 1892 DCHECK(!ipv6_probe_monitoring_); 1893 ipv6_probe_monitoring_ = true; 1894 OnIPAddressChanged(); 1895} 1896 1897void HostResolverImpl::SetDnsClientEnabled(bool enabled) { 1898 DCHECK(CalledOnValidThread()); 1899#if defined(ENABLE_BUILT_IN_DNS) 1900 if (enabled && !dns_client_) { 1901 SetDnsClient(DnsClient::CreateClient(net_log_)); 1902 } else if (!enabled && dns_client_) { 1903 SetDnsClient(scoped_ptr<DnsClient>()); 1904 } 1905#endif 1906} 1907 1908HostCache* HostResolverImpl::GetHostCache() { 1909 return cache_.get(); 1910} 1911 1912base::Value* HostResolverImpl::GetDnsConfigAsValue() const { 1913 // Check if async DNS is disabled. 1914 if (!dns_client_.get()) 1915 return NULL; 1916 1917 // Check if async DNS is enabled, but we currently have no configuration 1918 // for it. 1919 const DnsConfig* dns_config = dns_client_->GetConfig(); 1920 if (dns_config == NULL) 1921 return new DictionaryValue(); 1922 1923 return dns_config->ToValue(); 1924} 1925 1926bool HostResolverImpl::ResolveAsIP(const Key& key, 1927 const RequestInfo& info, 1928 int* net_error, 1929 AddressList* addresses) { 1930 DCHECK(addresses); 1931 DCHECK(net_error); 1932 IPAddressNumber ip_number; 1933 if (!ParseIPLiteralToNumber(key.hostname, &ip_number)) 1934 return false; 1935 1936 DCHECK_EQ(key.host_resolver_flags & 1937 ~(HOST_RESOLVER_CANONNAME | HOST_RESOLVER_LOOPBACK_ONLY | 1938 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6), 1939 0) << " Unhandled flag"; 1940 bool ipv6_disabled = (default_address_family_ == ADDRESS_FAMILY_IPV4) && 1941 !ipv6_probe_monitoring_; 1942 *net_error = OK; 1943 if ((ip_number.size() == kIPv6AddressSize) && ipv6_disabled) { 1944 *net_error = ERR_NAME_NOT_RESOLVED; 1945 } else { 1946 *addresses = AddressList::CreateFromIPAddress(ip_number, info.port()); 1947 if (key.host_resolver_flags & HOST_RESOLVER_CANONNAME) 1948 addresses->SetDefaultCanonicalName(); 1949 } 1950 return true; 1951} 1952 1953bool HostResolverImpl::ServeFromCache(const Key& key, 1954 const RequestInfo& info, 1955 int* net_error, 1956 AddressList* addresses) { 1957 DCHECK(addresses); 1958 DCHECK(net_error); 1959 if (!info.allow_cached_response() || !cache_.get()) 1960 return false; 1961 1962 const HostCache::Entry* cache_entry = cache_->Lookup( 1963 key, base::TimeTicks::Now()); 1964 if (!cache_entry) 1965 return false; 1966 1967 *net_error = cache_entry->error; 1968 if (*net_error == OK) { 1969 if (cache_entry->has_ttl()) 1970 RecordTTL(cache_entry->ttl); 1971 *addresses = EnsurePortOnAddressList(cache_entry->addrlist, info.port()); 1972 } 1973 return true; 1974} 1975 1976bool HostResolverImpl::ServeFromHosts(const Key& key, 1977 const RequestInfo& info, 1978 AddressList* addresses) { 1979 DCHECK(addresses); 1980 if (!HaveDnsConfig()) 1981 return false; 1982 addresses->clear(); 1983 1984 // HOSTS lookups are case-insensitive. 1985 std::string hostname = StringToLowerASCII(key.hostname); 1986 1987 const DnsHosts& hosts = dns_client_->GetConfig()->hosts; 1988 1989 // If |address_family| is ADDRESS_FAMILY_UNSPECIFIED other implementations 1990 // (glibc and c-ares) return the first matching line. We have more 1991 // flexibility, but lose implicit ordering. 1992 // We prefer IPv6 because "happy eyeballs" will fall back to IPv4 if 1993 // necessary. 1994 if (key.address_family == ADDRESS_FAMILY_IPV6 || 1995 key.address_family == ADDRESS_FAMILY_UNSPECIFIED) { 1996 DnsHosts::const_iterator it = hosts.find( 1997 DnsHostsKey(hostname, ADDRESS_FAMILY_IPV6)); 1998 if (it != hosts.end()) 1999 addresses->push_back(IPEndPoint(it->second, info.port())); 2000 } 2001 2002 if (key.address_family == ADDRESS_FAMILY_IPV4 || 2003 key.address_family == ADDRESS_FAMILY_UNSPECIFIED) { 2004 DnsHosts::const_iterator it = hosts.find( 2005 DnsHostsKey(hostname, ADDRESS_FAMILY_IPV4)); 2006 if (it != hosts.end()) 2007 addresses->push_back(IPEndPoint(it->second, info.port())); 2008 } 2009 2010 // If got only loopback addresses and the family was restricted, resolve 2011 // again, without restrictions. See SystemHostResolverCall for rationale. 2012 if ((key.host_resolver_flags & 2013 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6) && 2014 IsAllIPv4Loopback(*addresses)) { 2015 Key new_key(key); 2016 new_key.address_family = ADDRESS_FAMILY_UNSPECIFIED; 2017 new_key.host_resolver_flags &= 2018 ~HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; 2019 return ServeFromHosts(new_key, info, addresses); 2020 } 2021 return !addresses->empty(); 2022} 2023 2024void HostResolverImpl::CacheResult(const Key& key, 2025 const HostCache::Entry& entry, 2026 base::TimeDelta ttl) { 2027 if (cache_.get()) 2028 cache_->Set(key, entry, base::TimeTicks::Now(), ttl); 2029} 2030 2031void HostResolverImpl::RemoveJob(Job* job) { 2032 DCHECK(job); 2033 JobMap::iterator it = jobs_.find(job->key()); 2034 if (it != jobs_.end() && it->second == job) 2035 jobs_.erase(it); 2036} 2037 2038void HostResolverImpl::IPv6ProbeSetDefaultAddressFamily( 2039 AddressFamily address_family) { 2040 DCHECK(address_family == ADDRESS_FAMILY_UNSPECIFIED || 2041 address_family == ADDRESS_FAMILY_IPV4); 2042 if (!ipv6_probe_monitoring_) 2043 return; 2044 if (default_address_family_ != address_family) { 2045 VLOG(1) << "IPv6Probe forced AddressFamily setting to " 2046 << ((address_family == ADDRESS_FAMILY_UNSPECIFIED) ? 2047 "ADDRESS_FAMILY_UNSPECIFIED" : "ADDRESS_FAMILY_IPV4"); 2048 } 2049 default_address_family_ = address_family; 2050} 2051 2052void HostResolverImpl::SetHaveOnlyLoopbackAddresses(bool result) { 2053 if (result) { 2054 additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; 2055 } else { 2056 additional_resolver_flags_ &= ~HOST_RESOLVER_LOOPBACK_ONLY; 2057 } 2058} 2059 2060HostResolverImpl::Key HostResolverImpl::GetEffectiveKeyForRequest( 2061 const RequestInfo& info) const { 2062 HostResolverFlags effective_flags = 2063 info.host_resolver_flags() | additional_resolver_flags_; 2064 AddressFamily effective_address_family = info.address_family(); 2065 2066 if (info.address_family() == ADDRESS_FAMILY_UNSPECIFIED) { 2067 if (ipv6_probe_monitoring_) { 2068 base::TimeTicks start_time = base::TimeTicks::Now(); 2069 // Google DNS address. 2070 const uint8 kIPv6Address[] = 2071 { 0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00, 2072 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88 }; 2073 IPAddressNumber address(kIPv6Address, 2074 kIPv6Address + arraysize(kIPv6Address)); 2075 bool rv6 = IsGloballyReachable(address); 2076 2077 UMA_HISTOGRAM_TIMES("Net.IPv6ConnectDuration", 2078 base::TimeTicks::Now() - start_time); 2079 if (rv6) { 2080 UMA_HISTOGRAM_BOOLEAN("Net.IPv6ConnectSuccessMatch", 2081 default_address_family_ == ADDRESS_FAMILY_UNSPECIFIED); 2082 } else { 2083 UMA_HISTOGRAM_BOOLEAN("Net.IPv6ConnectFailureMatch", 2084 default_address_family_ != ADDRESS_FAMILY_UNSPECIFIED); 2085 2086 effective_address_family = ADDRESS_FAMILY_IPV4; 2087 effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; 2088 } 2089 } else { 2090 effective_address_family = default_address_family_; 2091 } 2092 } 2093 2094 return Key(info.hostname(), effective_address_family, effective_flags); 2095} 2096 2097void HostResolverImpl::AbortAllInProgressJobs() { 2098 // In Abort, a Request callback could spawn new Jobs with matching keys, so 2099 // first collect and remove all running jobs from |jobs_|. 2100 ScopedVector<Job> jobs_to_abort; 2101 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ) { 2102 Job* job = it->second; 2103 if (job->is_running()) { 2104 jobs_to_abort.push_back(job); 2105 jobs_.erase(it++); 2106 } else { 2107 DCHECK(job->is_queued()); 2108 ++it; 2109 } 2110 } 2111 2112 // Check if no dispatcher slots leaked out. 2113 DCHECK_EQ(dispatcher_.num_running_jobs(), jobs_to_abort.size()); 2114 2115 // Life check to bail once |this| is deleted. 2116 base::WeakPtr<HostResolverImpl> self = weak_ptr_factory_.GetWeakPtr(); 2117 2118 // Then Abort them. 2119 for (size_t i = 0; self.get() && i < jobs_to_abort.size(); ++i) { 2120 jobs_to_abort[i]->Abort(); 2121 jobs_to_abort[i] = NULL; 2122 } 2123} 2124 2125void HostResolverImpl::TryServingAllJobsFromHosts() { 2126 if (!HaveDnsConfig()) 2127 return; 2128 2129 // TODO(szym): Do not do this if nsswitch.conf instructs not to. 2130 // http://crbug.com/117655 2131 2132 // Life check to bail once |this| is deleted. 2133 base::WeakPtr<HostResolverImpl> self = weak_ptr_factory_.GetWeakPtr(); 2134 2135 for (JobMap::iterator it = jobs_.begin(); self.get() && it != jobs_.end();) { 2136 Job* job = it->second; 2137 ++it; 2138 // This could remove |job| from |jobs_|, but iterator will remain valid. 2139 job->ServeFromHosts(); 2140 } 2141} 2142 2143void HostResolverImpl::OnIPAddressChanged() { 2144 resolved_known_ipv6_hostname_ = false; 2145 // Abandon all ProbeJobs. 2146 probe_weak_ptr_factory_.InvalidateWeakPtrs(); 2147 if (cache_.get()) 2148 cache_->clear(); 2149 if (ipv6_probe_monitoring_) 2150 new IPv6ProbeJob(probe_weak_ptr_factory_.GetWeakPtr(), net_log_); 2151#if defined(OS_POSIX) && !defined(OS_MACOSX) 2152 new LoopbackProbeJob(probe_weak_ptr_factory_.GetWeakPtr()); 2153#endif 2154 AbortAllInProgressJobs(); 2155 // |this| may be deleted inside AbortAllInProgressJobs(). 2156} 2157 2158void HostResolverImpl::OnDNSChanged() { 2159 DnsConfig dns_config; 2160 NetworkChangeNotifier::GetDnsConfig(&dns_config); 2161 2162 if (net_log_) { 2163 net_log_->AddGlobalEntry( 2164 NetLog::TYPE_DNS_CONFIG_CHANGED, 2165 base::Bind(&NetLogDnsConfigCallback, &dns_config)); 2166 } 2167 2168 // TODO(szym): Remove once http://crbug.com/137914 is resolved. 2169 received_dns_config_ = dns_config.IsValid(); 2170 2171 num_dns_failures_ = 0; 2172 2173 // We want a new DnsSession in place, before we Abort running Jobs, so that 2174 // the newly started jobs use the new config. 2175 if (dns_client_.get()) { 2176 dns_client_->SetConfig(dns_config); 2177 if (dns_config.IsValid()) 2178 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", true); 2179 } 2180 2181 // If the DNS server has changed, existing cached info could be wrong so we 2182 // have to drop our internal cache :( Note that OS level DNS caches, such 2183 // as NSCD's cache should be dropped automatically by the OS when 2184 // resolv.conf changes so we don't need to do anything to clear that cache. 2185 if (cache_.get()) 2186 cache_->clear(); 2187 2188 // Life check to bail once |this| is deleted. 2189 base::WeakPtr<HostResolverImpl> self = weak_ptr_factory_.GetWeakPtr(); 2190 2191 // Existing jobs will have been sent to the original server so they need to 2192 // be aborted. 2193 AbortAllInProgressJobs(); 2194 2195 // |this| may be deleted inside AbortAllInProgressJobs(). 2196 if (self.get()) 2197 TryServingAllJobsFromHosts(); 2198} 2199 2200bool HostResolverImpl::HaveDnsConfig() const { 2201 // Use DnsClient only if it's fully configured and there is no override by 2202 // ScopedDefaultHostResolverProc. 2203 // The alternative is to use NetworkChangeNotifier to override DnsConfig, 2204 // but that would introduce construction order requirements for NCN and SDHRP. 2205 return (dns_client_.get() != NULL) && (dns_client_->GetConfig() != NULL) && 2206 !(proc_params_.resolver_proc.get() == NULL && 2207 HostResolverProc::GetDefault() != NULL); 2208} 2209 2210void HostResolverImpl::OnDnsTaskResolve(int net_error) { 2211 DCHECK(dns_client_); 2212 if (net_error == OK) { 2213 num_dns_failures_ = 0; 2214 return; 2215 } 2216 ++num_dns_failures_; 2217 if (num_dns_failures_ < kMaximumDnsFailures) 2218 return; 2219 // Disable DnsClient until the next DNS change. 2220 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it) 2221 it->second->AbortDnsTask(); 2222 dns_client_->SetConfig(DnsConfig()); 2223 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", false); 2224 UMA_HISTOGRAM_CUSTOM_ENUMERATION("AsyncDNS.DnsClientDisabledReason", 2225 std::abs(net_error), 2226 GetAllErrorCodesForUma()); 2227} 2228 2229void HostResolverImpl::SetDnsClient(scoped_ptr<DnsClient> dns_client) { 2230 if (HaveDnsConfig()) { 2231 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it) 2232 it->second->AbortDnsTask(); 2233 } 2234 dns_client_ = dns_client.Pass(); 2235 if (!dns_client_ || dns_client_->GetConfig() || 2236 num_dns_failures_ >= kMaximumDnsFailures) { 2237 return; 2238 } 2239 DnsConfig dns_config; 2240 NetworkChangeNotifier::GetDnsConfig(&dns_config); 2241 dns_client_->SetConfig(dns_config); 2242 num_dns_failures_ = 0; 2243 if (dns_config.IsValid()) 2244 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", true); 2245} 2246 2247} // namespace net 2248