1// Copyright (c) 2011 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#ifndef NET_BASE_HOST_RESOLVER_IMPL_H_
6#define NET_BASE_HOST_RESOLVER_IMPL_H_
7#pragma once
8
9#include <vector>
10
11#include "base/memory/scoped_ptr.h"
12#include "base/threading/non_thread_safe.h"
13#include "net/base/capturing_net_log.h"
14#include "net/base/host_cache.h"
15#include "net/base/host_resolver.h"
16#include "net/base/host_resolver_proc.h"
17#include "net/base/net_log.h"
18#include "net/base/network_change_notifier.h"
19
20namespace net {
21
22// For each hostname that is requested, HostResolver creates a
23// HostResolverImpl::Job. This job gets dispatched to a thread in the global
24// WorkerPool, where it runs SystemHostResolverProc(). If requests for that same
25// host are made while the job is already outstanding, then they are attached
26// to the existing job rather than creating a new one. This avoids doing
27// parallel resolves for the same host.
28//
29// The way these classes fit together is illustrated by:
30//
31//
32//            +----------- HostResolverImpl -------------+
33//            |                    |                     |
34//           Job                  Job                   Job
35//    (for host1, fam1)    (for host2, fam2)     (for hostx, famx)
36//       /    |   |            /   |   |             /   |   |
37//   Request ... Request  Request ... Request   Request ... Request
38//  (port1)     (port2)  (port3)      (port4)  (port5)      (portX)
39//
40//
41// When a HostResolverImpl::Job finishes its work in the threadpool, the
42// callbacks of each waiting request are run on the origin thread.
43//
44// Thread safety: This class is not threadsafe, and must only be called
45// from one thread!
46//
47// The HostResolverImpl enforces |max_jobs_| as the maximum number of concurrent
48// threads.
49//
50// Requests are ordered in the queue based on their priority.
51
52class HostResolverImpl : public HostResolver,
53                         public base::NonThreadSafe,
54                         public NetworkChangeNotifier::IPAddressObserver {
55 public:
56  // The index into |job_pools_| for the various job pools. Pools with a higher
57  // index have lower priority.
58  //
59  // Note: This is currently unused, since there is a single pool
60  //       for all requests.
61  enum JobPoolIndex {
62    POOL_NORMAL = 0,
63    POOL_COUNT,
64  };
65
66  // Creates a HostResolver that first uses the local cache |cache|, and then
67  // falls back to |resolver_proc|.
68  //
69  // If |cache| is NULL, then no caching is used. Otherwise we take
70  // ownership of the |cache| pointer, and will free it during destructor.
71  //
72  // |resolver_proc| is used to perform the actual resolves; it must be
73  // thread-safe since it is run from multiple worker threads. If
74  // |resolver_proc| is NULL then the default host resolver procedure is
75  // used (which is SystemHostResolverProc except if overridden).
76  // |max_jobs| specifies the maximum number of threads that the host resolver
77  // will use. Use SetPoolConstraints() to specify finer-grain settings.
78  //
79  // |net_log| must remain valid for the life of the HostResolverImpl.
80  HostResolverImpl(HostResolverProc* resolver_proc,
81                   HostCache* cache,
82                   size_t max_jobs,
83                   NetLog* net_log);
84
85  // If any completion callbacks are pending when the resolver is destroyed,
86  // the host resolutions are cancelled, and the completion callbacks will not
87  // be called.
88  virtual ~HostResolverImpl();
89
90  // Continuously observe whether IPv6 is supported, and set the allowable
91  // address family to IPv4 iff IPv6 is not supported.
92  void ProbeIPv6Support();
93
94  // Returns the cache this resolver uses, or NULL if caching is disabled.
95  HostCache* cache() { return cache_.get(); }
96
97  // Applies a set of constraints for requests that belong to the specified
98  // pool. NOTE: Don't call this after requests have been already been started.
99  //
100  //  |pool_index| -- Specifies which pool these constraints should be applied
101  //                  to.
102  //  |max_outstanding_jobs| -- How many concurrent jobs are allowed for this
103  //                            pool.
104  //  |max_pending_requests| -- How many requests can be enqueued for this pool
105  //                            before we start dropping requests. Dropped
106  //                            requests fail with
107  //                            ERR_HOST_RESOLVER_QUEUE_TOO_LARGE.
108  void SetPoolConstraints(JobPoolIndex pool_index,
109                          size_t max_outstanding_jobs,
110                          size_t max_pending_requests);
111
112  // HostResolver methods:
113  virtual int Resolve(const RequestInfo& info,
114                      AddressList* addresses,
115                      CompletionCallback* callback,
116                      RequestHandle* out_req,
117                      const BoundNetLog& source_net_log);
118  virtual void CancelRequest(RequestHandle req);
119  virtual void AddObserver(HostResolver::Observer* observer);
120  virtual void RemoveObserver(HostResolver::Observer* observer);
121
122  // Set address family, and disable IPv6 probe support.
123  virtual void SetDefaultAddressFamily(AddressFamily address_family);
124  virtual AddressFamily GetDefaultAddressFamily() const;
125
126  virtual HostResolverImpl* GetAsHostResolverImpl();
127
128  // TODO(eroman): hack for http://crbug.com/15513
129  virtual void Shutdown();
130
131 private:
132  class Job;
133  class JobPool;
134  class IPv6ProbeJob;
135  class Request;
136  typedef std::vector<Request*> RequestsList;
137  typedef HostCache::Key Key;
138  typedef std::map<Key, scoped_refptr<Job> > JobMap;
139  typedef std::vector<HostResolver::Observer*> ObserversList;
140
141  // Returns the HostResolverProc to use for this instance.
142  HostResolverProc* effective_resolver_proc() const {
143    return resolver_proc_ ?
144        resolver_proc_.get() : HostResolverProc::GetDefault();
145  }
146
147  // Adds a job to outstanding jobs list.
148  void AddOutstandingJob(Job* job);
149
150  // Returns the outstanding job for |key|, or NULL if there is none.
151  Job* FindOutstandingJob(const Key& key);
152
153  // Removes |job| from the outstanding jobs list.
154  void RemoveOutstandingJob(Job* job);
155
156  // Callback for when |job| has completed with |net_error| and |addrlist|.
157  void OnJobComplete(Job* job, int net_error, int os_error,
158                     const AddressList& addrlist);
159
160  // Aborts |job|.  Same as OnJobComplete() except does not remove |job|
161  // from |jobs_| and does not cache the result (ERR_ABORTED).
162  void AbortJob(Job* job);
163
164  // Used by both OnJobComplete() and AbortJob();
165  void OnJobCompleteInternal(Job* job, int net_error, int os_error,
166                             const AddressList& addrlist);
167
168  // Called when a request has just been started.
169  void OnStartRequest(const BoundNetLog& source_net_log,
170                      const BoundNetLog& request_net_log,
171                      int request_id,
172                      const RequestInfo& info);
173
174  // Called when a request has just completed (before its callback is run).
175  void OnFinishRequest(const BoundNetLog& source_net_log,
176                       const BoundNetLog& request_net_log,
177                       int request_id,
178                       const RequestInfo& info,
179                       int net_error,
180                       int os_error);
181
182  // Called when a request has been cancelled.
183  void OnCancelRequest(const BoundNetLog& source_net_log,
184                       const BoundNetLog& request_net_log,
185                       int request_id,
186                       const RequestInfo& info);
187
188  // Notify IPv6ProbeJob not to call back, and discard reference to the job.
189  void DiscardIPv6ProbeJob();
190
191  // Callback from IPv6 probe activity.
192  void IPv6ProbeSetDefaultAddressFamily(AddressFamily address_family);
193
194  // Returns true if the constraints for |pool| are met, and a new job can be
195  // created for this pool.
196  bool CanCreateJobForPool(const JobPool& pool) const;
197
198  // Returns the index of the pool that request |req| maps to.
199  static JobPoolIndex GetJobPoolIndexForRequest(const Request* req);
200
201  JobPool* GetPoolForRequest(const Request* req) {
202    return job_pools_[GetJobPoolIndexForRequest(req)];
203  }
204
205  // Starts up to 1 job given the current pool constraints. This job
206  // may have multiple requests attached to it.
207  void ProcessQueuedRequests();
208
209  // Returns the (hostname, address_family) key to use for |info|, choosing an
210  // "effective" address family by inheriting the resolver's default address
211  // family when the request leaves it unspecified.
212  Key GetEffectiveKeyForRequest(const RequestInfo& info) const;
213
214  // Attaches |req| to a new job, and starts it. Returns that job.
215  Job* CreateAndStartJob(Request* req);
216
217  // Adds a pending request |req| to |pool|.
218  int EnqueueRequest(JobPool* pool, Request* req);
219
220  // Cancels all jobs.
221  void CancelAllJobs();
222
223  // Aborts all in progress jobs (but might start new ones).
224  void AbortAllInProgressJobs();
225
226  // NetworkChangeNotifier::IPAddressObserver methods:
227  virtual void OnIPAddressChanged();
228
229  // Cache of host resolution results.
230  scoped_ptr<HostCache> cache_;
231
232  // Map from hostname to outstanding job.
233  JobMap jobs_;
234
235  // Maximum number of concurrent jobs allowed, across all pools.
236  size_t max_jobs_;
237
238  // The information to track pending requests for a JobPool, as well as
239  // how many outstanding jobs the pool already has, and its constraints.
240  JobPool* job_pools_[POOL_COUNT];
241
242  // The job that OnJobComplete() is currently processing (needed in case
243  // HostResolver gets deleted from within the callback).
244  scoped_refptr<Job> cur_completing_job_;
245
246  // The observers to notify when a request starts/ends.
247  ObserversList observers_;
248
249  // Monotonically increasing ID number to assign to the next request.
250  // Observers are the only consumers of this ID number.
251  int next_request_id_;
252
253  // Monotonically increasing ID number to assign to the next job.
254  // The only consumer of this ID is the requests tracing code.
255  int next_job_id_;
256
257  // The procedure to use for resolving host names. This will be NULL, except
258  // in the case of unit-tests which inject custom host resolving behaviors.
259  scoped_refptr<HostResolverProc> resolver_proc_;
260
261  // Address family to use when the request doesn't specify one.
262  AddressFamily default_address_family_;
263
264  // TODO(eroman): hack for http://crbug.com/15513
265  bool shutdown_;
266
267  // Indicate if probing is done after each network change event to set address
268  // family.
269  // When false, explicit setting of address family is used.
270  bool ipv6_probe_monitoring_;
271
272  // The last un-cancelled IPv6ProbeJob (if any).
273  scoped_refptr<IPv6ProbeJob> ipv6_probe_job_;
274
275  // Any resolver flags that should be added to a request by default.
276  HostResolverFlags additional_resolver_flags_;
277
278  NetLog* net_log_;
279
280  DISALLOW_COPY_AND_ASSIGN(HostResolverImpl);
281};
282
283}  // namespace net
284
285#endif  // NET_BASE_HOST_RESOLVER_IMPL_H_
286