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