Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(255)

Unified Diff: net/base/host_resolver_impl.cc

Issue 149511: Refactorings surrounding HostResolver:... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Merge in socks5_client_socket_unittest.cc Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/base/host_resolver_impl.h ('k') | net/base/host_resolver_impl_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/host_resolver_impl.cc
===================================================================
--- net/base/host_resolver_impl.cc (revision 20435)
+++ net/base/host_resolver_impl.cc (working copy)
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/base/host_resolver.h"
+#include "net/base/host_resolver_impl.h"
#if defined(OS_WIN)
#include <ws2tcpip.h>
@@ -22,161 +22,36 @@
#include "base/time.h"
#include "base/worker_pool.h"
#include "net/base/address_list.h"
+#include "net/base/host_resolver_proc.h"
#include "net/base/net_errors.h"
-#if defined(OS_LINUX)
-#include "base/singleton.h"
-#include "base/thread_local_storage.h"
-#endif
-
#if defined(OS_WIN)
#include "net/base/winsock_init.h"
#endif
namespace net {
-//-----------------------------------------------------------------------------
-
-static HostMapper* host_mapper;
-
-std::string HostMapper::MapUsingPrevious(const std::string& host) {
- return previous_mapper_.get() ? previous_mapper_->Map(host) : host;
+HostResolver* CreateSystemHostResolver() {
+ static const size_t kMaxHostCacheEntries = 100;
+ static const size_t kHostCacheExpirationMs = 60000; // 1 minute.
+ return new HostResolverImpl(
+ NULL, kMaxHostCacheEntries, kHostCacheExpirationMs);
}
-HostMapper* SetHostMapper(HostMapper* value) {
- std::swap(host_mapper, value);
- return value;
-}
-
-#if defined(OS_LINUX)
-// On Linux changes to /etc/resolv.conf can go unnoticed thus resulting in
-// DNS queries failing either because nameservers are unknown on startup
-// or because nameserver info has changed as a result of e.g. connecting to
-// a new network. Some distributions patch glibc to stat /etc/resolv.conf
-// to try to automatically detect such changes but these patches are not
-// universal and even patched systems such as Jaunty appear to need calls
-// to res_ninit to reload the nameserver information in different threads.
-//
-// We adopt the Mozilla solution here which is to call res_ninit when
-// lookups fail and to rate limit the reloading to once per second per
-// thread.
-
-// Keep a timer per calling thread to rate limit the calling of res_ninit.
-class DnsReloadTimer {
- public:
- DnsReloadTimer() {
- tls_index_.Initialize(SlotReturnFunction);
- }
-
- ~DnsReloadTimer() { }
-
- // Check if the timer for the calling thread has expired. When no
- // timer exists for the calling thread, create one.
- bool Expired() {
- const base::TimeDelta kRetryTime = base::TimeDelta::FromSeconds(1);
- base::TimeTicks now = base::TimeTicks::Now();
- base::TimeTicks* timer_ptr =
- static_cast<base::TimeTicks*>(tls_index_.Get());
-
- if (!timer_ptr) {
- timer_ptr = new base::TimeTicks();
- *timer_ptr = base::TimeTicks::Now();
- tls_index_.Set(timer_ptr);
- // Return true to reload dns info on the first call for each thread.
- return true;
- } else if (now - *timer_ptr > kRetryTime) {
- *timer_ptr = now;
- return true;
- } else {
- return false;
- }
- }
-
- // Free the allocated timer.
- static void SlotReturnFunction(void* data) {
- base::TimeTicks* tls_data = static_cast<base::TimeTicks*>(data);
- delete tls_data;
- }
-
- private:
- // We use thread local storage to identify which base::TimeTicks to
- // interact with.
- static ThreadLocalStorage::Slot tls_index_ ;
-
- DISALLOW_COPY_AND_ASSIGN(DnsReloadTimer);
-};
-
-// A TLS slot to the TimeTicks for the current thread.
-// static
-ThreadLocalStorage::Slot DnsReloadTimer::tls_index_(base::LINKER_INITIALIZED);
-
-#endif // defined(OS_LINUX)
-
-static int HostResolverProc(const std::string& host, struct addrinfo** out) {
- struct addrinfo hints = {0};
- hints.ai_family = AF_UNSPEC;
-
-#if defined(OS_WIN)
- // DO NOT USE AI_ADDRCONFIG ON WINDOWS.
- //
- // The following comment in <winsock2.h> is the best documentation I found
- // on AI_ADDRCONFIG for Windows:
- // Flags used in "hints" argument to getaddrinfo()
- // - AI_ADDRCONFIG is supported starting with Vista
- // - default is AI_ADDRCONFIG ON whether the flag is set or not
- // because the performance penalty in not having ADDRCONFIG in
- // the multi-protocol stack environment is severe;
- // this defaulting may be disabled by specifying the AI_ALL flag,
- // in that case AI_ADDRCONFIG must be EXPLICITLY specified to
- // enable ADDRCONFIG behavior
- //
- // Not only is AI_ADDRCONFIG unnecessary, but it can be harmful. If the
- // computer is not connected to a network, AI_ADDRCONFIG causes getaddrinfo
- // to fail with WSANO_DATA (11004) for "localhost", probably because of the
- // following note on AI_ADDRCONFIG in the MSDN getaddrinfo page:
- // The IPv4 or IPv6 loopback address is not considered a valid global
- // address.
- // See http://crbug.com/5234.
- hints.ai_flags = 0;
-#else
- hints.ai_flags = AI_ADDRCONFIG;
-#endif
-
- // Restrict result set to only this socket type to avoid duplicates.
- hints.ai_socktype = SOCK_STREAM;
-
- int err = getaddrinfo(host.c_str(), NULL, &hints, out);
-#if defined(OS_LINUX)
- net::DnsReloadTimer* dns_timer = Singleton<net::DnsReloadTimer>::get();
- // If we fail, re-initialise the resolver just in case there have been any
- // changes to /etc/resolv.conf and retry. See http://crbug.com/11380 for info.
- if (err && dns_timer->Expired()) {
- res_nclose(&_res);
- if (!res_ninit(&_res))
- err = getaddrinfo(host.c_str(), NULL, &hints, out);
- }
-#endif
-
- return err ? ERR_NAME_NOT_RESOLVED : OK;
-}
-
-static int ResolveAddrInfo(HostMapper* mapper, const std::string& host,
- struct addrinfo** out) {
- if (mapper) {
- std::string mapped_host = mapper->Map(host);
-
- if (mapped_host.empty())
- return ERR_NAME_NOT_RESOLVED;
-
- return HostResolverProc(mapped_host, out);
+static int ResolveAddrInfo(HostResolverProc* resolver_proc,
+ const std::string& host, AddressList* out) {
+ if (resolver_proc) {
+ // Use the custom procedure.
+ return resolver_proc->Resolve(host, out);
} else {
- return HostResolverProc(host, out);
+ // Use the system procedure (getaddrinfo).
+ return SystemHostResolverProc(host, out);
}
}
//-----------------------------------------------------------------------------
-class HostResolver::Request {
+class HostResolverImpl::Request {
public:
Request(int id, const RequestInfo& info, CompletionCallback* callback,
AddressList* addresses)
@@ -245,28 +120,25 @@
// This class represents a request to the worker pool for a "getaddrinfo()"
// call.
-class HostResolver::Job : public base::RefCountedThreadSafe<HostResolver::Job> {
+class HostResolverImpl::Job
+ : public base::RefCountedThreadSafe<HostResolverImpl::Job> {
public:
- Job(HostResolver* resolver, const std::string& host)
+ Job(HostResolverImpl* resolver, const std::string& host)
: host_(host),
resolver_(resolver),
origin_loop_(MessageLoop::current()),
- host_mapper_(host_mapper),
- error_(OK),
- results_(NULL) {
+ resolver_proc_(resolver->effective_resolver_proc()),
+ error_(OK) {
}
~Job() {
- if (results_)
- freeaddrinfo(results_);
-
// Free the requests attached to this job.
STLDeleteElements(&requests_);
}
// Attaches a request to this job. The job takes ownership of |req| and will
// take care to delete it.
- void AddRequest(HostResolver::Request* req) {
+ void AddRequest(Request* req) {
req->set_job(this);
requests_.push_back(req);
}
@@ -301,11 +173,11 @@
// We don't have to do anything further to actually cancel the requests
// that were attached to this job (since they are unreachable now).
- // But we will call HostResolver::CancelRequest(Request*) on each one
+ // But we will call HostResolverImpl::CancelRequest(Request*) on each one
// in order to notify any observers.
for (RequestsList::const_iterator it = requests_.begin();
it != requests_.end(); ++it) {
- HostResolver::Request* req = *it;
+ HostResolverImpl::Request* req = *it;
if (!req->was_cancelled())
resolver->CancelRequest(req);
}
@@ -329,7 +201,7 @@
private:
void DoLookup() {
// Running on the worker thread
- error_ = ResolveAddrInfo(host_mapper_, host_, &results_);
+ error_ = ResolveAddrInfo(resolver_proc_, host_, &results_);
Task* reply = NewRunnableMethod(this, &Job::OnLookupComplete);
@@ -353,59 +225,57 @@
// TODO(eroman): this is being hit by URLRequestTest.CancelTest*,
// because MessageLoop::current() == NULL.
//DCHECK_EQ(origin_loop_, MessageLoop::current());
- DCHECK(error_ || results_);
+ DCHECK(error_ || results_.head());
if (was_cancelled())
return;
DCHECK(!requests_.empty());
- // Adopt the address list using the port number of the first request.
- AddressList addrlist;
- if (error_ == OK) {
- addrlist.Adopt(results_);
- addrlist.SetPort(requests_[0]->port());
- results_ = NULL;
- }
+ // Use the port number of the first request.
+ if (error_ == OK)
+ results_.SetPort(requests_[0]->port());
- resolver_->OnJobComplete(this, error_, addrlist);
+ resolver_->OnJobComplete(this, error_, results_);
}
// Set on the origin thread, read on the worker thread.
std::string host_;
// Only used on the origin thread (where Resolve was called).
- HostResolver* resolver_;
+ HostResolverImpl* resolver_;
RequestsList requests_; // The requests waiting on this job.
// Used to post ourselves onto the origin thread.
Lock origin_loop_lock_;
MessageLoop* origin_loop_;
- // Hold an owning reference to the host mapper that we are going to use.
- // This may not be the current host mapper by the time we call
+ // Hold an owning reference to the HostResolverProc that we are going to use.
+ // This may not be the current resolver procedure by the time we call
// ResolveAddrInfo, but that's OK... we'll use it anyways, and the owning
// reference ensures that it remains valid until we are done.
- scoped_refptr<HostMapper> host_mapper_;
+ scoped_refptr<HostResolverProc> resolver_proc_;
// Assigned on the worker thread, read on the origin thread.
int error_;
- struct addrinfo* results_;
+ AddressList results_;
DISALLOW_COPY_AND_ASSIGN(Job);
};
//-----------------------------------------------------------------------------
-HostResolver::HostResolver(int max_cache_entries, int cache_duration_ms)
+HostResolverImpl::HostResolverImpl(HostResolverProc* resolver_proc,
+ int max_cache_entries,
+ int cache_duration_ms)
: cache_(max_cache_entries, cache_duration_ms), next_request_id_(0),
- shutdown_(false) {
+ resolver_proc_(resolver_proc), shutdown_(false) {
#if defined(OS_WIN)
EnsureWinsockInit();
#endif
}
-HostResolver::~HostResolver() {
+HostResolverImpl::~HostResolverImpl() {
// Cancel the outstanding jobs. Those jobs may contain several attached
// requests, which will also be cancelled.
for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it)
@@ -418,10 +288,10 @@
// TODO(eroman): Don't create cache entries for hostnames which are simply IP
// address literals.
-int HostResolver::Resolve(const RequestInfo& info,
- AddressList* addresses,
- CompletionCallback* callback,
- Request** out_req) {
+int HostResolverImpl::Resolve(const RequestInfo& info,
+ AddressList* addresses,
+ CompletionCallback* callback,
+ RequestHandle* out_req) {
if (shutdown_)
return ERR_UNEXPECTED;
@@ -437,7 +307,7 @@
info.hostname(), base::TimeTicks::Now());
if (cache_entry) {
addresses->SetFrom(cache_entry->addrlist, info.port());
- int error = OK;
+ int error = cache_entry->error;
// Notify registered observers.
NotifyObserversFinishRequest(request_id, info, error);
@@ -448,13 +318,10 @@
// If no callback was specified, do a synchronous resolution.
if (!callback) {
- struct addrinfo* results;
- int error = ResolveAddrInfo(host_mapper, info.hostname(), &results);
-
- // Adopt the address list.
AddressList addrlist;
+ int error = ResolveAddrInfo(
+ effective_resolver_proc(), info.hostname(), &addrlist);
if (error == OK) {
- addrlist.Adopt(results);
addrlist.SetPort(info.port());
*addresses = addrlist;
}
@@ -472,7 +339,7 @@
// asked for it (out_req != NULL).
Request* req = new Request(request_id, info, callback, addresses);
if (out_req)
- *out_req = req;
+ *out_req = reinterpret_cast<RequestHandle>(req);
// Next we need to attach our request to a "job". This job is responsible for
// calling "getaddrinfo(hostname)" on a worker thread.
@@ -499,7 +366,8 @@
// See OnJobComplete(Job*) for why it is important not to clean out
// cancelled requests from Job::requests_.
-void HostResolver::CancelRequest(Request* req) {
+void HostResolverImpl::CancelRequest(RequestHandle req_handle) {
+ Request* req = reinterpret_cast<Request*>(req_handle);
DCHECK(req);
DCHECK(req->job());
// NULL out the fields of req, to mark it as cancelled.
@@ -507,11 +375,11 @@
NotifyObserversCancelRequest(req->id(), req->info());
}
-void HostResolver::AddObserver(Observer* observer) {
+void HostResolverImpl::AddObserver(Observer* observer) {
observers_.push_back(observer);
}
-void HostResolver::RemoveObserver(Observer* observer) {
+void HostResolverImpl::RemoveObserver(Observer* observer) {
ObserversList::iterator it =
std::find(observers_.begin(), observers_.end(), observer);
@@ -521,7 +389,7 @@
observers_.erase(it);
}
-void HostResolver::Shutdown() {
+void HostResolverImpl::Shutdown() {
shutdown_ = true;
// Cancel the outstanding jobs.
@@ -530,13 +398,13 @@
jobs_.clear();
}
-void HostResolver::AddOutstandingJob(Job* job) {
+void HostResolverImpl::AddOutstandingJob(Job* job) {
scoped_refptr<Job>& found_job = jobs_[job->host()];
DCHECK(!found_job);
found_job = job;
}
-HostResolver::Job* HostResolver::FindOutstandingJob(
+HostResolverImpl::Job* HostResolverImpl::FindOutstandingJob(
const std::string& hostname) {
JobMap::iterator it = jobs_.find(hostname);
if (it != jobs_.end())
@@ -544,14 +412,14 @@
return NULL;
}
-void HostResolver::RemoveOutstandingJob(Job* job) {
+void HostResolverImpl::RemoveOutstandingJob(Job* job) {
JobMap::iterator it = jobs_.find(job->host());
DCHECK(it != jobs_.end());
DCHECK_EQ(it->second.get(), job);
jobs_.erase(it);
}
-void HostResolver::OnJobComplete(Job* job,
+void HostResolverImpl::OnJobComplete(Job* job,
int error,
const AddressList& addrlist) {
RemoveOutstandingJob(job);
@@ -586,7 +454,7 @@
cur_completing_job_ = NULL;
}
-void HostResolver::NotifyObserversStartRequest(int request_id,
+void HostResolverImpl::NotifyObserversStartRequest(int request_id,
const RequestInfo& info) {
for (ObserversList::iterator it = observers_.begin();
it != observers_.end(); ++it) {
@@ -594,7 +462,7 @@
}
}
-void HostResolver::NotifyObserversFinishRequest(int request_id,
+void HostResolverImpl::NotifyObserversFinishRequest(int request_id,
const RequestInfo& info,
int error) {
bool was_resolved = error == OK;
@@ -604,7 +472,7 @@
}
}
-void HostResolver::NotifyObserversCancelRequest(int request_id,
+void HostResolverImpl::NotifyObserversCancelRequest(int request_id,
const RequestInfo& info) {
for (ObserversList::iterator it = observers_.begin();
it != observers_.end(); ++it) {
@@ -612,56 +480,4 @@
}
}
-//-----------------------------------------------------------------------------
-
-SingleRequestHostResolver::SingleRequestHostResolver(HostResolver* resolver)
- : resolver_(resolver),
- cur_request_(NULL),
- cur_request_callback_(NULL),
- ALLOW_THIS_IN_INITIALIZER_LIST(
- callback_(this, &SingleRequestHostResolver::OnResolveCompletion)) {
- DCHECK(resolver_ != NULL);
-}
-
-SingleRequestHostResolver::~SingleRequestHostResolver() {
- if (cur_request_) {
- resolver_->CancelRequest(cur_request_);
- }
-}
-
-int SingleRequestHostResolver::Resolve(const HostResolver::RequestInfo& info,
- AddressList* addresses,
- CompletionCallback* callback) {
- DCHECK(!cur_request_ && !cur_request_callback_) << "resolver already in use";
-
- HostResolver::Request* request = NULL;
-
- // We need to be notified of completion before |callback| is called, so that
- // we can clear out |cur_request_*|.
- CompletionCallback* transient_callback = callback ? &callback_ : NULL;
-
- int rv = resolver_->Resolve(info, addresses, transient_callback, &request);
-
- if (rv == ERR_IO_PENDING) {
- // Cleared in OnResolveCompletion().
- cur_request_ = request;
- cur_request_callback_ = callback;
- }
-
- return rv;
-}
-
-void SingleRequestHostResolver::OnResolveCompletion(int result) {
- DCHECK(cur_request_ && cur_request_callback_);
-
- CompletionCallback* callback = cur_request_callback_;
-
- // Clear the outstanding request information.
- cur_request_ = NULL;
- cur_request_callback_ = NULL;
-
- // Call the user's original callback.
- callback->Run(result);
-}
-
} // namespace net
« no previous file with comments | « net/base/host_resolver_impl.h ('k') | net/base/host_resolver_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698