| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef NET_BASE_HOST_RESOLVER_IMPL_H_ |
| #define NET_BASE_HOST_RESOLVER_IMPL_H_ |
| #pragma once |
| |
| #include <vector> |
| |
| #include "base/memory/scoped_ptr.h" |
| #include "base/threading/non_thread_safe.h" |
| #include "net/base/capturing_net_log.h" |
| #include "net/base/host_cache.h" |
| #include "net/base/host_resolver.h" |
| #include "net/base/host_resolver_proc.h" |
| #include "net/base/net_log.h" |
| #include "net/base/network_change_notifier.h" |
| |
| namespace net { |
| |
| // For each hostname that is requested, HostResolver creates a |
| // HostResolverImpl::Job. This job gets dispatched to a thread in the global |
| // WorkerPool, where it runs SystemHostResolverProc(). If requests for that same |
| // host are made while the job is already outstanding, then they are attached |
| // to the existing job rather than creating a new one. This avoids doing |
| // parallel resolves for the same host. |
| // |
| // The way these classes fit together is illustrated by: |
| // |
| // |
| // +----------- HostResolverImpl -------------+ |
| // | | | |
| // Job Job Job |
| // (for host1, fam1) (for host2, fam2) (for hostx, famx) |
| // / | | / | | / | | |
| // Request ... Request Request ... Request Request ... Request |
| // (port1) (port2) (port3) (port4) (port5) (portX) |
| // |
| // |
| // When a HostResolverImpl::Job finishes its work in the threadpool, the |
| // callbacks of each waiting request are run on the origin thread. |
| // |
| // Thread safety: This class is not threadsafe, and must only be called |
| // from one thread! |
| // |
| // The HostResolverImpl enforces |max_jobs_| as the maximum number of concurrent |
| // threads. |
| // |
| // Requests are ordered in the queue based on their priority. |
| |
| class HostResolverImpl : public HostResolver, |
| public base::NonThreadSafe, |
| public NetworkChangeNotifier::IPAddressObserver { |
| public: |
| // The index into |job_pools_| for the various job pools. Pools with a higher |
| // index have lower priority. |
| // |
| // Note: This is currently unused, since there is a single pool |
| // for all requests. |
| enum JobPoolIndex { |
| POOL_NORMAL = 0, |
| POOL_COUNT, |
| }; |
| |
| // Creates a HostResolver that first uses the local cache |cache|, and then |
| // falls back to |resolver_proc|. |
| // |
| // If |cache| is NULL, then no caching is used. Otherwise we take |
| // ownership of the |cache| pointer, and will free it during destructor. |
| // |
| // |resolver_proc| is used to perform the actual resolves; it must be |
| // thread-safe since it is run from multiple worker threads. If |
| // |resolver_proc| is NULL then the default host resolver procedure is |
| // used (which is SystemHostResolverProc except if overridden). |
| // |max_jobs| specifies the maximum number of threads that the host resolver |
| // will use. Use SetPoolConstraints() to specify finer-grain settings. |
| // |
| // |net_log| must remain valid for the life of the HostResolverImpl. |
| HostResolverImpl(HostResolverProc* resolver_proc, |
| HostCache* cache, |
| size_t max_jobs, |
| NetLog* net_log); |
| |
| // If any completion callbacks are pending when the resolver is destroyed, |
| // the host resolutions are cancelled, and the completion callbacks will not |
| // be called. |
| virtual ~HostResolverImpl(); |
| |
| // Continuously observe whether IPv6 is supported, and set the allowable |
| // address family to IPv4 iff IPv6 is not supported. |
| void ProbeIPv6Support(); |
| |
| // Returns the cache this resolver uses, or NULL if caching is disabled. |
| HostCache* cache() { return cache_.get(); } |
| |
| // Applies a set of constraints for requests that belong to the specified |
| // pool. NOTE: Don't call this after requests have been already been started. |
| // |
| // |pool_index| -- Specifies which pool these constraints should be applied |
| // to. |
| // |max_outstanding_jobs| -- How many concurrent jobs are allowed for this |
| // pool. |
| // |max_pending_requests| -- How many requests can be enqueued for this pool |
| // before we start dropping requests. Dropped |
| // requests fail with |
| // ERR_HOST_RESOLVER_QUEUE_TOO_LARGE. |
| void SetPoolConstraints(JobPoolIndex pool_index, |
| size_t max_outstanding_jobs, |
| size_t max_pending_requests); |
| |
| // HostResolver methods: |
| virtual int Resolve(const RequestInfo& info, |
| AddressList* addresses, |
| CompletionCallback* callback, |
| RequestHandle* out_req, |
| const BoundNetLog& source_net_log); |
| virtual void CancelRequest(RequestHandle req); |
| virtual void AddObserver(HostResolver::Observer* observer); |
| virtual void RemoveObserver(HostResolver::Observer* observer); |
| |
| // Set address family, and disable IPv6 probe support. |
| virtual void SetDefaultAddressFamily(AddressFamily address_family); |
| virtual AddressFamily GetDefaultAddressFamily() const; |
| |
| virtual HostResolverImpl* GetAsHostResolverImpl(); |
| |
| // TODO(eroman): hack for http://crbug.com/15513 |
| virtual void Shutdown(); |
| |
| private: |
| class Job; |
| class JobPool; |
| class IPv6ProbeJob; |
| class Request; |
| typedef std::vector<Request*> RequestsList; |
| typedef HostCache::Key Key; |
| typedef std::map<Key, scoped_refptr<Job> > JobMap; |
| typedef std::vector<HostResolver::Observer*> ObserversList; |
| |
| // Returns the HostResolverProc to use for this instance. |
| HostResolverProc* effective_resolver_proc() const { |
| return resolver_proc_ ? |
| resolver_proc_.get() : HostResolverProc::GetDefault(); |
| } |
| |
| // Adds a job to outstanding jobs list. |
| void AddOutstandingJob(Job* job); |
| |
| // Returns the outstanding job for |key|, or NULL if there is none. |
| Job* FindOutstandingJob(const Key& key); |
| |
| // Removes |job| from the outstanding jobs list. |
| void RemoveOutstandingJob(Job* job); |
| |
| // Callback for when |job| has completed with |net_error| and |addrlist|. |
| void OnJobComplete(Job* job, int net_error, int os_error, |
| const AddressList& addrlist); |
| |
| // Aborts |job|. Same as OnJobComplete() except does not remove |job| |
| // from |jobs_| and does not cache the result (ERR_ABORTED). |
| void AbortJob(Job* job); |
| |
| // Used by both OnJobComplete() and AbortJob(); |
| void OnJobCompleteInternal(Job* job, int net_error, int os_error, |
| const AddressList& addrlist); |
| |
| // Called when a request has just been started. |
| void OnStartRequest(const BoundNetLog& source_net_log, |
| const BoundNetLog& request_net_log, |
| int request_id, |
| const RequestInfo& info); |
| |
| // Called when a request has just completed (before its callback is run). |
| void OnFinishRequest(const BoundNetLog& source_net_log, |
| const BoundNetLog& request_net_log, |
| int request_id, |
| const RequestInfo& info, |
| int net_error, |
| int os_error); |
| |
| // Called when a request has been cancelled. |
| void OnCancelRequest(const BoundNetLog& source_net_log, |
| const BoundNetLog& request_net_log, |
| int request_id, |
| const RequestInfo& info); |
| |
| // Notify IPv6ProbeJob not to call back, and discard reference to the job. |
| void DiscardIPv6ProbeJob(); |
| |
| // Callback from IPv6 probe activity. |
| void IPv6ProbeSetDefaultAddressFamily(AddressFamily address_family); |
| |
| // Returns true if the constraints for |pool| are met, and a new job can be |
| // created for this pool. |
| bool CanCreateJobForPool(const JobPool& pool) const; |
| |
| // Returns the index of the pool that request |req| maps to. |
| static JobPoolIndex GetJobPoolIndexForRequest(const Request* req); |
| |
| JobPool* GetPoolForRequest(const Request* req) { |
| return job_pools_[GetJobPoolIndexForRequest(req)]; |
| } |
| |
| // Starts up to 1 job given the current pool constraints. This job |
| // may have multiple requests attached to it. |
| void ProcessQueuedRequests(); |
| |
| // Returns the (hostname, address_family) key to use for |info|, choosing an |
| // "effective" address family by inheriting the resolver's default address |
| // family when the request leaves it unspecified. |
| Key GetEffectiveKeyForRequest(const RequestInfo& info) const; |
| |
| // Attaches |req| to a new job, and starts it. Returns that job. |
| Job* CreateAndStartJob(Request* req); |
| |
| // Adds a pending request |req| to |pool|. |
| int EnqueueRequest(JobPool* pool, Request* req); |
| |
| // Cancels all jobs. |
| void CancelAllJobs(); |
| |
| // Aborts all in progress jobs (but might start new ones). |
| void AbortAllInProgressJobs(); |
| |
| // NetworkChangeNotifier::IPAddressObserver methods: |
| virtual void OnIPAddressChanged(); |
| |
| // Cache of host resolution results. |
| scoped_ptr<HostCache> cache_; |
| |
| // Map from hostname to outstanding job. |
| JobMap jobs_; |
| |
| // Maximum number of concurrent jobs allowed, across all pools. |
| size_t max_jobs_; |
| |
| // The information to track pending requests for a JobPool, as well as |
| // how many outstanding jobs the pool already has, and its constraints. |
| JobPool* job_pools_[POOL_COUNT]; |
| |
| // The job that OnJobComplete() is currently processing (needed in case |
| // HostResolver gets deleted from within the callback). |
| scoped_refptr<Job> cur_completing_job_; |
| |
| // The observers to notify when a request starts/ends. |
| ObserversList observers_; |
| |
| // Monotonically increasing ID number to assign to the next request. |
| // Observers are the only consumers of this ID number. |
| int next_request_id_; |
| |
| // Monotonically increasing ID number to assign to the next job. |
| // The only consumer of this ID is the requests tracing code. |
| int next_job_id_; |
| |
| // The procedure to use for resolving host names. This will be NULL, except |
| // in the case of unit-tests which inject custom host resolving behaviors. |
| scoped_refptr<HostResolverProc> resolver_proc_; |
| |
| // Address family to use when the request doesn't specify one. |
| AddressFamily default_address_family_; |
| |
| // TODO(eroman): hack for http://crbug.com/15513 |
| bool shutdown_; |
| |
| // Indicate if probing is done after each network change event to set address |
| // family. |
| // When false, explicit setting of address family is used. |
| bool ipv6_probe_monitoring_; |
| |
| // The last un-cancelled IPv6ProbeJob (if any). |
| scoped_refptr<IPv6ProbeJob> ipv6_probe_job_; |
| |
| // Any resolver flags that should be added to a request by default. |
| HostResolverFlags additional_resolver_flags_; |
| |
| NetLog* net_log_; |
| |
| DISALLOW_COPY_AND_ASSIGN(HostResolverImpl); |
| }; |
| |
| } // namespace net |
| |
| #endif // NET_BASE_HOST_RESOLVER_IMPL_H_ |