Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2010 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/base/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 <deque>
     15 #include <vector>
     16 
     17 #include "base/basictypes.h"
     18 #include "base/compiler_specific.h"
     19 #include "base/debug/debugger.h"
     20 #include "base/debug/stack_trace.h"
     21 #include "base/message_loop.h"
     22 #include "base/metrics/field_trial.h"
     23 #include "base/metrics/histogram.h"
     24 #include "base/stl_util-inl.h"
     25 #include "base/string_util.h"
     26 #include "base/synchronization/lock.h"
     27 #include "base/threading/worker_pool.h"
     28 #include "base/time.h"
     29 #include "base/utf_string_conversions.h"
     30 #include "base/values.h"
     31 #include "net/base/address_list.h"
     32 #include "net/base/address_list_net_log_param.h"
     33 #include "net/base/host_port_pair.h"
     34 #include "net/base/host_resolver_proc.h"
     35 #include "net/base/net_errors.h"
     36 #include "net/base/net_log.h"
     37 #include "net/base/net_util.h"
     38 
     39 #if defined(OS_WIN)
     40 #include "net/base/winsock_init.h"
     41 #endif
     42 
     43 namespace net {
     44 
     45 namespace {
     46 
     47 // We use a separate histogram name for each platform to facilitate the
     48 // display of error codes by their symbolic name (since each platform has
     49 // different mappings).
     50 const char kOSErrorsForGetAddrinfoHistogramName[] =
     51 #if defined(OS_WIN)
     52     "Net.OSErrorsForGetAddrinfo_Win";
     53 #elif defined(OS_MACOSX)
     54     "Net.OSErrorsForGetAddrinfo_Mac";
     55 #elif defined(OS_LINUX)
     56     "Net.OSErrorsForGetAddrinfo_Linux";
     57 #else
     58     "Net.OSErrorsForGetAddrinfo";
     59 #endif
     60 
     61 HostCache* CreateDefaultCache() {
     62   static const size_t kMaxHostCacheEntries = 100;
     63 
     64   HostCache* cache = new HostCache(
     65       kMaxHostCacheEntries,
     66       base::TimeDelta::FromMinutes(1),
     67       base::TimeDelta::FromSeconds(0));  // Disable caching of failed DNS.
     68 
     69   return cache;
     70 }
     71 
     72 }  // anonymous namespace
     73 
     74 HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves,
     75                                        HostResolverProc* resolver_proc,
     76                                        NetLog* net_log) {
     77   // Maximum of 8 concurrent resolver threads.
     78   // Some routers (or resolvers) appear to start to provide host-not-found if
     79   // too many simultaneous resolutions are pending.  This number needs to be
     80   // further optimized, but 8 is what FF currently does.
     81   static const size_t kDefaultMaxJobs = 8u;
     82 
     83   if (max_concurrent_resolves == HostResolver::kDefaultParallelism)
     84     max_concurrent_resolves = kDefaultMaxJobs;
     85 
     86   HostResolverImpl* resolver =
     87       new HostResolverImpl(resolver_proc, CreateDefaultCache(),
     88                            max_concurrent_resolves, net_log);
     89 
     90   return resolver;
     91 }
     92 
     93 static int ResolveAddrInfo(HostResolverProc* resolver_proc,
     94                            const std::string& host,
     95                            AddressFamily address_family,
     96                            HostResolverFlags host_resolver_flags,
     97                            AddressList* out,
     98                            int* os_error) {
     99   if (resolver_proc) {
    100     // Use the custom procedure.
    101     return resolver_proc->Resolve(host, address_family,
    102                                   host_resolver_flags, out, os_error);
    103   } else {
    104     // Use the system procedure (getaddrinfo).
    105     return SystemHostResolverProc(host, address_family,
    106                                   host_resolver_flags, out, os_error);
    107   }
    108 }
    109 
    110 // Extra parameters to attach to the NetLog when the resolve failed.
    111 class HostResolveFailedParams : public NetLog::EventParameters {
    112  public:
    113   HostResolveFailedParams(int net_error, int os_error)
    114       : net_error_(net_error),
    115         os_error_(os_error) {
    116   }
    117 
    118   virtual Value* ToValue() const {
    119     DictionaryValue* dict = new DictionaryValue();
    120     dict->SetInteger("net_error", net_error_);
    121 
    122     if (os_error_) {
    123       dict->SetInteger("os_error", os_error_);
    124 #if defined(OS_POSIX)
    125       dict->SetString("os_error_string", gai_strerror(os_error_));
    126 #elif defined(OS_WIN)
    127       // Map the error code to a human-readable string.
    128       LPWSTR error_string = NULL;
    129       int size = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
    130                                FORMAT_MESSAGE_FROM_SYSTEM,
    131                                0,  // Use the internal message table.
    132                                os_error_,
    133                                0,  // Use default language.
    134                                (LPWSTR)&error_string,
    135                                0,  // Buffer size.
    136                                0);  // Arguments (unused).
    137       dict->SetString("os_error_string", WideToUTF8(error_string));
    138       LocalFree(error_string);
    139 #endif
    140     }
    141 
    142     return dict;
    143   }
    144 
    145  private:
    146   const int net_error_;
    147   const int os_error_;
    148 };
    149 
    150 // Parameters representing the information in a RequestInfo object, along with
    151 // the associated NetLog::Source.
    152 class RequestInfoParameters : public NetLog::EventParameters {
    153  public:
    154   RequestInfoParameters(const HostResolver::RequestInfo& info,
    155                         const NetLog::Source& source)
    156       : info_(info), source_(source) {}
    157 
    158   virtual Value* ToValue() const {
    159     DictionaryValue* dict = new DictionaryValue();
    160     dict->SetString("host", info_.host_port_pair().ToString());
    161     dict->SetInteger("address_family",
    162                      static_cast<int>(info_.address_family()));
    163     dict->SetBoolean("allow_cached_response", info_.allow_cached_response());
    164     dict->SetBoolean("only_use_cached_response",
    165                      info_.only_use_cached_response());
    166     dict->SetBoolean("is_speculative", info_.is_speculative());
    167     dict->SetInteger("priority", info_.priority());
    168 
    169     if (source_.is_valid())
    170       dict->Set("source_dependency", source_.ToValue());
    171 
    172     return dict;
    173   }
    174 
    175  private:
    176   const HostResolver::RequestInfo info_;
    177   const NetLog::Source source_;
    178 };
    179 
    180 // Parameters associated with the creation of a HostResolverImpl::Job.
    181 class JobCreationParameters : public NetLog::EventParameters {
    182  public:
    183   JobCreationParameters(const std::string& host, const NetLog::Source& source)
    184       : host_(host), source_(source) {}
    185 
    186   virtual Value* ToValue() const {
    187     DictionaryValue* dict = new DictionaryValue();
    188     dict->SetString("host", host_);
    189     dict->Set("source_dependency", source_.ToValue());
    190     return dict;
    191   }
    192 
    193  private:
    194   const std::string host_;
    195   const NetLog::Source source_;
    196 };
    197 
    198 // Gets a list of the likely error codes that getaddrinfo() can return
    199 // (non-exhaustive). These are the error codes that we will track via
    200 // a histogram.
    201 std::vector<int> GetAllGetAddrinfoOSErrors() {
    202   int os_errors[] = {
    203 #if defined(OS_POSIX)
    204 #ifndef ANDROID
    205     // "obsoleted ..." see bionic/libc/include/netdb.h
    206     EAI_ADDRFAMILY,
    207 #endif
    208     EAI_AGAIN,
    209     EAI_BADFLAGS,
    210     EAI_FAIL,
    211     EAI_FAMILY,
    212     EAI_MEMORY,
    213     EAI_NODATA,
    214     EAI_NONAME,
    215     EAI_SERVICE,
    216     EAI_SOCKTYPE,
    217     EAI_SYSTEM,
    218 #elif defined(OS_WIN)
    219     // See: http://msdn.microsoft.com/en-us/library/ms738520(VS.85).aspx
    220     WSA_NOT_ENOUGH_MEMORY,
    221     WSAEAFNOSUPPORT,
    222     WSAEINVAL,
    223     WSAESOCKTNOSUPPORT,
    224     WSAHOST_NOT_FOUND,
    225     WSANO_DATA,
    226     WSANO_RECOVERY,
    227     WSANOTINITIALISED,
    228     WSATRY_AGAIN,
    229     WSATYPE_NOT_FOUND,
    230     // The following are not in doc, but might be to appearing in results :-(.
    231     WSA_INVALID_HANDLE,
    232 #endif
    233   };
    234 
    235   // Histogram enumerations require positive numbers.
    236   std::vector<int> errors;
    237   for (size_t i = 0; i < arraysize(os_errors); ++i) {
    238     errors.push_back(std::abs(os_errors[i]));
    239     // Also add N+1 for each error, so the bucket that contains our expected
    240     // error is of size 1. That way if we get unexpected error codes, they
    241     // won't fall into the same buckets as the expected ones.
    242     errors.push_back(std::abs(os_errors[i]) + 1);
    243   }
    244   return errors;
    245 }
    246 
    247 //-----------------------------------------------------------------------------
    248 
    249 class HostResolverImpl::Request {
    250  public:
    251   Request(const BoundNetLog& source_net_log,
    252           const BoundNetLog& request_net_log,
    253           int id,
    254           const RequestInfo& info,
    255           CompletionCallback* callback,
    256           AddressList* addresses)
    257       : source_net_log_(source_net_log),
    258         request_net_log_(request_net_log),
    259         id_(id),
    260         info_(info),
    261         job_(NULL),
    262         callback_(callback),
    263         addresses_(addresses) {
    264   }
    265 
    266   // Mark the request as cancelled.
    267   void MarkAsCancelled() {
    268     job_ = NULL;
    269     callback_ = NULL;
    270     addresses_ = NULL;
    271   }
    272 
    273   bool was_cancelled() const {
    274     return callback_ == NULL;
    275   }
    276 
    277   void set_job(Job* job) {
    278     DCHECK(job != NULL);
    279     // Identify which job the request is waiting on.
    280     job_ = job;
    281   }
    282 
    283   void OnComplete(int error, const AddressList& addrlist) {
    284     if (error == OK)
    285       addresses_->SetFrom(addrlist, port());
    286     CompletionCallback* callback = callback_;
    287     MarkAsCancelled();
    288     callback->Run(error);
    289   }
    290 
    291   int port() const {
    292     return info_.port();
    293   }
    294 
    295   Job* job() const {
    296     return job_;
    297   }
    298 
    299   const BoundNetLog& source_net_log() {
    300     return source_net_log_;
    301   }
    302 
    303   const BoundNetLog& request_net_log() {
    304     return request_net_log_;
    305   }
    306 
    307   int id() const {
    308     return id_;
    309   }
    310 
    311   const RequestInfo& info() const {
    312     return info_;
    313   }
    314 
    315  private:
    316   BoundNetLog source_net_log_;
    317   BoundNetLog request_net_log_;
    318 
    319   // Unique ID for this request. Used by observers to identify requests.
    320   int id_;
    321 
    322   // The request info that started the request.
    323   RequestInfo info_;
    324 
    325   // The resolve job (running in worker pool) that this request is dependent on.
    326   Job* job_;
    327 
    328   // The user's callback to invoke when the request completes.
    329   CompletionCallback* callback_;
    330 
    331   // The address list to save result into.
    332   AddressList* addresses_;
    333 
    334   DISALLOW_COPY_AND_ASSIGN(Request);
    335 };
    336 
    337 //------------------------------------------------------------------------------
    338 
    339 // Provide a common macro to simplify code and readability. We must use a
    340 // macros as the underlying HISTOGRAM macro creates static varibles.
    341 #define DNS_HISTOGRAM(name, time) UMA_HISTOGRAM_CUSTOM_TIMES(name, time, \
    342     base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromHours(1), 100)
    343 
    344 // This class represents a request to the worker pool for a "getaddrinfo()"
    345 // call.
    346 class HostResolverImpl::Job
    347     : public base::RefCountedThreadSafe<HostResolverImpl::Job> {
    348  public:
    349   Job(int id,
    350       HostResolverImpl* resolver,
    351       const Key& key,
    352       const BoundNetLog& source_net_log,
    353       NetLog* net_log)
    354      : id_(id),
    355        key_(key),
    356        resolver_(resolver),
    357        origin_loop_(MessageLoop::current()),
    358        resolver_proc_(resolver->effective_resolver_proc()),
    359        error_(OK),
    360        os_error_(0),
    361        had_non_speculative_request_(false),
    362        net_log_(BoundNetLog::Make(net_log,
    363                                   NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)) {
    364     net_log_.BeginEvent(
    365         NetLog::TYPE_HOST_RESOLVER_IMPL_JOB,
    366         make_scoped_refptr(
    367             new JobCreationParameters(key.hostname, source_net_log.source())));
    368   }
    369 
    370   // Attaches a request to this job. The job takes ownership of |req| and will
    371   // take care to delete it.
    372   void AddRequest(Request* req) {
    373     req->request_net_log().BeginEvent(
    374         NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH,
    375         make_scoped_refptr(new NetLogSourceParameter(
    376             "source_dependency", net_log_.source())));
    377 
    378     req->set_job(this);
    379     requests_.push_back(req);
    380 
    381     if (!req->info().is_speculative())
    382       had_non_speculative_request_ = true;
    383   }
    384 
    385   // Called from origin loop.
    386   void Start() {
    387     start_time_ = base::TimeTicks::Now();
    388 
    389     // Dispatch the job to a worker thread.
    390     if (!base::WorkerPool::PostTask(FROM_HERE,
    391             NewRunnableMethod(this, &Job::DoLookup), true)) {
    392       NOTREACHED();
    393 
    394       // Since we could be running within Resolve() right now, we can't just
    395       // call OnLookupComplete().  Instead we must wait until Resolve() has
    396       // returned (IO_PENDING).
    397       error_ = ERR_UNEXPECTED;
    398       MessageLoop::current()->PostTask(
    399           FROM_HERE, NewRunnableMethod(this, &Job::OnLookupComplete));
    400     }
    401   }
    402 
    403   // Cancels the current job. Callable from origin thread.
    404   void Cancel() {
    405     net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
    406 
    407     HostResolver* resolver = resolver_;
    408     resolver_ = NULL;
    409 
    410     // Mark the job as cancelled, so when worker thread completes it will
    411     // not try to post completion to origin loop.
    412     {
    413       base::AutoLock locked(origin_loop_lock_);
    414       origin_loop_ = NULL;
    415     }
    416 
    417     // End here to prevent issues when a Job outlives the HostResolver that
    418     // spawned it.
    419     net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, NULL);
    420 
    421     // We will call HostResolverImpl::CancelRequest(Request*) on each one
    422     // in order to notify any observers.
    423     for (RequestsList::const_iterator it = requests_.begin();
    424          it != requests_.end(); ++it) {
    425       HostResolverImpl::Request* req = *it;
    426       if (!req->was_cancelled())
    427         resolver->CancelRequest(req);
    428     }
    429   }
    430 
    431   // Called from origin thread.
    432   bool was_cancelled() const {
    433     return resolver_ == NULL;
    434   }
    435 
    436   // Called from origin thread.
    437   const Key& key() const {
    438     return key_;
    439   }
    440 
    441   int id() const {
    442     return id_;
    443   }
    444 
    445   base::TimeTicks start_time() const {
    446     return start_time_;
    447   }
    448 
    449   // Called from origin thread.
    450   const RequestsList& requests() const {
    451     return requests_;
    452   }
    453 
    454   // Returns the first request attached to the job.
    455   const Request* initial_request() const {
    456     DCHECK_EQ(origin_loop_, MessageLoop::current());
    457     DCHECK(!requests_.empty());
    458     return requests_[0];
    459   }
    460 
    461   // Returns true if |req_info| can be fulfilled by this job.
    462   bool CanServiceRequest(const RequestInfo& req_info) const {
    463     return key_ == resolver_->GetEffectiveKeyForRequest(req_info);
    464   }
    465 
    466  private:
    467   friend class base::RefCountedThreadSafe<HostResolverImpl::Job>;
    468 
    469   ~Job() {
    470     // Free the requests attached to this job.
    471     STLDeleteElements(&requests_);
    472   }
    473 
    474   // WARNING: This code runs inside a worker pool. The shutdown code cannot
    475   // wait for it to finish, so we must be very careful here about using other
    476   // objects (like MessageLoops, Singletons, etc). During shutdown these objects
    477   // may no longer exist.
    478   void DoLookup() {
    479     // Running on the worker thread
    480     error_ = ResolveAddrInfo(resolver_proc_,
    481                              key_.hostname,
    482                              key_.address_family,
    483                              key_.host_resolver_flags,
    484                              &results_,
    485                              &os_error_);
    486 
    487     // The origin loop could go away while we are trying to post to it, so we
    488     // need to call its PostTask method inside a lock.  See ~HostResolver.
    489     {
    490       base::AutoLock locked(origin_loop_lock_);
    491       if (origin_loop_) {
    492         origin_loop_->PostTask(FROM_HERE,
    493                                NewRunnableMethod(this, &Job::OnLookupComplete));
    494       }
    495     }
    496   }
    497 
    498   // Callback for when DoLookup() completes (runs on origin thread).
    499   void OnLookupComplete() {
    500     // Should be running on origin loop.
    501     // TODO(eroman): this is being hit by URLRequestTest.CancelTest*,
    502     // because MessageLoop::current() == NULL.
    503     //DCHECK_EQ(origin_loop_, MessageLoop::current());
    504     DCHECK(error_ || results_.head());
    505 
    506     // Ideally the following code would be part of host_resolver_proc.cc,
    507     // however it isn't safe to call NetworkChangeNotifier from worker
    508     // threads. So we do it here on the IO thread instead.
    509     if (error_ != OK && NetworkChangeNotifier::IsOffline())
    510       error_ = ERR_INTERNET_DISCONNECTED;
    511 
    512     RecordPerformanceHistograms();
    513 
    514     if (was_cancelled())
    515       return;
    516 
    517     scoped_refptr<NetLog::EventParameters> params;
    518     if (error_ != OK) {
    519       params = new HostResolveFailedParams(error_, os_error_);
    520     } else {
    521       params = new AddressListNetLogParam(results_);
    522     }
    523 
    524     // End here to prevent issues when a Job outlives the HostResolver that
    525     // spawned it.
    526     net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, params);
    527 
    528     DCHECK(!requests_.empty());
    529 
    530      // Use the port number of the first request.
    531     if (error_ == OK)
    532       results_.SetPort(requests_[0]->port());
    533 
    534     resolver_->OnJobComplete(this, error_, os_error_, results_);
    535   }
    536 
    537   void RecordPerformanceHistograms() const {
    538     enum Category {  // Used in HISTOGRAM_ENUMERATION.
    539       RESOLVE_SUCCESS,
    540       RESOLVE_FAIL,
    541       RESOLVE_SPECULATIVE_SUCCESS,
    542       RESOLVE_SPECULATIVE_FAIL,
    543       RESOLVE_MAX,  // Bounding value.
    544     };
    545     int category = RESOLVE_MAX;  // Illegal value for later DCHECK only.
    546 
    547     base::TimeDelta duration = base::TimeTicks::Now() - start_time_;
    548     if (error_ == OK) {
    549       if (had_non_speculative_request_) {
    550         category = RESOLVE_SUCCESS;
    551         DNS_HISTOGRAM("DNS.ResolveSuccess", duration);
    552       } else {
    553         category = RESOLVE_SPECULATIVE_SUCCESS;
    554         DNS_HISTOGRAM("DNS.ResolveSpeculativeSuccess", duration);
    555       }
    556     } else {
    557       if (had_non_speculative_request_) {
    558         category = RESOLVE_FAIL;
    559         DNS_HISTOGRAM("DNS.ResolveFail", duration);
    560       } else {
    561         category = RESOLVE_SPECULATIVE_FAIL;
    562         DNS_HISTOGRAM("DNS.ResolveSpeculativeFail", duration);
    563       }
    564       UMA_HISTOGRAM_CUSTOM_ENUMERATION(kOSErrorsForGetAddrinfoHistogramName,
    565                                        std::abs(os_error_),
    566                                        GetAllGetAddrinfoOSErrors());
    567     }
    568     DCHECK_LT(category, static_cast<int>(RESOLVE_MAX));  // Be sure it was set.
    569 
    570     UMA_HISTOGRAM_ENUMERATION("DNS.ResolveCategory", category, RESOLVE_MAX);
    571 
    572     static bool show_speculative_experiment_histograms =
    573         base::FieldTrialList::Find("DnsImpact") &&
    574         !base::FieldTrialList::Find("DnsImpact")->group_name().empty();
    575     if (show_speculative_experiment_histograms) {
    576       UMA_HISTOGRAM_ENUMERATION(
    577           base::FieldTrial::MakeName("DNS.ResolveCategory", "DnsImpact"),
    578           category, RESOLVE_MAX);
    579       if (RESOLVE_SUCCESS == category) {
    580         DNS_HISTOGRAM(base::FieldTrial::MakeName("DNS.ResolveSuccess",
    581                                                  "DnsImpact"), duration);
    582       }
    583     }
    584     static bool show_parallelism_experiment_histograms =
    585         base::FieldTrialList::Find("DnsParallelism") &&
    586         !base::FieldTrialList::Find("DnsParallelism")->group_name().empty();
    587     if (show_parallelism_experiment_histograms) {
    588       UMA_HISTOGRAM_ENUMERATION(
    589           base::FieldTrial::MakeName("DNS.ResolveCategory", "DnsParallelism"),
    590           category, RESOLVE_MAX);
    591       if (RESOLVE_SUCCESS == category) {
    592         DNS_HISTOGRAM(base::FieldTrial::MakeName("DNS.ResolveSuccess",
    593                                                  "DnsParallelism"), duration);
    594       }
    595     }
    596   }
    597 
    598 
    599 
    600   // Immutable. Can be read from either thread,
    601   const int id_;
    602 
    603   // Set on the origin thread, read on the worker thread.
    604   Key key_;
    605 
    606   // Only used on the origin thread (where Resolve was called).
    607   HostResolverImpl* resolver_;
    608   RequestsList requests_;  // The requests waiting on this job.
    609 
    610   // Used to post ourselves onto the origin thread.
    611   base::Lock origin_loop_lock_;
    612   MessageLoop* origin_loop_;
    613 
    614   // Hold an owning reference to the HostResolverProc that we are going to use.
    615   // This may not be the current resolver procedure by the time we call
    616   // ResolveAddrInfo, but that's OK... we'll use it anyways, and the owning
    617   // reference ensures that it remains valid until we are done.
    618   scoped_refptr<HostResolverProc> resolver_proc_;
    619 
    620   // Assigned on the worker thread, read on the origin thread.
    621   int error_;
    622   int os_error_;
    623 
    624   // True if a non-speculative request was ever attached to this job
    625   // (regardless of whether or not it was later cancelled.
    626   // This boolean is used for histogramming the duration of jobs used to
    627   // service non-speculative requests.
    628   bool had_non_speculative_request_;
    629 
    630   AddressList results_;
    631 
    632   // The time when the job was started.
    633   base::TimeTicks start_time_;
    634 
    635   BoundNetLog net_log_;
    636 
    637   DISALLOW_COPY_AND_ASSIGN(Job);
    638 };
    639 
    640 //-----------------------------------------------------------------------------
    641 
    642 // This class represents a request to the worker pool for a "probe for IPv6
    643 // support" call.
    644 class HostResolverImpl::IPv6ProbeJob
    645     : public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> {
    646  public:
    647   explicit IPv6ProbeJob(HostResolverImpl* resolver)
    648       : resolver_(resolver),
    649         origin_loop_(MessageLoop::current()) {
    650     DCHECK(!was_cancelled());
    651   }
    652 
    653   void Start() {
    654     if (was_cancelled())
    655       return;
    656     DCHECK(IsOnOriginThread());
    657     const bool kIsSlow = true;
    658     base::WorkerPool::PostTask(
    659         FROM_HERE, NewRunnableMethod(this, &IPv6ProbeJob::DoProbe), kIsSlow);
    660   }
    661 
    662   // Cancels the current job.
    663   void Cancel() {
    664     if (was_cancelled())
    665       return;
    666     DCHECK(IsOnOriginThread());
    667     resolver_ = NULL;  // Read/write ONLY on origin thread.
    668     {
    669       base::AutoLock locked(origin_loop_lock_);
    670       // Origin loop may be destroyed before we can use it!
    671       origin_loop_ = NULL;  // Write ONLY on origin thread.
    672     }
    673   }
    674 
    675  private:
    676   friend class base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob>;
    677 
    678   ~IPv6ProbeJob() {
    679   }
    680 
    681   // Should be run on |orgin_thread_|, but that may not be well defined now.
    682   bool was_cancelled() const {
    683     if (!resolver_ || !origin_loop_) {
    684       DCHECK(!resolver_);
    685       DCHECK(!origin_loop_);
    686       return true;
    687     }
    688     return false;
    689   }
    690 
    691   // Run on worker thread.
    692   void DoProbe() {
    693     // Do actual testing on this thread, as it takes 40-100ms.
    694     AddressFamily family = IPv6Supported() ? ADDRESS_FAMILY_UNSPECIFIED
    695                                            : ADDRESS_FAMILY_IPV4;
    696 
    697     Task* reply = NewRunnableMethod(this, &IPv6ProbeJob::OnProbeComplete,
    698                                     family);
    699 
    700     // The origin loop could go away while we are trying to post to it, so we
    701     // need to call its PostTask method inside a lock.  See ~HostResolver.
    702     {
    703       base::AutoLock locked(origin_loop_lock_);
    704       if (origin_loop_) {
    705         origin_loop_->PostTask(FROM_HERE, reply);
    706         return;
    707       }
    708     }
    709 
    710     // We didn't post, so delete the reply.
    711     delete reply;
    712   }
    713 
    714   // Callback for when DoProbe() completes (runs on origin thread).
    715   void OnProbeComplete(AddressFamily address_family) {
    716     if (was_cancelled())
    717       return;
    718     DCHECK(IsOnOriginThread());
    719     resolver_->IPv6ProbeSetDefaultAddressFamily(address_family);
    720   }
    721 
    722   bool IsOnOriginThread() const {
    723     return !MessageLoop::current() || origin_loop_ == MessageLoop::current();
    724   }
    725 
    726   // Used/set only on origin thread.
    727   HostResolverImpl* resolver_;
    728 
    729   // Used to post ourselves onto the origin thread.
    730   base::Lock origin_loop_lock_;
    731   MessageLoop* origin_loop_;
    732 
    733   DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob);
    734 };
    735 
    736 //-----------------------------------------------------------------------------
    737 
    738 // We rely on the priority enum values being sequential having starting at 0,
    739 // and increasing for lower priorities.
    740 COMPILE_ASSERT(HIGHEST == 0u &&
    741                LOWEST > HIGHEST &&
    742                IDLE > LOWEST &&
    743                NUM_PRIORITIES > IDLE,
    744                priority_indexes_incompatible);
    745 
    746 // JobPool contains all the information relating to queued requests, including
    747 // the limits on how many jobs are allowed to be used for this category of
    748 // requests.
    749 class HostResolverImpl::JobPool {
    750  public:
    751   JobPool(size_t max_outstanding_jobs, size_t max_pending_requests)
    752       : num_outstanding_jobs_(0u) {
    753     SetConstraints(max_outstanding_jobs, max_pending_requests);
    754   }
    755 
    756   ~JobPool() {
    757     // Free the pending requests.
    758     for (size_t i = 0; i < arraysize(pending_requests_); ++i)
    759       STLDeleteElements(&pending_requests_[i]);
    760   }
    761 
    762   // Sets the constraints for this pool. See SetPoolConstraints() for the
    763   // specific meaning of these parameters.
    764   void SetConstraints(size_t max_outstanding_jobs,
    765                       size_t max_pending_requests) {
    766     CHECK_NE(max_outstanding_jobs, 0u);
    767     max_outstanding_jobs_ = max_outstanding_jobs;
    768     max_pending_requests_ = max_pending_requests;
    769   }
    770 
    771   // Returns the number of pending requests enqueued to this pool.
    772   // A pending request is one waiting to be attached to a job.
    773   size_t GetNumPendingRequests() const {
    774     size_t total = 0u;
    775     for (size_t i = 0u; i < arraysize(pending_requests_); ++i)
    776       total += pending_requests_[i].size();
    777     return total;
    778   }
    779 
    780   bool HasPendingRequests() const {
    781     return GetNumPendingRequests() > 0u;
    782   }
    783 
    784   // Enqueues a request to this pool. As a result of enqueing this request,
    785   // the queue may have reached its maximum size. In this case, a request is
    786   // evicted from the queue, and returned. Otherwise returns NULL. The caller
    787   // is responsible for freeing the evicted request.
    788   Request* InsertPendingRequest(Request* req) {
    789     req->request_net_log().BeginEvent(
    790         NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_POOL_QUEUE,
    791         NULL);
    792 
    793     PendingRequestsQueue& q = pending_requests_[req->info().priority()];
    794     q.push_back(req);
    795 
    796     // If the queue is too big, kick out the lowest priority oldest request.
    797     if (GetNumPendingRequests() > max_pending_requests_) {
    798       // Iterate over the queues from lowest priority to highest priority.
    799       for (int i = static_cast<int>(arraysize(pending_requests_)) - 1;
    800            i >= 0; --i) {
    801         PendingRequestsQueue& q = pending_requests_[i];
    802         if (!q.empty()) {
    803           Request* req = q.front();
    804           q.pop_front();
    805           req->request_net_log().AddEvent(
    806               NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_POOL_QUEUE_EVICTED, NULL);
    807           req->request_net_log().EndEvent(
    808               NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_POOL_QUEUE, NULL);
    809           return req;
    810         }
    811       }
    812     }
    813 
    814     return NULL;
    815   }
    816 
    817   // Erases |req| from this container. Caller is responsible for freeing
    818   // |req| afterwards.
    819   void RemovePendingRequest(Request* req) {
    820     PendingRequestsQueue& q = pending_requests_[req->info().priority()];
    821     PendingRequestsQueue::iterator it = std::find(q.begin(), q.end(), req);
    822     DCHECK(it != q.end());
    823     q.erase(it);
    824     req->request_net_log().EndEvent(
    825         NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_POOL_QUEUE, NULL);
    826   }
    827 
    828   // Removes and returns the highest priority pending request.
    829   Request* RemoveTopPendingRequest() {
    830     DCHECK(HasPendingRequests());
    831 
    832     for (size_t i = 0u; i < arraysize(pending_requests_); ++i) {
    833       PendingRequestsQueue& q = pending_requests_[i];
    834       if (!q.empty()) {
    835         Request* req = q.front();
    836         q.pop_front();
    837         req->request_net_log().EndEvent(
    838             NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_POOL_QUEUE, NULL);
    839         return req;
    840       }
    841     }
    842 
    843     NOTREACHED();
    844     return NULL;
    845   }
    846 
    847   // Keeps track of a job that was just added/removed, and belongs to this pool.
    848   void AdjustNumOutstandingJobs(int offset) {
    849     DCHECK(offset == 1 || (offset == -1 && num_outstanding_jobs_ > 0u));
    850     num_outstanding_jobs_ += offset;
    851   }
    852 
    853   void ResetNumOutstandingJobs() {
    854     num_outstanding_jobs_ = 0;
    855   }
    856 
    857   // Returns true if a new job can be created for this pool.
    858   bool CanCreateJob() const {
    859     return num_outstanding_jobs_ + 1u <= max_outstanding_jobs_;
    860   }
    861 
    862   // Removes any pending requests from the queue which are for the
    863   // same (hostname / effective address-family) as |job|, and attaches them to
    864   // |job|.
    865   void MoveRequestsToJob(Job* job) {
    866     for (size_t i = 0u; i < arraysize(pending_requests_); ++i) {
    867       PendingRequestsQueue& q = pending_requests_[i];
    868       PendingRequestsQueue::iterator req_it = q.begin();
    869       while (req_it != q.end()) {
    870         Request* req = *req_it;
    871         if (job->CanServiceRequest(req->info())) {
    872           // Job takes ownership of |req|.
    873           job->AddRequest(req);
    874           req_it = q.erase(req_it);
    875         } else {
    876           ++req_it;
    877         }
    878       }
    879     }
    880   }
    881 
    882  private:
    883   typedef std::deque<Request*> PendingRequestsQueue;
    884 
    885   // Maximum number of concurrent jobs allowed to be started for requests
    886   // belonging to this pool.
    887   size_t max_outstanding_jobs_;
    888 
    889   // The current number of running jobs that were started for requests
    890   // belonging to this pool.
    891   size_t num_outstanding_jobs_;
    892 
    893   // The maximum number of requests we allow to be waiting on a job,
    894   // for this pool.
    895   size_t max_pending_requests_;
    896 
    897   // The requests which are waiting to be started for this pool.
    898   PendingRequestsQueue pending_requests_[NUM_PRIORITIES];
    899 };
    900 
    901 //-----------------------------------------------------------------------------
    902 
    903 HostResolverImpl::HostResolverImpl(
    904     HostResolverProc* resolver_proc,
    905     HostCache* cache,
    906     size_t max_jobs,
    907     NetLog* net_log)
    908     : cache_(cache),
    909       max_jobs_(max_jobs),
    910       next_request_id_(0),
    911       next_job_id_(0),
    912       resolver_proc_(resolver_proc),
    913       default_address_family_(ADDRESS_FAMILY_UNSPECIFIED),
    914       shutdown_(false),
    915       ipv6_probe_monitoring_(false),
    916       additional_resolver_flags_(0),
    917       net_log_(net_log) {
    918   DCHECK_GT(max_jobs, 0u);
    919 
    920   // It is cumbersome to expose all of the constraints in the constructor,
    921   // so we choose some defaults, which users can override later.
    922   job_pools_[POOL_NORMAL] = new JobPool(max_jobs, 100u * max_jobs);
    923 
    924 #if defined(OS_WIN)
    925   EnsureWinsockInit();
    926 #endif
    927 #if defined(OS_LINUX)
    928   if (HaveOnlyLoopbackAddresses())
    929     additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY;
    930 #endif
    931   NetworkChangeNotifier::AddIPAddressObserver(this);
    932 }
    933 
    934 HostResolverImpl::~HostResolverImpl() {
    935   // Cancel the outstanding jobs. Those jobs may contain several attached
    936   // requests, which will also be cancelled.
    937   DiscardIPv6ProbeJob();
    938 
    939   CancelAllJobs();
    940 
    941   // In case we are being deleted during the processing of a callback.
    942   if (cur_completing_job_)
    943     cur_completing_job_->Cancel();
    944 
    945   NetworkChangeNotifier::RemoveIPAddressObserver(this);
    946 
    947   // Delete the job pools.
    948   for (size_t i = 0u; i < arraysize(job_pools_); ++i)
    949     delete job_pools_[i];
    950 }
    951 
    952 void HostResolverImpl::ProbeIPv6Support() {
    953   DCHECK(CalledOnValidThread());
    954   DCHECK(!ipv6_probe_monitoring_);
    955   ipv6_probe_monitoring_ = true;
    956   OnIPAddressChanged();  // Give initial setup call.
    957 }
    958 
    959 void HostResolverImpl::SetPoolConstraints(JobPoolIndex pool_index,
    960                                           size_t max_outstanding_jobs,
    961                                           size_t max_pending_requests) {
    962   DCHECK(CalledOnValidThread());
    963   CHECK_GE(pool_index, 0);
    964   CHECK_LT(pool_index, POOL_COUNT);
    965   CHECK(jobs_.empty()) << "Can only set constraints during setup";
    966   JobPool* pool = job_pools_[pool_index];
    967   pool->SetConstraints(max_outstanding_jobs, max_pending_requests);
    968 }
    969 
    970 int HostResolverImpl::Resolve(const RequestInfo& info,
    971                               AddressList* addresses,
    972                               CompletionCallback* callback,
    973                               RequestHandle* out_req,
    974                               const BoundNetLog& source_net_log) {
    975   DCHECK(CalledOnValidThread());
    976 
    977   if (shutdown_)
    978     return ERR_UNEXPECTED;
    979 
    980   // Choose a unique ID number for observers to see.
    981   int request_id = next_request_id_++;
    982 
    983   // Make a log item for the request.
    984   BoundNetLog request_net_log = BoundNetLog::Make(net_log_,
    985       NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST);
    986 
    987   // Update the net log and notify registered observers.
    988   OnStartRequest(source_net_log, request_net_log, request_id, info);
    989 
    990   // Build a key that identifies the request in the cache and in the
    991   // outstanding jobs map.
    992   Key key = GetEffectiveKeyForRequest(info);
    993 
    994   // Check for IP literal.
    995   IPAddressNumber ip_number;
    996   if (ParseIPLiteralToNumber(info.hostname(), &ip_number)) {
    997     DCHECK_EQ(key.host_resolver_flags &
    998                   ~(HOST_RESOLVER_CANONNAME | HOST_RESOLVER_LOOPBACK_ONLY |
    999                     HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6),
   1000               0) << " Unhandled flag";
   1001     bool ipv6_disabled = default_address_family_ == ADDRESS_FAMILY_IPV4 &&
   1002         !ipv6_probe_monitoring_;
   1003     int net_error = OK;
   1004     if (ip_number.size() == 16 && ipv6_disabled) {
   1005       net_error = ERR_NAME_NOT_RESOLVED;
   1006     } else {
   1007       AddressList result(ip_number, info.port(),
   1008                          (key.host_resolver_flags & HOST_RESOLVER_CANONNAME));
   1009       *addresses = result;
   1010     }
   1011     // Update the net log and notify registered observers.
   1012     OnFinishRequest(source_net_log, request_net_log, request_id, info,
   1013                     net_error, 0  /* os_error (unknown since from cache) */);
   1014     return net_error;
   1015   }
   1016 
   1017   // If we have an unexpired cache entry, use it.
   1018   if (info.allow_cached_response() && cache_.get()) {
   1019     const HostCache::Entry* cache_entry = cache_->Lookup(
   1020         key, base::TimeTicks::Now());
   1021     if (cache_entry) {
   1022       request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL);
   1023       int net_error = cache_entry->error;
   1024       if (net_error == OK)
   1025         addresses->SetFrom(cache_entry->addrlist, info.port());
   1026 
   1027       // Update the net log and notify registered observers.
   1028       OnFinishRequest(source_net_log, request_net_log, request_id, info,
   1029                       net_error,
   1030                       0  /* os_error (unknown since from cache) */);
   1031 
   1032       return net_error;
   1033     }
   1034   }
   1035 
   1036   if (info.only_use_cached_response()) {  // Not allowed to do a real lookup.
   1037     OnFinishRequest(source_net_log,
   1038                     request_net_log,
   1039                     request_id,
   1040                     info,
   1041                     ERR_NAME_NOT_RESOLVED,
   1042                     0);
   1043     return ERR_NAME_NOT_RESOLVED;
   1044   }
   1045 
   1046   // If no callback was specified, do a synchronous resolution.
   1047   if (!callback) {
   1048     AddressList addrlist;
   1049     int os_error = 0;
   1050     int error = ResolveAddrInfo(
   1051         effective_resolver_proc(), key.hostname, key.address_family,
   1052         key.host_resolver_flags, &addrlist, &os_error);
   1053     if (error == OK) {
   1054       addrlist.SetPort(info.port());
   1055       *addresses = addrlist;
   1056     }
   1057 
   1058     // Write to cache.
   1059     if (cache_.get())
   1060       cache_->Set(key, error, addrlist, base::TimeTicks::Now());
   1061 
   1062     // Update the net log and notify registered observers.
   1063     OnFinishRequest(source_net_log, request_net_log, request_id, info, error,
   1064                     os_error);
   1065 
   1066     return error;
   1067   }
   1068 
   1069   // Create a handle for this request, and pass it back to the user if they
   1070   // asked for it (out_req != NULL).
   1071   Request* req = new Request(source_net_log, request_net_log, request_id, info,
   1072                              callback, addresses);
   1073   if (out_req)
   1074     *out_req = reinterpret_cast<RequestHandle>(req);
   1075 
   1076   // Next we need to attach our request to a "job". This job is responsible for
   1077   // calling "getaddrinfo(hostname)" on a worker thread.
   1078   scoped_refptr<Job> job;
   1079 
   1080   // If there is already an outstanding job to resolve |key|, use
   1081   // it. This prevents starting concurrent resolves for the same hostname.
   1082   job = FindOutstandingJob(key);
   1083   if (job) {
   1084     job->AddRequest(req);
   1085   } else {
   1086     JobPool* pool = GetPoolForRequest(req);
   1087     if (CanCreateJobForPool(*pool)) {
   1088       CreateAndStartJob(req);
   1089     } else {
   1090       return EnqueueRequest(pool, req);
   1091     }
   1092   }
   1093 
   1094   // Completion happens during OnJobComplete(Job*).
   1095   return ERR_IO_PENDING;
   1096 }
   1097 
   1098 // See OnJobComplete(Job*) for why it is important not to clean out
   1099 // cancelled requests from Job::requests_.
   1100 void HostResolverImpl::CancelRequest(RequestHandle req_handle) {
   1101   DCHECK(CalledOnValidThread());
   1102   if (shutdown_) {
   1103     // TODO(eroman): temp hack for: http://crbug.com/18373
   1104     // Because we destroy outstanding requests during Shutdown(),
   1105     // |req_handle| is already cancelled.
   1106     LOG(ERROR) << "Called HostResolverImpl::CancelRequest() after Shutdown().";
   1107     base::debug::StackTrace().PrintBacktrace();
   1108     return;
   1109   }
   1110   Request* req = reinterpret_cast<Request*>(req_handle);
   1111   DCHECK(req);
   1112 
   1113   scoped_ptr<Request> request_deleter;  // Frees at end of function.
   1114 
   1115   if (!req->job()) {
   1116     // If the request was not attached to a job yet, it must have been
   1117     // enqueued into a pool. Remove it from that pool's queue.
   1118     // Otherwise if it was attached to a job, the job is responsible for
   1119     // deleting it.
   1120     JobPool* pool = GetPoolForRequest(req);
   1121     pool->RemovePendingRequest(req);
   1122     request_deleter.reset(req);
   1123   } else {
   1124     req->request_net_log().EndEvent(
   1125         NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, NULL);
   1126   }
   1127 
   1128   // NULL out the fields of req, to mark it as cancelled.
   1129   req->MarkAsCancelled();
   1130   OnCancelRequest(req->source_net_log(), req->request_net_log(), req->id(),
   1131                   req->info());
   1132 }
   1133 
   1134 void HostResolverImpl::AddObserver(HostResolver::Observer* observer) {
   1135   DCHECK(CalledOnValidThread());
   1136   observers_.push_back(observer);
   1137 }
   1138 
   1139 void HostResolverImpl::RemoveObserver(HostResolver::Observer* observer) {
   1140   DCHECK(CalledOnValidThread());
   1141   ObserversList::iterator it =
   1142       std::find(observers_.begin(), observers_.end(), observer);
   1143 
   1144   // Observer must exist.
   1145   DCHECK(it != observers_.end());
   1146 
   1147   observers_.erase(it);
   1148 }
   1149 
   1150 void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) {
   1151   DCHECK(CalledOnValidThread());
   1152   ipv6_probe_monitoring_ = false;
   1153   DiscardIPv6ProbeJob();
   1154   default_address_family_ = address_family;
   1155 }
   1156 
   1157 AddressFamily HostResolverImpl::GetDefaultAddressFamily() const {
   1158   return default_address_family_;
   1159 }
   1160 
   1161 HostResolverImpl* HostResolverImpl::GetAsHostResolverImpl() {
   1162   return this;
   1163 }
   1164 
   1165 void HostResolverImpl::Shutdown() {
   1166   DCHECK(CalledOnValidThread());
   1167 
   1168   // Cancel the outstanding jobs.
   1169   CancelAllJobs();
   1170   DiscardIPv6ProbeJob();
   1171 
   1172   shutdown_ = true;
   1173 }
   1174 
   1175 void HostResolverImpl::AddOutstandingJob(Job* job) {
   1176   scoped_refptr<Job>& found_job = jobs_[job->key()];
   1177   DCHECK(!found_job);
   1178   found_job = job;
   1179 
   1180   JobPool* pool = GetPoolForRequest(job->initial_request());
   1181   pool->AdjustNumOutstandingJobs(1);
   1182 }
   1183 
   1184 HostResolverImpl::Job* HostResolverImpl::FindOutstandingJob(const Key& key) {
   1185   JobMap::iterator it = jobs_.find(key);
   1186   if (it != jobs_.end())
   1187     return it->second;
   1188   return NULL;
   1189 }
   1190 
   1191 void HostResolverImpl::RemoveOutstandingJob(Job* job) {
   1192   JobMap::iterator it = jobs_.find(job->key());
   1193   DCHECK(it != jobs_.end());
   1194   DCHECK_EQ(it->second.get(), job);
   1195   jobs_.erase(it);
   1196 
   1197   JobPool* pool = GetPoolForRequest(job->initial_request());
   1198   pool->AdjustNumOutstandingJobs(-1);
   1199 }
   1200 
   1201 void HostResolverImpl::OnJobComplete(Job* job,
   1202                                      int net_error,
   1203                                      int os_error,
   1204                                      const AddressList& addrlist) {
   1205   RemoveOutstandingJob(job);
   1206 
   1207   // Write result to the cache.
   1208   if (cache_.get())
   1209     cache_->Set(job->key(), net_error, addrlist, base::TimeTicks::Now());
   1210 
   1211   OnJobCompleteInternal(job, net_error, os_error, addrlist);
   1212 }
   1213 
   1214 void HostResolverImpl::AbortJob(Job* job) {
   1215   OnJobCompleteInternal(job, ERR_ABORTED, 0 /* no os_error */, AddressList());
   1216 }
   1217 
   1218 void HostResolverImpl::OnJobCompleteInternal(
   1219     Job* job,
   1220     int net_error,
   1221     int os_error,
   1222     const AddressList& addrlist) {
   1223   // Make a note that we are executing within OnJobComplete() in case the
   1224   // HostResolver is deleted by a callback invocation.
   1225   DCHECK(!cur_completing_job_);
   1226   cur_completing_job_ = job;
   1227 
   1228   // Try to start any queued requests now that a job-slot has freed up.
   1229   ProcessQueuedRequests();
   1230 
   1231   // Complete all of the requests that were attached to the job.
   1232   for (RequestsList::const_iterator it = job->requests().begin();
   1233        it != job->requests().end(); ++it) {
   1234     Request* req = *it;
   1235     if (!req->was_cancelled()) {
   1236       DCHECK_EQ(job, req->job());
   1237       req->request_net_log().EndEvent(
   1238           NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, NULL);
   1239 
   1240       // Update the net log and notify registered observers.
   1241       OnFinishRequest(req->source_net_log(), req->request_net_log(), req->id(),
   1242                       req->info(), net_error, os_error);
   1243 
   1244       req->OnComplete(net_error, addrlist);
   1245 
   1246       // Check if the job was cancelled as a result of running the callback.
   1247       // (Meaning that |this| was deleted).
   1248       if (job->was_cancelled())
   1249         return;
   1250     }
   1251   }
   1252 
   1253   cur_completing_job_ = NULL;
   1254 }
   1255 
   1256 void HostResolverImpl::OnStartRequest(const BoundNetLog& source_net_log,
   1257                                       const BoundNetLog& request_net_log,
   1258                                       int request_id,
   1259                                       const RequestInfo& info) {
   1260   source_net_log.BeginEvent(
   1261       NetLog::TYPE_HOST_RESOLVER_IMPL,
   1262       make_scoped_refptr(new NetLogSourceParameter(
   1263           "source_dependency", request_net_log.source())));
   1264 
   1265   request_net_log.BeginEvent(
   1266       NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST,
   1267       make_scoped_refptr(new RequestInfoParameters(
   1268           info, source_net_log.source())));
   1269 
   1270   // Notify the observers of the start.
   1271   if (!observers_.empty()) {
   1272     for (ObserversList::iterator it = observers_.begin();
   1273          it != observers_.end(); ++it) {
   1274       (*it)->OnStartResolution(request_id, info);
   1275     }
   1276   }
   1277 }
   1278 
   1279 void HostResolverImpl::OnFinishRequest(const BoundNetLog& source_net_log,
   1280                                        const BoundNetLog& request_net_log,
   1281                                        int request_id,
   1282                                        const RequestInfo& info,
   1283                                        int net_error,
   1284                                        int os_error) {
   1285   bool was_resolved = net_error == OK;
   1286 
   1287   // Notify the observers of the completion.
   1288   if (!observers_.empty()) {
   1289     for (ObserversList::iterator it = observers_.begin();
   1290          it != observers_.end(); ++it) {
   1291       (*it)->OnFinishResolutionWithStatus(request_id, was_resolved, info);
   1292     }
   1293   }
   1294 
   1295   // Log some extra parameters on failure for synchronous requests.
   1296   scoped_refptr<NetLog::EventParameters> params;
   1297   if (!was_resolved) {
   1298     params = new HostResolveFailedParams(net_error, os_error);
   1299   }
   1300 
   1301   request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, params);
   1302   source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL);
   1303 }
   1304 
   1305 void HostResolverImpl::OnCancelRequest(const BoundNetLog& source_net_log,
   1306                                        const BoundNetLog& request_net_log,
   1307                                        int request_id,
   1308                                        const RequestInfo& info) {
   1309   request_net_log.AddEvent(NetLog::TYPE_CANCELLED, NULL);
   1310 
   1311   // Notify the observers of the cancellation.
   1312   if (!observers_.empty()) {
   1313     for (ObserversList::iterator it = observers_.begin();
   1314          it != observers_.end(); ++it) {
   1315       (*it)->OnCancelResolution(request_id, info);
   1316     }
   1317   }
   1318 
   1319   request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, NULL);
   1320   source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL);
   1321 }
   1322 
   1323 void HostResolverImpl::DiscardIPv6ProbeJob() {
   1324   if (ipv6_probe_job_.get()) {
   1325     ipv6_probe_job_->Cancel();
   1326     ipv6_probe_job_ = NULL;
   1327   }
   1328 }
   1329 
   1330 void HostResolverImpl::IPv6ProbeSetDefaultAddressFamily(
   1331     AddressFamily address_family) {
   1332   DCHECK(address_family == ADDRESS_FAMILY_UNSPECIFIED ||
   1333          address_family == ADDRESS_FAMILY_IPV4);
   1334   if (default_address_family_ != address_family) {
   1335     VLOG(1) << "IPv6Probe forced AddressFamily setting to "
   1336             << ((address_family == ADDRESS_FAMILY_UNSPECIFIED) ?
   1337                 "ADDRESS_FAMILY_UNSPECIFIED" : "ADDRESS_FAMILY_IPV4");
   1338   }
   1339   default_address_family_ = address_family;
   1340   // Drop reference since the job has called us back.
   1341   DiscardIPv6ProbeJob();
   1342 }
   1343 
   1344 bool HostResolverImpl::CanCreateJobForPool(const JobPool& pool) const {
   1345   DCHECK_LE(jobs_.size(), max_jobs_);
   1346 
   1347   // We can't create another job if it would exceed the global total.
   1348   if (jobs_.size() + 1 > max_jobs_)
   1349     return false;
   1350 
   1351   // Check whether the pool's constraints are met.
   1352   return pool.CanCreateJob();
   1353 }
   1354 
   1355 // static
   1356 HostResolverImpl::JobPoolIndex HostResolverImpl::GetJobPoolIndexForRequest(
   1357     const Request* req) {
   1358   return POOL_NORMAL;
   1359 }
   1360 
   1361 void HostResolverImpl::ProcessQueuedRequests() {
   1362   // Find the highest priority request that can be scheduled.
   1363   Request* top_req = NULL;
   1364   for (size_t i = 0; i < arraysize(job_pools_); ++i) {
   1365     JobPool* pool = job_pools_[i];
   1366     if (pool->HasPendingRequests() && CanCreateJobForPool(*pool)) {
   1367       top_req = pool->RemoveTopPendingRequest();
   1368       break;
   1369     }
   1370   }
   1371 
   1372   if (!top_req)
   1373     return;
   1374 
   1375   scoped_refptr<Job> job(CreateAndStartJob(top_req));
   1376 
   1377   // Search for any other pending request which can piggy-back off this job.
   1378   for (size_t pool_i = 0; pool_i < POOL_COUNT; ++pool_i) {
   1379     JobPool* pool = job_pools_[pool_i];
   1380     pool->MoveRequestsToJob(job);
   1381   }
   1382 }
   1383 
   1384 HostResolverImpl::Key HostResolverImpl::GetEffectiveKeyForRequest(
   1385     const RequestInfo& info) const {
   1386   HostResolverFlags effective_flags =
   1387       info.host_resolver_flags() | additional_resolver_flags_;
   1388   AddressFamily effective_address_family = info.address_family();
   1389   if (effective_address_family == ADDRESS_FAMILY_UNSPECIFIED &&
   1390       default_address_family_ != ADDRESS_FAMILY_UNSPECIFIED) {
   1391     effective_address_family = default_address_family_;
   1392     if (ipv6_probe_monitoring_)
   1393       effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
   1394   }
   1395   return Key(info.hostname(), effective_address_family, effective_flags);
   1396 }
   1397 
   1398 HostResolverImpl::Job* HostResolverImpl::CreateAndStartJob(Request* req) {
   1399   DCHECK(CanCreateJobForPool(*GetPoolForRequest(req)));
   1400   Key key = GetEffectiveKeyForRequest(req->info());
   1401 
   1402   req->request_net_log().AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB,
   1403                                   NULL);
   1404 
   1405   scoped_refptr<Job> job(new Job(next_job_id_++, this, key,
   1406                                    req->request_net_log(), net_log_));
   1407   job->AddRequest(req);
   1408   AddOutstandingJob(job);
   1409   job->Start();
   1410 
   1411   return job.get();
   1412 }
   1413 
   1414 int HostResolverImpl::EnqueueRequest(JobPool* pool, Request* req) {
   1415   scoped_ptr<Request> req_evicted_from_queue(
   1416       pool->InsertPendingRequest(req));
   1417 
   1418   // If the queue has become too large, we need to kick something out.
   1419   if (req_evicted_from_queue.get()) {
   1420     Request* r = req_evicted_from_queue.get();
   1421     int error = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE;
   1422 
   1423     OnFinishRequest(r->source_net_log(), r->request_net_log(), r->id(),
   1424                     r->info(), error,
   1425                     0  /* os_error (not applicable) */);
   1426 
   1427     if (r == req)
   1428       return error;
   1429 
   1430     r->OnComplete(error, AddressList());
   1431   }
   1432 
   1433   return ERR_IO_PENDING;
   1434 }
   1435 
   1436 void HostResolverImpl::CancelAllJobs() {
   1437   JobMap jobs;
   1438   jobs.swap(jobs_);
   1439   for (JobMap::iterator it = jobs.begin(); it != jobs.end(); ++it)
   1440     it->second->Cancel();
   1441 }
   1442 
   1443 void HostResolverImpl::AbortAllInProgressJobs() {
   1444   for (size_t i = 0; i < arraysize(job_pools_); ++i)
   1445     job_pools_[i]->ResetNumOutstandingJobs();
   1446   JobMap jobs;
   1447   jobs.swap(jobs_);
   1448   for (JobMap::iterator it = jobs.begin(); it != jobs.end(); ++it) {
   1449     AbortJob(it->second);
   1450     it->second->Cancel();
   1451   }
   1452 }
   1453 
   1454 void HostResolverImpl::OnIPAddressChanged() {
   1455   if (cache_.get())
   1456     cache_->clear();
   1457   if (ipv6_probe_monitoring_) {
   1458     DCHECK(!shutdown_);
   1459     if (shutdown_)
   1460       return;
   1461     DiscardIPv6ProbeJob();
   1462     ipv6_probe_job_ = new IPv6ProbeJob(this);
   1463     ipv6_probe_job_->Start();
   1464   }
   1465 #if defined(OS_LINUX)
   1466   if (HaveOnlyLoopbackAddresses()) {
   1467     additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY;
   1468   } else {
   1469     additional_resolver_flags_ &= ~HOST_RESOLVER_LOOPBACK_ONLY;
   1470   }
   1471 #endif
   1472   AbortAllInProgressJobs();
   1473   // |this| may be deleted inside AbortAllInProgressJobs().
   1474 }
   1475 
   1476 }  // namespace net
   1477