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

Unified Diff: net/base/host_resolver_impl.cc

Issue 9369045: [net] HostResolverImpl + DnsTransaction + DnsConfigService = Asynchronous DNS ready for experiments. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix ClientSocketFactory lifetime. Move ScopedAllowIO to StartWatch. Added DnsTask logging. Created 8 years, 10 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
Index: net/base/host_resolver_impl.cc
diff --git a/net/base/host_resolver_impl.cc b/net/base/host_resolver_impl.cc
index d9330e213cebb1405002629e2fda5e6042329fac..c7b8c925d947b9b90e7cb835d0b0136f7ac39716 100644
--- a/net/base/host_resolver_impl.cc
+++ b/net/base/host_resolver_impl.cc
@@ -24,12 +24,14 @@
#include "base/message_loop_proxy.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
+#include "base/rand_util.h"
#include "base/stl_util.h"
#include "base/string_util.h"
#include "base/threading/worker_pool.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
+#include "net/base/address_family.h"
#include "net/base/address_list.h"
#include "net/base/address_list_net_log_param.h"
#include "net/base/dns_reloader.h"
@@ -38,6 +40,12 @@
#include "net/base/net_errors.h"
#include "net/base/net_log.h"
#include "net/base/net_util.h"
+#include "net/dns/dns_config_service.h"
+#include "net/dns/dns_protocol.h"
+#include "net/dns/dns_response.h"
+#include "net/dns/dns_session.h"
+#include "net/dns/dns_transaction.h"
+#include "net/socket/client_socket_factory.h"
#if defined(OS_WIN)
#include "net/base/winsock_init.h"
@@ -315,8 +323,8 @@ void LogCancelRequest(const BoundNetLog& source_net_log,
// Keeps track of the highest priority.
class PriorityTracker {
public:
- PriorityTracker()
- : highest_priority_(IDLE), total_count_(0) {
+ PriorityTracker(RequestPriority priority)
cbentzel 2012/02/14 13:08:26 explicit
+ : highest_priority_(priority), total_count_(0) {
cbentzel 2012/02/14 13:08:26 This was a little tricky - I expected total_count_
memset(counts_, 0, sizeof(counts_));
}
@@ -359,22 +367,66 @@ class PriorityTracker {
//-----------------------------------------------------------------------------
+// Convenience wrapper for PrioritizedDispatcher::Handle so that we don't forget
+// to update it when cancelling or changing the priority.
+// TODO(szym): consider making PrioritizedDispatcher::Handle into this.
+class DispatcherHandle {
+ public:
+ DispatcherHandle() : dispatcher_(NULL) {}
+ DispatcherHandle(PrioritizedDispatcher* dispatcher,
+ const PrioritizedDispatcher::Handle& handle)
+ : dispatcher_(dispatcher), handle_(handle) {
+ if (handle_.is_null())
+ dispatcher_ = NULL;
+ }
+
+ bool is_null() const {
+ return dispatcher_ == NULL;
+ }
+
+ void Reset() {
+ dispatcher_ = NULL;
+ handle_ = PrioritizedDispatcher::Handle();
+ }
+
+ void ChangePriority(RequestPriority priority) {
+ DCHECK(!is_null());
+ handle_ = dispatcher_->ChangePriority(handle_, priority);
+ }
+
+ void Cancel() {
+ DCHECK(!is_null());
+ dispatcher_->Cancel(handle_);
+ Reset();
+ }
+
+ private:
+ PrioritizedDispatcher* dispatcher_;
+ PrioritizedDispatcher::Handle handle_;
+};
+
+//-----------------------------------------------------------------------------
+
HostResolver* CreateHostResolver(size_t max_concurrent_resolves,
size_t max_retry_attempts,
- bool use_cache,
+ HostCache* cache,
+ scoped_ptr<DnsConfigService> config_service,
NetLog* net_log) {
if (max_concurrent_resolves == HostResolver::kDefaultParallelism)
max_concurrent_resolves = kDefaultMaxProcTasks;
// TODO(szym): Add experiments with reserved slots for higher priority
// requests.
+ // TODO(szym): Add tighter limits for proc_dispatcher_
cbentzel 2012/02/14 13:12:06 Why do you need this TODO? In this case it will on
szym 2012/02/14 15:56:24 I need this TODO to remember that even if I start
PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, max_concurrent_resolves);
HostResolverImpl* resolver = new HostResolverImpl(
- use_cache ? HostCache::CreateDefaultCache() : NULL,
+ cache,
+ limits,
limits,
HostResolverImpl::ProcTaskParams(NULL, max_retry_attempts),
+ config_service.Pass(),
net_log);
return resolver;
@@ -389,7 +441,8 @@ HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves,
NetLog* net_log) {
return CreateHostResolver(max_concurrent_resolves,
max_retry_attempts,
- true /* use_cache */,
+ HostCache::CreateDefaultCache(),
+ scoped_ptr<DnsConfigService>(NULL),
net_log);
}
@@ -398,7 +451,21 @@ HostResolver* CreateNonCachingSystemHostResolver(size_t max_concurrent_resolves,
NetLog* net_log) {
return CreateHostResolver(max_concurrent_resolves,
max_retry_attempts,
- false /* use_cache */,
+ NULL,
+ scoped_ptr<DnsConfigService>(NULL),
+ net_log);
+}
+
+HostResolver* CreateAsyncHostResolver(size_t max_concurrent_resolves,
+ size_t max_retry_attempts,
+ NetLog* net_log) {
+ scoped_ptr<DnsConfigService> config_service
+ = DnsConfigService::CreateSystemService();
mmenke 2012/02/14 18:46:00 nit: Put the equals sign on the previous line (Ca
+ config_service->Watch();
+ return CreateHostResolver(max_concurrent_resolves,
+ max_retry_attempts,
+ HostCache::CreateDefaultCache(),
+ config_service.Pass(),
net_log);
}
@@ -505,7 +572,9 @@ class HostResolverImpl::Request {
class HostResolverImpl::ProcTask
: public base::RefCountedThreadSafe<HostResolverImpl::ProcTask> {
public:
- typedef base::Callback<void(int, int, const AddressList&)> Callback;
+ typedef base::Callback<void(int net_error,
+ int os_error,
+ const AddressList& addr_list)> Callback;
ProcTask(const Key& key,
const ProcTaskParams& params,
@@ -891,6 +960,8 @@ class HostResolverImpl::ProcTask
//-----------------------------------------------------------------------------
// Represents a request to the worker pool for a "probe for IPv6 support" call.
+//
+// TODO(szym): This could also be replaced with PostTaskAndReply and Callbacks.
class HostResolverImpl::IPv6ProbeJob
: public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> {
public:
@@ -958,6 +1029,74 @@ class HostResolverImpl::IPv6ProbeJob
//-----------------------------------------------------------------------------
+// Resolves the hostname using DnsTransaction.
+// TODO(szym): This could be moved to separate source file as well.
+class HostResolverImpl::DnsTask {
+ public:
+ typedef base::Callback<void(int net_error,
+ const AddressList& addr_list,
+ base::TimeDelta ttl)> Callback;
+
+ DnsTask(DnsTransactionFactory* factory,
+ const Key& key,
+ const Callback& callback,
+ const BoundNetLog& job_net_log)
+ : callback_(callback), net_log_(job_net_log) {
+ DCHECK(factory);
+ DCHECK(!callback.is_null());
+
+ // For now we treat ADDRESS_FAMILY_UNSPEC as if it was IPV4.
+ uint16 qtype = (key.address_family == ADDRESS_FAMILY_IPV6)
+ ? dns_protocol::kTypeAAAA
+ : dns_protocol::kTypeA;
+ // TODO(szym): Implement "happy eyeballs".
+ transaction_ = factory->CreateTransaction(
+ key.hostname,
+ qtype,
+ base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this)),
+ net_log_);
+ DCHECK(transaction_.get());
+ }
+
+ int Start() {
+ net_log_.BeginEvent(
+ NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK,
+ new NetLogSourceParameter("source_dependency",
+ transaction_->net_log().source()));
+ return transaction_->Start();
+ }
+
+ void OnTransactionComplete(DnsTransaction* transaction,
+ int net_error,
+ const DnsResponse* response) {
+ // TODO(szym): Record performance histograms.
+ if (net_error == OK) {
+ AddressList addr_list;
+ base::TimeDelta ttl;
+ if (response->ParseAddressList(&addr_list, &ttl)) {
+ net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK,
+ new AddressListNetLogParam(addr_list));
+ callback_.Run(net_error, addr_list, ttl);
+ return;
+ }
+ net_error = ERR_DNS_MALFORMED_RESPONSE;
+ }
+ callback_.Run(net_error, AddressList(), base::TimeDelta());
+ net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK,
+ net_error);
+ }
+
+ private:
+ // The listener to the results of this DnsTask.
+ Callback callback_;
+
+ const BoundNetLog net_log_;
+
+ scoped_ptr<DnsTransaction> transaction_;
+};
+
+//-----------------------------------------------------------------------------
+
// Aggregates all Requests for the same Key. Dispatched via PriorityDispatch.
// Spawns ProcTask when started.
cbentzel 2012/02/14 13:08:26 The comment "Spawns ProcTask when started" is no l
class HostResolverImpl::Job : public PrioritizedDispatcher::Job {
@@ -966,9 +1105,11 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job {
// request that spawned it.
Job(HostResolverImpl* resolver,
const Key& key,
- const BoundNetLog& request_net_log)
+ const BoundNetLog& request_net_log,
+ RequestPriority priority)
: resolver_(resolver->AsWeakPtr()),
key_(key),
+ priority_tracker_(priority),
had_non_speculative_request_(false),
net_log_(BoundNetLog::Make(request_net_log.net_log(),
NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)),
@@ -1009,10 +1150,6 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job {
STLDeleteElements(&requests_);
}
- HostResolverImpl* resolver() const {
- return resolver_;
- }
-
RequestPriority priority() const {
return priority_tracker_.highest_priority();
}
@@ -1030,13 +1167,13 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job {
return net_error_;
}
- // Used by HostResolverImpl with |dispatcher_|.
- const PrioritizedDispatcher::Handle& handle() const {
- return handle_;
+ void AddToDispatcher(PrioritizedDispatcher* dispatcher) {
+ DCHECK(handle_.is_null());
+ handle_ = DispatcherHandle(dispatcher, dispatcher->Add(this, priority()));
}
- void set_handle(const PrioritizedDispatcher::Handle& handle) {
- handle_ = handle;
+ bool IsWaitingInDispatch() const {
+ return !handle_.is_null();
}
// The Job will own |req| and destroy it in ~Job.
cbentzel 2012/02/14 13:08:26 Nit: change this to take a scoped_ptr<Request> arg
@@ -1064,6 +1201,9 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job {
if (proc_task_)
proc_task_->set_had_non_speculative_request();
}
+
+ if (!handle_.is_null())
+ handle_.ChangePriority(priority());
}
void CancelRequest(Request* req) {
@@ -1078,44 +1218,72 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job {
NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_DETACH,
make_scoped_refptr(new JobAttachParameters(
req->request_net_log().source(), priority())));
+
+ if (!handle_.is_null()) {
+ if (num_active_requests() > 0) {
+ handle_.ChangePriority(priority());
+ } else {
+ handle_.Cancel();
+ }
+ }
}
// Aborts and destroys the job, completes all requests as aborted.
void Abort() {
// Job should only be aborted if it's running.
DCHECK(is_running());
cbentzel 2012/02/14 13:08:26 Should this remove itself from the PrioritizedDisp
szym 2012/02/14 15:56:24 If is_running() then handle_ should be null. (A ru
- proc_task_->Cancel();
- proc_task_ = NULL;
+ if (proc_task_.get()) {
+ proc_task_->Cancel();
+ proc_task_ = NULL;
+ }
+ dns_task_.reset();
net_error_ = ERR_ABORTED;
os_error_ = 0;
- CompleteRequests(AddressList());
+ CompleteRequests(AddressList(), base::TimeDelta());
}
- bool is_running() const {
+ bool is_dns_running() const {
+ return dns_task_.get() != NULL;
+ }
+
+ bool is_proc_running() const {
return proc_task_.get() != NULL;
}
+ bool is_running() const {
+ return is_dns_running() || is_proc_running();
+ }
+
// Called by HostResolverImpl when this job is evicted due to queue overflow.
void OnEvicted() {
// Must not be running.
DCHECK(!is_running());
- handle_ = PrioritizedDispatcher::Handle();
+ handle_.Reset();
net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED, NULL);
// This signals to CompleteRequests that this job never ran.
net_error_ = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE;
os_error_ = 0;
- CompleteRequests(AddressList());
+ CompleteRequests(AddressList(), base::TimeDelta());
}
// PriorityDispatch::Job interface.
virtual void Start() OVERRIDE {
DCHECK(!is_running());
- handle_ = PrioritizedDispatcher::Handle();
+ handle_.Reset();
net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED, NULL);
+ if (resolver_->dns_transaction_factory_.get()) {
+ StartDnsTask();
+ } else {
+ StartProcTask();
+ }
+ }
+
+ private:
+ void StartProcTask() {
proc_task_ = new ProcTask(
key_,
resolver_->proc_params_,
@@ -1129,33 +1297,70 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job {
proc_task_->Start();
}
- private:
+ void StartDnsTask() {
+ dns_task_.reset(new DnsTask(
+ resolver_->dns_transaction_factory_.get(),
+ key_,
+ base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this)),
+ net_log_));
+
+ int rv = dns_task_->Start();
+ if (rv != ERR_IO_PENDING) {
+ DCHECK_NE(OK, rv);
+ // TODO(szym): AddToDispatcher(resolver_->proc_dispatcher_);
+ StartProcTask();
+ }
+ }
+
// Called by ProcTask when it completes.
void OnProcTaskComplete(int net_error, int os_error,
cbentzel 2012/02/14 13:08:26 Nit: probably easier to read if this were moved di
- const AddressList& addrlist) {
- DCHECK(is_running());
+ const AddressList& addr_list) {
+ DCHECK(is_proc_running());
proc_task_ = NULL;
net_error_ = net_error;
os_error_ = os_error;
- // We are the only consumer of |addrlist|, so we can safely change the port
- // without copy-on-write. This pays off, when job has only one request.
- AddressList list = addrlist;
- if (net_error == OK && !requests_.empty())
- MutableSetPort(requests_.front()->info().port(), &list);
- CompleteRequests(list);
+ base::TimeDelta ttl = base::TimeDelta::FromSeconds(0);
cbentzel 2012/02/14 13:08:26 Should there be a constant for negative cache TTL?
+ if (net_error == OK)
+ ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds);
+ CompleteRequests(addr_list, ttl);
+ }
+
+ // Called by DnsTask when it completes.
+ void OnDnsTaskComplete(int net_error,
+ const AddressList& addr_list,
+ base::TimeDelta ttl) {
+ DCHECK(is_dns_running());
+ dns_task_.reset();
+
+ if (net_error != OK) {
+ // TODO(szym): Some net errors indicate lack of connectivity. Starting
+ // ProcTask in that case is a waste of time.
+ StartProcTask();
+ return;
+ }
+
+ net_error_ = OK;
+ os_error_ = 0;
+ CompleteRequests(addr_list, ttl);
}
// Completes all Requests. Calls OnJobFinished and deletes self.
- void CompleteRequests(const AddressList& addrlist) {
+ void CompleteRequests(const AddressList& addr_list, base::TimeDelta ttl) {
CHECK(resolver_);
+ // We are the only consumer of |addr_list|, so we can safely change the port
+ // without copy-on-write. This pays off, when job has only one request.
+ AddressList list = addr_list;
+ if (net_error_ == OK && !requests_.empty())
+ MutableSetPort(requests_.front()->info().port(), &list);
+
// This job must be removed from resolver's |jobs_| now to make room for a
// new job with the same key in case one of the OnComplete callbacks decides
// to spawn one. Consequently, the job deletes itself when CompleteRequests
// is done.
scoped_ptr<Job> self_deleter(this);
- resolver_->OnJobFinished(this, addrlist);
+ resolver_->OnJobFinished(this, addr_list, ttl);
cbentzel 2012/02/14 13:08:26 Does this need to be called after deleting self? W
szym 2012/02/14 15:56:24 I'm not clear what you mean. After deleting self I
cbentzel 2012/02/14 18:01:27 It was the second point I was concerned about. Agr
// Complete all of the requests that were attached to the job.
for (RequestsList::const_iterator it = requests_.begin();
@@ -1170,7 +1375,7 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job {
LogFinishRequest(req->source_net_log(), req->request_net_log(),
req->info(), net_error_, os_error_);
- req->OnComplete(net_error_, addrlist);
+ req->OnComplete(net_error_, addr_list);
// Check if the resolver was destroyed as a result of running the
// callback. If it was, we could continue, but we choose to bail.
@@ -1179,7 +1384,7 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job {
}
}
- // Used to call OnJobFinished and RemoveJob.
+ // Used to call OnJobFinished.
base::WeakPtr<HostResolverImpl> resolver_;
Key key_;
@@ -1195,14 +1400,17 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job {
int net_error_;
int os_error_;
- // A ProcTask created and started when this Job is dispatched..
+ // Resolves the host using a HostResolverProc.
scoped_refptr<ProcTask> proc_task_;
+ // Resolves the host using a DnsTransaction.
+ scoped_ptr<DnsTask> dns_task_;
+
// All Requests waiting for the result of this Job. Some can be canceled.
RequestsList requests_;
// A handle used by HostResolverImpl in |dispatcher_|.
- PrioritizedDispatcher::Handle handle_;
+ DispatcherHandle handle_;
};
//-----------------------------------------------------------------------------
@@ -1221,18 +1429,23 @@ HostResolverImpl::ProcTaskParams::~ProcTaskParams() {}
HostResolverImpl::HostResolverImpl(
HostCache* cache,
const PrioritizedDispatcher::Limits& job_limits,
+ const PrioritizedDispatcher::Limits& proc_limits,
const ProcTaskParams& proc_params,
+ scoped_ptr<DnsConfigService> dns_config_service,
NetLog* net_log)
: cache_(cache),
dispatcher_(job_limits),
+ proc_dispatcher_(proc_limits),
cbentzel 2012/02/14 13:08:26 Is proc_dispatcher_ even used? It looks like we ju
szym 2012/02/14 15:56:24 Right now it is not. I'm okay removing it until we
cbentzel 2012/02/14 18:01:27 I'd recommend removing it for now, as well as the
max_queued_jobs_(job_limits.total_jobs * 100u),
proc_params_(proc_params),
default_address_family_(ADDRESS_FAMILY_UNSPECIFIED),
+ dns_config_service_(dns_config_service.Pass()),
ipv6_probe_monitoring_(false),
additional_resolver_flags_(0),
net_log_(net_log) {
DCHECK_GE(dispatcher_.num_priorities(), static_cast<size_t>(NUM_PRIORITIES));
+ DCHECK_EQ(proc_dispatcher_.num_priorities(), dispatcher_.num_priorities());
// Maximum of 4 retry attempts for host resolution.
static const size_t kDefaultMaxRetryAttempts = 4u;
@@ -1254,6 +1467,9 @@ HostResolverImpl::HostResolverImpl(
#endif
NetworkChangeNotifier::AddDNSObserver(this);
#endif
+
+ if (dns_config_service_.get())
+ dns_config_service_->AddObserver(this);
}
HostResolverImpl::~HostResolverImpl() {
@@ -1307,8 +1523,8 @@ int HostResolverImpl::Resolve(const RequestInfo& info,
Job* job;
if (jobit == jobs_.end()) {
// Create new Job.
- job = new Job(this, key, request_net_log);
- job->set_handle(dispatcher_.Add(job, info.priority()));
+ job = new Job(this, key, request_net_log, info.priority());
+ job->AddToDispatcher(&dispatcher_);
// Check for queue overflow.
if (dispatcher_.num_queued_jobs() > max_queued_jobs_) {
@@ -1332,8 +1548,6 @@ int HostResolverImpl::Resolve(const RequestInfo& info,
Request* req = new Request(source_net_log, request_net_log, info, callback,
addresses);
job->AddRequest(req);
- if (!job->handle().is_null())
- job->set_handle(dispatcher_.ChangePriority(job->handle(), job->priority()));
if (out_req)
*out_req = reinterpret_cast<RequestHandle>(req);
@@ -1391,23 +1605,16 @@ void HostResolverImpl::CancelRequest(RequestHandle req_handle) {
job->CancelRequest(req);
- if (!job->handle().is_null()) {
- // Still in queue.
- if (job->num_active_requests()) {
- job->set_handle(dispatcher_.ChangePriority(job->handle(),
- job->priority()));
+ if (job->num_active_requests() == 0) {
+ if (job->is_running()) {
+ // Job is running (and could be in CompleteRequests right now).
+ // But to be in Request::OnComplete we would have to have a non-canceled
+ // request. So it is safe to Abort it if it has no more active requests.
+ job->Abort();
} else {
- dispatcher_.Cancel(job->handle());
RemoveJob(job);
delete job;
}
- } else {
- // Job is running (and could be in CompleteRequests right now).
- // But to be in Request::OnComplete we would have to have a non-canceled
- // request. So it is safe to Abort it if it has no more active requests.
- if (!job->num_active_requests()) {
- job->Abort();
- }
}
}
@@ -1482,9 +1689,11 @@ bool HostResolverImpl::ServeFromCache(const Key& key,
return true;
}
-void HostResolverImpl::OnJobFinished(Job* job, const AddressList& addrlist) {
+void HostResolverImpl::OnJobFinished(Job* job,
+ const AddressList& addrlist,
+ base::TimeDelta ttl) {
DCHECK(job);
- DCHECK(job->handle().is_null());
+ DCHECK(!job->IsWaitingInDispatch());
RemoveJob(job);
if (job->net_error() == ERR_HOST_RESOLVER_QUEUE_TOO_LARGE)
return;
@@ -1495,9 +1704,6 @@ void HostResolverImpl::OnJobFinished(Job* job, const AddressList& addrlist) {
return;
// Write result to the cache.
if (cache_.get()) {
- base::TimeDelta ttl = base::TimeDelta::FromSeconds(0);
- if (job->net_error() == OK)
- ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds);
cache_->Set(job->key(), job->net_error(), addrlist,
base::TimeTicks::Now(), ttl);
}
@@ -1557,7 +1763,7 @@ void HostResolverImpl::AbortAllInProgressJobs() {
return;
} else {
// Keep it in |dispatch_|.
- DCHECK(!job->handle().is_null());
+ DCHECK(job->IsWaitingInDispatch());
}
}
}
@@ -1594,4 +1800,22 @@ void HostResolverImpl::OnDNSChanged() {
// |this| may be deleted inside AbortAllInProgressJobs().
}
+void HostResolverImpl::OnConfigChanged(const DnsConfig& dns_config) {
+ // We want a new factory in place, before we Abort running Jobs, so that the
+ // newly started jobs use the new factory.
+ bool had_factory = (dns_transaction_factory_.get() != NULL);
+ if (dns_config.IsValid()) {
+ dns_transaction_factory_ = DnsTransactionFactory::CreateFactory(
+ new DnsSession(dns_config,
+ ClientSocketFactory::GetDefaultFactory(),
+ base::Bind(&base::RandInt),
+ net_log_));
+ } else {
+ dns_transaction_factory_.reset();
+ }
+ if (had_factory) {
+ OnDNSChanged();
+ }
+}
+
} // namespace net

Powered by Google App Engine
This is Rietveld 408576698