• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 namespace 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 
52 class 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.
cache()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.
effective_resolver_proc()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 
GetPoolForRequest(const Request * req)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