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