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
43namespace net {
44
45namespace {
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).
50const 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
61HostCache* 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
74HostResolver* 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
93static 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.
111class 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.
152class 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.
181class 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.
201std::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
249class 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.
346class 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.
644class 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.
740COMPILE_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.
749class 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
903HostResolverImpl::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
934HostResolverImpl::~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
952void HostResolverImpl::ProbeIPv6Support() {
953  DCHECK(CalledOnValidThread());
954  DCHECK(!ipv6_probe_monitoring_);
955  ipv6_probe_monitoring_ = true;
956  OnIPAddressChanged();  // Give initial setup call.
957}
958
959void 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
970int 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_.
1100void 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
1134void HostResolverImpl::AddObserver(HostResolver::Observer* observer) {
1135  DCHECK(CalledOnValidThread());
1136  observers_.push_back(observer);
1137}
1138
1139void 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
1150void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) {
1151  DCHECK(CalledOnValidThread());
1152  ipv6_probe_monitoring_ = false;
1153  DiscardIPv6ProbeJob();
1154  default_address_family_ = address_family;
1155}
1156
1157AddressFamily HostResolverImpl::GetDefaultAddressFamily() const {
1158  return default_address_family_;
1159}
1160
1161HostResolverImpl* HostResolverImpl::GetAsHostResolverImpl() {
1162  return this;
1163}
1164
1165void HostResolverImpl::Shutdown() {
1166  DCHECK(CalledOnValidThread());
1167
1168  // Cancel the outstanding jobs.
1169  CancelAllJobs();
1170  DiscardIPv6ProbeJob();
1171
1172  shutdown_ = true;
1173}
1174
1175void 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
1184HostResolverImpl::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
1191void 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
1201void 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
1214void HostResolverImpl::AbortJob(Job* job) {
1215  OnJobCompleteInternal(job, ERR_ABORTED, 0 /* no os_error */, AddressList());
1216}
1217
1218void 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
1256void 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
1279void 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
1305void 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
1323void HostResolverImpl::DiscardIPv6ProbeJob() {
1324  if (ipv6_probe_job_.get()) {
1325    ipv6_probe_job_->Cancel();
1326    ipv6_probe_job_ = NULL;
1327  }
1328}
1329
1330void 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
1344bool 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
1356HostResolverImpl::JobPoolIndex HostResolverImpl::GetJobPoolIndexForRequest(
1357    const Request* req) {
1358  return POOL_NORMAL;
1359}
1360
1361void 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
1384HostResolverImpl::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
1398HostResolverImpl::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
1414int 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
1436void 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
1443void 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
1454void 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