OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/base/host_resolver_impl.h" | 5 #include "net/base/host_resolver_impl.h" |
6 | 6 |
7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
8 #include <Winsock2.h> | 8 #include <Winsock2.h> |
9 #elif defined(OS_POSIX) | 9 #elif defined(OS_POSIX) |
10 #include <netdb.h> | 10 #include <netdb.h> |
11 #endif | 11 #endif |
12 | 12 |
13 #include <cmath> | 13 #include <cmath> |
14 #include <utility> | 14 #include <utility> |
15 #include <vector> | 15 #include <vector> |
16 | 16 |
17 #include "base/basictypes.h" | 17 #include "base/basictypes.h" |
18 #include "base/bind.h" | 18 #include "base/bind.h" |
19 #include "base/bind_helpers.h" | 19 #include "base/bind_helpers.h" |
20 #include "base/callback.h" | 20 #include "base/callback.h" |
21 #include "base/compiler_specific.h" | 21 #include "base/compiler_specific.h" |
22 #include "base/debug/debugger.h" | 22 #include "base/debug/debugger.h" |
23 #include "base/debug/stack_trace.h" | 23 #include "base/debug/stack_trace.h" |
24 #include "base/message_loop_proxy.h" | 24 #include "base/message_loop_proxy.h" |
25 #include "base/metrics/field_trial.h" | 25 #include "base/metrics/field_trial.h" |
26 #include "base/metrics/histogram.h" | 26 #include "base/metrics/histogram.h" |
| 27 #include "base/rand_util.h" |
27 #include "base/stl_util.h" | 28 #include "base/stl_util.h" |
28 #include "base/string_util.h" | 29 #include "base/string_util.h" |
29 #include "base/threading/worker_pool.h" | 30 #include "base/threading/worker_pool.h" |
30 #include "base/time.h" | 31 #include "base/time.h" |
31 #include "base/utf_string_conversions.h" | 32 #include "base/utf_string_conversions.h" |
32 #include "base/values.h" | 33 #include "base/values.h" |
| 34 #include "net/base/address_family.h" |
33 #include "net/base/address_list.h" | 35 #include "net/base/address_list.h" |
34 #include "net/base/address_list_net_log_param.h" | 36 #include "net/base/address_list_net_log_param.h" |
35 #include "net/base/dns_reloader.h" | 37 #include "net/base/dns_reloader.h" |
36 #include "net/base/host_port_pair.h" | 38 #include "net/base/host_port_pair.h" |
37 #include "net/base/host_resolver_proc.h" | 39 #include "net/base/host_resolver_proc.h" |
38 #include "net/base/net_errors.h" | 40 #include "net/base/net_errors.h" |
39 #include "net/base/net_log.h" | 41 #include "net/base/net_log.h" |
40 #include "net/base/net_util.h" | 42 #include "net/base/net_util.h" |
| 43 #include "net/dns/dns_config_service.h" |
| 44 #include "net/dns/dns_protocol.h" |
| 45 #include "net/dns/dns_response.h" |
| 46 #include "net/dns/dns_session.h" |
| 47 #include "net/dns/dns_transaction.h" |
| 48 #include "net/socket/client_socket_factory.h" |
41 | 49 |
42 #if defined(OS_WIN) | 50 #if defined(OS_WIN) |
43 #include "net/base/winsock_init.h" | 51 #include "net/base/winsock_init.h" |
44 #endif | 52 #endif |
45 | 53 |
46 namespace net { | 54 namespace net { |
47 | 55 |
48 namespace { | 56 namespace { |
49 | 57 |
50 // Limit the size of hostnames that will be resolved to combat issues in | 58 // Limit the size of hostnames that will be resolved to combat issues in |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 request_net_log.AddEvent(NetLog::TYPE_CANCELLED, NULL); | 316 request_net_log.AddEvent(NetLog::TYPE_CANCELLED, NULL); |
309 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, NULL); | 317 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, NULL); |
310 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); | 318 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); |
311 } | 319 } |
312 | 320 |
313 //----------------------------------------------------------------------------- | 321 //----------------------------------------------------------------------------- |
314 | 322 |
315 // Keeps track of the highest priority. | 323 // Keeps track of the highest priority. |
316 class PriorityTracker { | 324 class PriorityTracker { |
317 public: | 325 public: |
318 PriorityTracker() | 326 PriorityTracker(RequestPriority priority) |
319 : highest_priority_(IDLE), total_count_(0) { | 327 : highest_priority_(priority), total_count_(0) { |
320 memset(counts_, 0, sizeof(counts_)); | 328 memset(counts_, 0, sizeof(counts_)); |
321 } | 329 } |
322 | 330 |
323 RequestPriority highest_priority() const { | 331 RequestPriority highest_priority() const { |
324 return highest_priority_; | 332 return highest_priority_; |
325 } | 333 } |
326 | 334 |
327 size_t total_count() const { | 335 size_t total_count() const { |
328 return total_count_; | 336 return total_count_; |
329 } | 337 } |
(...skipping 22 matching lines...) Expand all Loading... |
352 } | 360 } |
353 | 361 |
354 private: | 362 private: |
355 RequestPriority highest_priority_; | 363 RequestPriority highest_priority_; |
356 size_t total_count_; | 364 size_t total_count_; |
357 size_t counts_[NUM_PRIORITIES]; | 365 size_t counts_[NUM_PRIORITIES]; |
358 }; | 366 }; |
359 | 367 |
360 //----------------------------------------------------------------------------- | 368 //----------------------------------------------------------------------------- |
361 | 369 |
| 370 // Convenience wrapper for PrioritizedDispatcher::Handle so that we don't forget |
| 371 // to update it when cancelling or changing the priority. |
| 372 // TODO(szym): consider making PrioritizedDispatcher::Handle into this. |
| 373 class DispatcherHandle { |
| 374 public: |
| 375 DispatcherHandle() : dispatcher_(NULL) {} |
| 376 DispatcherHandle(PrioritizedDispatcher* dispatcher, |
| 377 const PrioritizedDispatcher::Handle& handle) |
| 378 : dispatcher_(dispatcher), handle_(handle) { |
| 379 if (handle_.is_null()) |
| 380 dispatcher_ = NULL; |
| 381 } |
| 382 |
| 383 bool is_null() const { |
| 384 return dispatcher_ == NULL; |
| 385 } |
| 386 |
| 387 void Reset() { |
| 388 dispatcher_ = NULL; |
| 389 handle_ = PrioritizedDispatcher::Handle(); |
| 390 } |
| 391 |
| 392 void ChangePriority(RequestPriority priority) { |
| 393 DCHECK(!is_null()); |
| 394 handle_ = dispatcher_->ChangePriority(handle_, priority); |
| 395 } |
| 396 |
| 397 void Cancel() { |
| 398 DCHECK(!is_null()); |
| 399 dispatcher_->Cancel(handle_); |
| 400 Reset(); |
| 401 } |
| 402 |
| 403 private: |
| 404 PrioritizedDispatcher* dispatcher_; |
| 405 PrioritizedDispatcher::Handle handle_; |
| 406 }; |
| 407 |
| 408 //----------------------------------------------------------------------------- |
| 409 |
362 HostResolver* CreateHostResolver(size_t max_concurrent_resolves, | 410 HostResolver* CreateHostResolver(size_t max_concurrent_resolves, |
363 size_t max_retry_attempts, | 411 size_t max_retry_attempts, |
364 bool use_cache, | 412 bool use_cache, |
| 413 bool use_async, |
365 NetLog* net_log) { | 414 NetLog* net_log) { |
366 if (max_concurrent_resolves == HostResolver::kDefaultParallelism) | 415 if (max_concurrent_resolves == HostResolver::kDefaultParallelism) |
367 max_concurrent_resolves = kDefaultMaxProcTasks; | 416 max_concurrent_resolves = kDefaultMaxProcTasks; |
368 | 417 |
369 // TODO(szym): Add experiments with reserved slots for higher priority | 418 // TODO(szym): Add experiments with reserved slots for higher priority |
370 // requests. | 419 // requests. |
| 420 // TODO(szym): Add tighter limits for proc_dispatcher_ |
371 | 421 |
372 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, max_concurrent_resolves); | 422 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, max_concurrent_resolves); |
373 | 423 |
| 424 scoped_ptr<DnsConfigService> config_service; |
| 425 if (use_async) |
| 426 config_service = DnsConfigService::CreateSystemService(); |
| 427 |
374 HostResolverImpl* resolver = new HostResolverImpl( | 428 HostResolverImpl* resolver = new HostResolverImpl( |
375 use_cache ? HostCache::CreateDefaultCache() : NULL, | 429 use_cache ? HostCache::CreateDefaultCache() : NULL, |
376 limits, | 430 limits, |
| 431 limits, |
377 HostResolverImpl::ProcTaskParams(NULL, max_retry_attempts), | 432 HostResolverImpl::ProcTaskParams(NULL, max_retry_attempts), |
| 433 config_service.Pass(), |
378 net_log); | 434 net_log); |
379 | 435 |
380 return resolver; | 436 return resolver; |
381 } | 437 } |
382 | 438 |
383 } // anonymous namespace | 439 } // anonymous namespace |
384 | 440 |
385 //----------------------------------------------------------------------------- | 441 //----------------------------------------------------------------------------- |
386 | 442 |
387 HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves, | 443 HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves, |
388 size_t max_retry_attempts, | 444 size_t max_retry_attempts, |
389 NetLog* net_log) { | 445 NetLog* net_log) { |
390 return CreateHostResolver(max_concurrent_resolves, | 446 return CreateHostResolver(max_concurrent_resolves, |
391 max_retry_attempts, | 447 max_retry_attempts, |
392 true /* use_cache */, | 448 true /* use_cache */, |
| 449 false /* use_async */, |
393 net_log); | 450 net_log); |
394 } | 451 } |
395 | 452 |
396 HostResolver* CreateNonCachingSystemHostResolver(size_t max_concurrent_resolves, | 453 HostResolver* CreateNonCachingSystemHostResolver(size_t max_concurrent_resolves, |
397 size_t max_retry_attempts, | 454 size_t max_retry_attempts, |
398 NetLog* net_log) { | 455 NetLog* net_log) { |
399 return CreateHostResolver(max_concurrent_resolves, | 456 return CreateHostResolver(max_concurrent_resolves, |
400 max_retry_attempts, | 457 max_retry_attempts, |
401 false /* use_cache */, | 458 false /* use_cache */, |
| 459 false /* use_async */, |
402 net_log); | 460 net_log); |
403 } | 461 } |
404 | 462 |
| 463 HostResolver* CreateAsyncHostResolver(size_t max_concurrent_resolves, |
| 464 size_t max_retry_attempts, |
| 465 NetLog* net_log) { |
| 466 return CreateHostResolver(max_concurrent_resolves, |
| 467 max_retry_attempts, |
| 468 true /* use_cache */, |
| 469 true /* use_async */, |
| 470 net_log); |
| 471 } |
| 472 |
405 //----------------------------------------------------------------------------- | 473 //----------------------------------------------------------------------------- |
406 | 474 |
407 // Holds the data for a request that could not be completed synchronously. | 475 // Holds the data for a request that could not be completed synchronously. |
408 // It is owned by a Job. Canceled Requests are only marked as canceled rather | 476 // It is owned by a Job. Canceled Requests are only marked as canceled rather |
409 // than removed from the Job's |requests_| list. | 477 // than removed from the Job's |requests_| list. |
410 class HostResolverImpl::Request { | 478 class HostResolverImpl::Request { |
411 public: | 479 public: |
412 Request(const BoundNetLog& source_net_log, | 480 Request(const BoundNetLog& source_net_log, |
413 const BoundNetLog& request_net_log, | 481 const BoundNetLog& request_net_log, |
414 const RequestInfo& info, | 482 const RequestInfo& info, |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 // resolution (OnLookupComplete) is completed or not. If the original attempt | 566 // resolution (OnLookupComplete) is completed or not. If the original attempt |
499 // hasn't completed, then we start another attempt for host resolution. We take | 567 // hasn't completed, then we start another attempt for host resolution. We take |
500 // the results from the first attempt that finishes and ignore the results from | 568 // the results from the first attempt that finishes and ignore the results from |
501 // all other attempts. | 569 // all other attempts. |
502 // | 570 // |
503 // TODO(szym): Move to separate source file for testing and mocking. | 571 // TODO(szym): Move to separate source file for testing and mocking. |
504 // | 572 // |
505 class HostResolverImpl::ProcTask | 573 class HostResolverImpl::ProcTask |
506 : public base::RefCountedThreadSafe<HostResolverImpl::ProcTask> { | 574 : public base::RefCountedThreadSafe<HostResolverImpl::ProcTask> { |
507 public: | 575 public: |
508 typedef base::Callback<void(int, int, const AddressList&)> Callback; | 576 typedef base::Callback<void(int net_error, |
| 577 int os_error, |
| 578 const AddressList& addr_list)> Callback; |
509 | 579 |
510 ProcTask(const Key& key, | 580 ProcTask(const Key& key, |
511 const ProcTaskParams& params, | 581 const ProcTaskParams& params, |
512 const Callback& callback, | 582 const Callback& callback, |
513 const BoundNetLog& job_net_log) | 583 const BoundNetLog& job_net_log) |
514 : key_(key), | 584 : key_(key), |
515 params_(params), | 585 params_(params), |
516 callback_(callback), | 586 callback_(callback), |
517 origin_loop_(base::MessageLoopProxy::current()), | 587 origin_loop_(base::MessageLoopProxy::current()), |
518 attempt_number_(0), | 588 attempt_number_(0), |
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
884 AddressList results_; | 954 AddressList results_; |
885 | 955 |
886 BoundNetLog net_log_; | 956 BoundNetLog net_log_; |
887 | 957 |
888 DISALLOW_COPY_AND_ASSIGN(ProcTask); | 958 DISALLOW_COPY_AND_ASSIGN(ProcTask); |
889 }; | 959 }; |
890 | 960 |
891 //----------------------------------------------------------------------------- | 961 //----------------------------------------------------------------------------- |
892 | 962 |
893 // Represents a request to the worker pool for a "probe for IPv6 support" call. | 963 // Represents a request to the worker pool for a "probe for IPv6 support" call. |
| 964 // |
| 965 // TODO(szym): This could also be replaced with PostTaskAndReply and Callbacks. |
894 class HostResolverImpl::IPv6ProbeJob | 966 class HostResolverImpl::IPv6ProbeJob |
895 : public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> { | 967 : public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> { |
896 public: | 968 public: |
897 explicit IPv6ProbeJob(HostResolverImpl* resolver) | 969 explicit IPv6ProbeJob(HostResolverImpl* resolver) |
898 : resolver_(resolver), | 970 : resolver_(resolver), |
899 origin_loop_(base::MessageLoopProxy::current()) { | 971 origin_loop_(base::MessageLoopProxy::current()) { |
900 DCHECK(resolver); | 972 DCHECK(resolver); |
901 } | 973 } |
902 | 974 |
903 void Start() { | 975 void Start() { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
951 HostResolverImpl* resolver_; | 1023 HostResolverImpl* resolver_; |
952 | 1024 |
953 // Used to post ourselves onto the origin thread. | 1025 // Used to post ourselves onto the origin thread. |
954 scoped_refptr<base::MessageLoopProxy> origin_loop_; | 1026 scoped_refptr<base::MessageLoopProxy> origin_loop_; |
955 | 1027 |
956 DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); | 1028 DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); |
957 }; | 1029 }; |
958 | 1030 |
959 //----------------------------------------------------------------------------- | 1031 //----------------------------------------------------------------------------- |
960 | 1032 |
| 1033 // Resolves the hostname using DnsTransaction. |
| 1034 // TODO(szym): This could be moved to separate source file as well. |
| 1035 class HostResolverImpl::DnsTask { |
| 1036 public: |
| 1037 typedef base::Callback<void(int net_error, |
| 1038 const AddressList& addr_list, |
| 1039 base::TimeDelta ttl)> Callback; |
| 1040 |
| 1041 DnsTask(DnsTransactionFactory* factory, |
| 1042 const Key& key, |
| 1043 const Callback& callback, |
| 1044 const BoundNetLog& source_net_log) { |
| 1045 DCHECK(factory); |
| 1046 |
| 1047 // For now we treat ADDRESS_FAMILY_UNSPEC as if it was IPV4. |
| 1048 uint16 qtype = (key.address_family == ADDRESS_FAMILY_IPV6) |
| 1049 ? dns_protocol::kTypeAAAA |
| 1050 : dns_protocol::kTypeA; |
| 1051 // TODO(szym): Implement "happy eyeballs". |
| 1052 transaction_ = factory->CreateTransaction( |
| 1053 key.hostname, |
| 1054 qtype, |
| 1055 base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this)), |
| 1056 source_net_log); |
| 1057 DCHECK(transaction_.get()); |
| 1058 } |
| 1059 |
| 1060 int Start() { |
| 1061 return transaction_->Start(); |
| 1062 } |
| 1063 |
| 1064 void OnTransactionComplete(DnsTransaction* transaction, |
| 1065 int net_error, |
| 1066 const DnsResponse* response) { |
| 1067 // TODO(szym): Record performance histograms. |
| 1068 if (net_error == OK) { |
| 1069 AddressList addr_list; |
| 1070 base::TimeDelta ttl; |
| 1071 if (DnsResponseToAddressList(response, &addr_list, &ttl)) { |
| 1072 callback_.Run(net_error, addr_list, ttl); |
| 1073 return; |
| 1074 } |
| 1075 net_error = ERR_DNS_MALFORMED_RESPONSE; |
| 1076 } |
| 1077 callback_.Run(net_error, AddressList(), base::TimeDelta()); |
| 1078 } |
| 1079 |
| 1080 private: |
| 1081 // The listener to the results of this DnsTask. |
| 1082 Callback callback_; |
| 1083 |
| 1084 scoped_ptr<DnsTransaction> transaction_; |
| 1085 }; |
| 1086 |
| 1087 //----------------------------------------------------------------------------- |
| 1088 |
961 // Aggregates all Requests for the same Key. Dispatched via PriorityDispatch. | 1089 // Aggregates all Requests for the same Key. Dispatched via PriorityDispatch. |
962 // Spawns ProcTask when started. | 1090 // Spawns ProcTask when started. |
963 class HostResolverImpl::Job : public PrioritizedDispatcher::Job { | 1091 class HostResolverImpl::Job : public PrioritizedDispatcher::Job { |
964 public: | 1092 public: |
965 // Creates new job for |key| where |request_net_log| is bound to the | 1093 // Creates new job for |key| where |request_net_log| is bound to the |
966 // request that spawned it. | 1094 // request that spawned it. |
967 Job(HostResolverImpl* resolver, | 1095 Job(HostResolverImpl* resolver, |
968 const Key& key, | 1096 const Key& key, |
969 const BoundNetLog& request_net_log) | 1097 const BoundNetLog& request_net_log, |
| 1098 RequestPriority priority) |
970 : resolver_(resolver->AsWeakPtr()), | 1099 : resolver_(resolver->AsWeakPtr()), |
971 key_(key), | 1100 key_(key), |
| 1101 priority_tracker_(priority), |
972 had_non_speculative_request_(false), | 1102 had_non_speculative_request_(false), |
973 net_log_(BoundNetLog::Make(request_net_log.net_log(), | 1103 net_log_(BoundNetLog::Make(request_net_log.net_log(), |
974 NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)), | 1104 NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)), |
975 net_error_(ERR_IO_PENDING), | 1105 net_error_(ERR_IO_PENDING), |
976 os_error_(0) { | 1106 os_error_(0) { |
977 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB, NULL); | 1107 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB, NULL); |
978 | 1108 |
979 net_log_.BeginEvent( | 1109 net_log_.BeginEvent( |
980 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, | 1110 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, |
981 make_scoped_refptr(new JobCreationParameters( | 1111 make_scoped_refptr(new JobCreationParameters( |
(...skipping 20 matching lines...) Expand all Loading... |
1002 DCHECK_EQ(this, req->job()); | 1132 DCHECK_EQ(this, req->job()); |
1003 LogCancelRequest(req->source_net_log(), req->request_net_log(), | 1133 LogCancelRequest(req->source_net_log(), req->request_net_log(), |
1004 req->info()); | 1134 req->info()); |
1005 } | 1135 } |
1006 } | 1136 } |
1007 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, | 1137 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, |
1008 net_error_); | 1138 net_error_); |
1009 STLDeleteElements(&requests_); | 1139 STLDeleteElements(&requests_); |
1010 } | 1140 } |
1011 | 1141 |
1012 HostResolverImpl* resolver() const { | |
1013 return resolver_; | |
1014 } | |
1015 | |
1016 RequestPriority priority() const { | 1142 RequestPriority priority() const { |
1017 return priority_tracker_.highest_priority(); | 1143 return priority_tracker_.highest_priority(); |
1018 } | 1144 } |
1019 | 1145 |
1020 // Number of non-canceled requests in |requests_|. | 1146 // Number of non-canceled requests in |requests_|. |
1021 size_t num_active_requests() const { | 1147 size_t num_active_requests() const { |
1022 return priority_tracker_.total_count(); | 1148 return priority_tracker_.total_count(); |
1023 } | 1149 } |
1024 | 1150 |
1025 const Key& key() const { | 1151 const Key& key() const { |
1026 return key_; | 1152 return key_; |
1027 } | 1153 } |
1028 | 1154 |
1029 int net_error() const { | 1155 int net_error() const { |
1030 return net_error_; | 1156 return net_error_; |
1031 } | 1157 } |
1032 | 1158 |
1033 // Used by HostResolverImpl with |dispatcher_|. | 1159 void AddToDispatcher(PrioritizedDispatcher* dispatcher) { |
1034 const PrioritizedDispatcher::Handle& handle() const { | 1160 DCHECK(handle_.is_null()); |
1035 return handle_; | 1161 handle_ = DispatcherHandle(dispatcher, dispatcher->Add(this, priority())); |
1036 } | 1162 } |
1037 | 1163 |
1038 void set_handle(const PrioritizedDispatcher::Handle& handle) { | 1164 bool IsWaitingInDispatch() const { |
1039 handle_ = handle; | 1165 return !handle_.is_null(); |
1040 } | 1166 } |
1041 | 1167 |
1042 // The Job will own |req| and destroy it in ~Job. | 1168 // The Job will own |req| and destroy it in ~Job. |
1043 void AddRequest(Request* req) { | 1169 void AddRequest(Request* req) { |
1044 DCHECK_EQ(key_.hostname, req->info().hostname()); | 1170 DCHECK_EQ(key_.hostname, req->info().hostname()); |
1045 | 1171 |
1046 req->set_job(this); | 1172 req->set_job(this); |
1047 requests_.push_back(req); | 1173 requests_.push_back(req); |
1048 | 1174 |
1049 priority_tracker_.Add(req->info().priority()); | 1175 priority_tracker_.Add(req->info().priority()); |
1050 | 1176 |
1051 req->request_net_log().AddEvent( | 1177 req->request_net_log().AddEvent( |
1052 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, | 1178 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, |
1053 make_scoped_refptr(new NetLogSourceParameter( | 1179 make_scoped_refptr(new NetLogSourceParameter( |
1054 "source_dependency", net_log_.source()))); | 1180 "source_dependency", net_log_.source()))); |
1055 | 1181 |
1056 net_log_.AddEvent( | 1182 net_log_.AddEvent( |
1057 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_ATTACH, | 1183 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_ATTACH, |
1058 make_scoped_refptr(new JobAttachParameters( | 1184 make_scoped_refptr(new JobAttachParameters( |
1059 req->request_net_log().source(), priority()))); | 1185 req->request_net_log().source(), priority()))); |
1060 | 1186 |
1061 // TODO(szym): Check if this is still needed. | 1187 // TODO(szym): Check if this is still needed. |
1062 if (!req->info().is_speculative()) { | 1188 if (!req->info().is_speculative()) { |
1063 had_non_speculative_request_ = true; | 1189 had_non_speculative_request_ = true; |
1064 if (proc_task_) | 1190 if (proc_task_) |
1065 proc_task_->set_had_non_speculative_request(); | 1191 proc_task_->set_had_non_speculative_request(); |
1066 } | 1192 } |
| 1193 |
| 1194 if (!handle_.is_null()) |
| 1195 handle_.ChangePriority(priority()); |
1067 } | 1196 } |
1068 | 1197 |
1069 void CancelRequest(Request* req) { | 1198 void CancelRequest(Request* req) { |
1070 DCHECK_EQ(key_.hostname, req->info().hostname()); | 1199 DCHECK_EQ(key_.hostname, req->info().hostname()); |
1071 DCHECK(!req->was_canceled()); | 1200 DCHECK(!req->was_canceled()); |
1072 // Don't remove it from |requests_| just mark it canceled. | 1201 // Don't remove it from |requests_| just mark it canceled. |
1073 req->MarkAsCanceled(); | 1202 req->MarkAsCanceled(); |
1074 LogCancelRequest(req->source_net_log(), req->request_net_log(), | 1203 LogCancelRequest(req->source_net_log(), req->request_net_log(), |
1075 req->info()); | 1204 req->info()); |
1076 priority_tracker_.Remove(req->info().priority()); | 1205 priority_tracker_.Remove(req->info().priority()); |
1077 net_log_.AddEvent( | 1206 net_log_.AddEvent( |
1078 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_DETACH, | 1207 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_DETACH, |
1079 make_scoped_refptr(new JobAttachParameters( | 1208 make_scoped_refptr(new JobAttachParameters( |
1080 req->request_net_log().source(), priority()))); | 1209 req->request_net_log().source(), priority()))); |
| 1210 |
| 1211 if (!handle_.is_null()) { |
| 1212 if (num_active_requests() > 0) { |
| 1213 handle_.ChangePriority(priority()); |
| 1214 } else { |
| 1215 handle_.Cancel(); |
| 1216 } |
| 1217 } |
1081 } | 1218 } |
1082 | 1219 |
1083 // Aborts and destroys the job, completes all requests as aborted. | 1220 // Aborts and destroys the job, completes all requests as aborted. |
1084 void Abort() { | 1221 void Abort() { |
1085 // Job should only be aborted if it's running. | 1222 // Job should only be aborted if it's running. |
1086 DCHECK(is_running()); | 1223 DCHECK(is_running()); |
1087 proc_task_->Cancel(); | 1224 if (proc_task_.get()) { |
1088 proc_task_ = NULL; | 1225 proc_task_->Cancel(); |
| 1226 proc_task_ = NULL; |
| 1227 } |
| 1228 dns_task_.reset(); |
1089 net_error_ = ERR_ABORTED; | 1229 net_error_ = ERR_ABORTED; |
1090 os_error_ = 0; | 1230 os_error_ = 0; |
1091 CompleteRequests(AddressList()); | 1231 CompleteRequests(AddressList(), base::TimeDelta()); |
| 1232 } |
| 1233 |
| 1234 bool is_dns_running() const { |
| 1235 return dns_task_.get() != NULL; |
| 1236 } |
| 1237 |
| 1238 bool is_proc_running() const { |
| 1239 return proc_task_.get() != NULL; |
1092 } | 1240 } |
1093 | 1241 |
1094 bool is_running() const { | 1242 bool is_running() const { |
1095 return proc_task_.get() != NULL; | 1243 return is_dns_running() || is_proc_running(); |
1096 } | 1244 } |
1097 | 1245 |
1098 // Called by HostResolverImpl when this job is evicted due to queue overflow. | 1246 // Called by HostResolverImpl when this job is evicted due to queue overflow. |
1099 void OnEvicted() { | 1247 void OnEvicted() { |
1100 // Must not be running. | 1248 // Must not be running. |
1101 DCHECK(!is_running()); | 1249 DCHECK(!is_running()); |
1102 handle_ = PrioritizedDispatcher::Handle(); | 1250 handle_.Reset(); |
1103 | 1251 |
1104 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED, NULL); | 1252 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED, NULL); |
1105 | 1253 |
1106 // This signals to CompleteRequests that this job never ran. | 1254 // This signals to CompleteRequests that this job never ran. |
1107 net_error_ = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; | 1255 net_error_ = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; |
1108 os_error_ = 0; | 1256 os_error_ = 0; |
1109 CompleteRequests(AddressList()); | 1257 CompleteRequests(AddressList(), base::TimeDelta()); |
1110 } | 1258 } |
1111 | 1259 |
1112 // PriorityDispatch::Job interface. | 1260 // PriorityDispatch::Job interface. |
1113 virtual void Start() OVERRIDE { | 1261 virtual void Start() OVERRIDE { |
1114 DCHECK(!is_running()); | 1262 DCHECK(!is_running()); |
1115 handle_ = PrioritizedDispatcher::Handle(); | 1263 handle_.Reset(); |
1116 | 1264 |
1117 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED, NULL); | 1265 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED, NULL); |
1118 | 1266 |
| 1267 if (resolver_->dns_transaction_factory_.get()) { |
| 1268 StartDnsTask(); |
| 1269 } else { |
| 1270 StartProcTask(); |
| 1271 } |
| 1272 } |
| 1273 |
| 1274 private: |
| 1275 void StartProcTask() { |
1119 proc_task_ = new ProcTask( | 1276 proc_task_ = new ProcTask( |
1120 key_, | 1277 key_, |
1121 resolver_->proc_params_, | 1278 resolver_->proc_params_, |
1122 base::Bind(&Job::OnProcTaskComplete, base::Unretained(this)), | 1279 base::Bind(&Job::OnProcTaskComplete, base::Unretained(this)), |
1123 net_log_); | 1280 net_log_); |
1124 | 1281 |
1125 if (had_non_speculative_request_) | 1282 if (had_non_speculative_request_) |
1126 proc_task_->set_had_non_speculative_request(); | 1283 proc_task_->set_had_non_speculative_request(); |
1127 // Start() could be called from within Resolve(), hence it must NOT directly | 1284 // Start() could be called from within Resolve(), hence it must NOT directly |
1128 // call OnProcTaskComplete, for example, on synchronous failure. | 1285 // call OnProcTaskComplete, for example, on synchronous failure. |
1129 proc_task_->Start(); | 1286 proc_task_->Start(); |
1130 } | 1287 } |
1131 | 1288 |
1132 private: | 1289 void StartDnsTask() { |
| 1290 dns_task_.reset(new DnsTask( |
| 1291 resolver_->dns_transaction_factory_.get(), |
| 1292 key_, |
| 1293 base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this)), |
| 1294 net_log_)); |
| 1295 |
| 1296 int rv = dns_task_->Start(); |
| 1297 if (rv != ERR_IO_PENDING) { |
| 1298 DCHECK_NE(OK, rv); |
| 1299 // TODO(szym): AddToDispatcher(resolver_->proc_dispatcher_); |
| 1300 StartProcTask(); |
| 1301 } |
| 1302 } |
| 1303 |
1133 // Called by ProcTask when it completes. | 1304 // Called by ProcTask when it completes. |
1134 void OnProcTaskComplete(int net_error, int os_error, | 1305 void OnProcTaskComplete(int net_error, int os_error, |
1135 const AddressList& addrlist) { | 1306 const AddressList& addr_list) { |
1136 DCHECK(is_running()); | 1307 DCHECK(is_proc_running()); |
1137 proc_task_ = NULL; | 1308 proc_task_ = NULL; |
1138 net_error_ = net_error; | 1309 net_error_ = net_error; |
1139 os_error_ = os_error; | 1310 os_error_ = os_error; |
1140 | 1311 |
1141 // We are the only consumer of |addrlist|, so we can safely change the port | 1312 base::TimeDelta ttl = base::TimeDelta::FromSeconds(0); |
1142 // without copy-on-write. This pays off, when job has only one request. | 1313 if (net_error == OK) |
1143 AddressList list = addrlist; | 1314 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); |
1144 if (net_error == OK && !requests_.empty()) | 1315 CompleteRequests(addr_list, ttl); |
1145 MutableSetPort(requests_.front()->info().port(), &list); | 1316 } |
1146 CompleteRequests(list); | 1317 |
| 1318 // Called by DnsTask when it completes. |
| 1319 void OnDnsTaskComplete(int net_error, |
| 1320 const AddressList& addr_list, |
| 1321 base::TimeDelta ttl) { |
| 1322 DCHECK(is_dns_running()); |
| 1323 dns_task_.reset(); |
| 1324 |
| 1325 if (net_error != OK) { |
| 1326 // TODO(szym): Some net errors indicate lack of connectivity. Starting |
| 1327 // ProcTask in that case is a waste of time. |
| 1328 StartProcTask(); |
| 1329 return; |
| 1330 } |
| 1331 |
| 1332 net_error_ = OK; |
| 1333 os_error_ = 0; |
| 1334 CompleteRequests(addr_list, ttl); |
1147 } | 1335 } |
1148 | 1336 |
1149 // Completes all Requests. Calls OnJobFinished and deletes self. | 1337 // Completes all Requests. Calls OnJobFinished and deletes self. |
1150 void CompleteRequests(const AddressList& addrlist) { | 1338 void CompleteRequests(const AddressList& addr_list, base::TimeDelta ttl) { |
1151 CHECK(resolver_); | 1339 CHECK(resolver_); |
1152 | 1340 |
| 1341 // We are the only consumer of |addr_list|, so we can safely change the port |
| 1342 // without copy-on-write. This pays off, when job has only one request. |
| 1343 AddressList list = addr_list; |
| 1344 if (net_error_ == OK && !requests_.empty()) |
| 1345 MutableSetPort(requests_.front()->info().port(), &list); |
| 1346 |
1153 // This job must be removed from resolver's |jobs_| now to make room for a | 1347 // This job must be removed from resolver's |jobs_| now to make room for a |
1154 // new job with the same key in case one of the OnComplete callbacks decides | 1348 // new job with the same key in case one of the OnComplete callbacks decides |
1155 // to spawn one. Consequently, the job deletes itself when CompleteRequests | 1349 // to spawn one. Consequently, the job deletes itself when CompleteRequests |
1156 // is done. | 1350 // is done. |
1157 scoped_ptr<Job> self_deleter(this); | 1351 scoped_ptr<Job> self_deleter(this); |
1158 resolver_->OnJobFinished(this, addrlist); | 1352 resolver_->OnJobFinished(this, addr_list, ttl); |
1159 | 1353 |
1160 // Complete all of the requests that were attached to the job. | 1354 // Complete all of the requests that were attached to the job. |
1161 for (RequestsList::const_iterator it = requests_.begin(); | 1355 for (RequestsList::const_iterator it = requests_.begin(); |
1162 it != requests_.end(); ++it) { | 1356 it != requests_.end(); ++it) { |
1163 Request* req = *it; | 1357 Request* req = *it; |
1164 | 1358 |
1165 if (req->was_canceled()) | 1359 if (req->was_canceled()) |
1166 continue; | 1360 continue; |
1167 | 1361 |
1168 DCHECK_EQ(this, req->job()); | 1362 DCHECK_EQ(this, req->job()); |
1169 // Update the net log and notify registered observers. | 1363 // Update the net log and notify registered observers. |
1170 LogFinishRequest(req->source_net_log(), req->request_net_log(), | 1364 LogFinishRequest(req->source_net_log(), req->request_net_log(), |
1171 req->info(), net_error_, os_error_); | 1365 req->info(), net_error_, os_error_); |
1172 | 1366 |
1173 req->OnComplete(net_error_, addrlist); | 1367 req->OnComplete(net_error_, addr_list); |
1174 | 1368 |
1175 // Check if the resolver was destroyed as a result of running the | 1369 // Check if the resolver was destroyed as a result of running the |
1176 // callback. If it was, we could continue, but we choose to bail. | 1370 // callback. If it was, we could continue, but we choose to bail. |
1177 if (!resolver_) | 1371 if (!resolver_) |
1178 return; | 1372 return; |
1179 } | 1373 } |
1180 } | 1374 } |
1181 | 1375 |
1182 // Used to call OnJobFinished and RemoveJob. | 1376 // Used to call OnJobFinished. |
1183 base::WeakPtr<HostResolverImpl> resolver_; | 1377 base::WeakPtr<HostResolverImpl> resolver_; |
1184 | 1378 |
1185 Key key_; | 1379 Key key_; |
1186 | 1380 |
1187 // Tracks the highest priority across |requests_|. | 1381 // Tracks the highest priority across |requests_|. |
1188 PriorityTracker priority_tracker_; | 1382 PriorityTracker priority_tracker_; |
1189 | 1383 |
1190 bool had_non_speculative_request_; | 1384 bool had_non_speculative_request_; |
1191 | 1385 |
1192 BoundNetLog net_log_; | 1386 BoundNetLog net_log_; |
1193 | 1387 |
1194 // Store result here in case the job fails fast in Resolve(). | 1388 // Store result here in case the job fails fast in Resolve(). |
1195 int net_error_; | 1389 int net_error_; |
1196 int os_error_; | 1390 int os_error_; |
1197 | 1391 |
1198 // A ProcTask created and started when this Job is dispatched.. | 1392 // Resolves the host using a HostResolverProc. |
1199 scoped_refptr<ProcTask> proc_task_; | 1393 scoped_refptr<ProcTask> proc_task_; |
1200 | 1394 |
| 1395 // Resolves the host using a DnsTransaction. |
| 1396 scoped_ptr<DnsTask> dns_task_; |
| 1397 |
1201 // All Requests waiting for the result of this Job. Some can be canceled. | 1398 // All Requests waiting for the result of this Job. Some can be canceled. |
1202 RequestsList requests_; | 1399 RequestsList requests_; |
1203 | 1400 |
1204 // A handle used by HostResolverImpl in |dispatcher_|. | 1401 // A handle used by HostResolverImpl in |dispatcher_|. |
1205 PrioritizedDispatcher::Handle handle_; | 1402 DispatcherHandle handle_; |
1206 }; | 1403 }; |
1207 | 1404 |
1208 //----------------------------------------------------------------------------- | 1405 //----------------------------------------------------------------------------- |
1209 | 1406 |
1210 HostResolverImpl::ProcTaskParams::ProcTaskParams( | 1407 HostResolverImpl::ProcTaskParams::ProcTaskParams( |
1211 HostResolverProc* resolver_proc, | 1408 HostResolverProc* resolver_proc, |
1212 size_t max_retry_attempts) | 1409 size_t max_retry_attempts) |
1213 : resolver_proc(resolver_proc), | 1410 : resolver_proc(resolver_proc), |
1214 max_retry_attempts(max_retry_attempts), | 1411 max_retry_attempts(max_retry_attempts), |
1215 unresponsive_delay(base::TimeDelta::FromMilliseconds(6000)), | 1412 unresponsive_delay(base::TimeDelta::FromMilliseconds(6000)), |
1216 retry_factor(2) { | 1413 retry_factor(2) { |
1217 } | 1414 } |
1218 | 1415 |
1219 HostResolverImpl::ProcTaskParams::~ProcTaskParams() {} | 1416 HostResolverImpl::ProcTaskParams::~ProcTaskParams() {} |
1220 | 1417 |
1221 HostResolverImpl::HostResolverImpl( | 1418 HostResolverImpl::HostResolverImpl( |
1222 HostCache* cache, | 1419 HostCache* cache, |
1223 const PrioritizedDispatcher::Limits& job_limits, | 1420 const PrioritizedDispatcher::Limits& job_limits, |
| 1421 const PrioritizedDispatcher::Limits& proc_limits, |
1224 const ProcTaskParams& proc_params, | 1422 const ProcTaskParams& proc_params, |
| 1423 scoped_ptr<DnsConfigService> dns_config_service, |
1225 NetLog* net_log) | 1424 NetLog* net_log) |
1226 : cache_(cache), | 1425 : cache_(cache), |
1227 dispatcher_(job_limits), | 1426 dispatcher_(job_limits), |
| 1427 proc_dispatcher_(proc_limits), |
1228 max_queued_jobs_(job_limits.total_jobs * 100u), | 1428 max_queued_jobs_(job_limits.total_jobs * 100u), |
1229 proc_params_(proc_params), | 1429 proc_params_(proc_params), |
1230 default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), | 1430 default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), |
| 1431 dns_config_service_(dns_config_service.Pass()), |
1231 ipv6_probe_monitoring_(false), | 1432 ipv6_probe_monitoring_(false), |
1232 additional_resolver_flags_(0), | 1433 additional_resolver_flags_(0), |
1233 net_log_(net_log) { | 1434 net_log_(net_log) { |
1234 | 1435 |
1235 DCHECK_GE(dispatcher_.num_priorities(), static_cast<size_t>(NUM_PRIORITIES)); | 1436 DCHECK_GE(dispatcher_.num_priorities(), static_cast<size_t>(NUM_PRIORITIES)); |
| 1437 DCHECK_EQ(proc_dispatcher_.num_priorities(), dispatcher_.num_priorities()); |
1236 | 1438 |
1237 // Maximum of 4 retry attempts for host resolution. | 1439 // Maximum of 4 retry attempts for host resolution. |
1238 static const size_t kDefaultMaxRetryAttempts = 4u; | 1440 static const size_t kDefaultMaxRetryAttempts = 4u; |
1239 | 1441 |
1240 if (proc_params_.max_retry_attempts == HostResolver::kDefaultRetryAttempts) | 1442 if (proc_params_.max_retry_attempts == HostResolver::kDefaultRetryAttempts) |
1241 proc_params_.max_retry_attempts = kDefaultMaxRetryAttempts; | 1443 proc_params_.max_retry_attempts = kDefaultMaxRetryAttempts; |
1242 | 1444 |
1243 #if defined(OS_WIN) | 1445 #if defined(OS_WIN) |
1244 EnsureWinsockInit(); | 1446 EnsureWinsockInit(); |
1245 #endif | 1447 #endif |
1246 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 1448 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
1247 if (HaveOnlyLoopbackAddresses()) | 1449 if (HaveOnlyLoopbackAddresses()) |
1248 additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; | 1450 additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; |
1249 #endif | 1451 #endif |
1250 NetworkChangeNotifier::AddIPAddressObserver(this); | 1452 NetworkChangeNotifier::AddIPAddressObserver(this); |
1251 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) | 1453 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) |
1252 #if !defined(OS_ANDROID) | 1454 #if !defined(OS_ANDROID) |
1253 EnsureDnsReloaderInit(); | 1455 EnsureDnsReloaderInit(); |
1254 #endif | 1456 #endif |
1255 NetworkChangeNotifier::AddDNSObserver(this); | 1457 NetworkChangeNotifier::AddDNSObserver(this); |
1256 #endif | 1458 #endif |
| 1459 |
| 1460 if (dns_config_service_.get()) |
| 1461 dns_config_service_->AddObserver(this); |
1257 } | 1462 } |
1258 | 1463 |
1259 HostResolverImpl::~HostResolverImpl() { | 1464 HostResolverImpl::~HostResolverImpl() { |
1260 DiscardIPv6ProbeJob(); | 1465 DiscardIPv6ProbeJob(); |
1261 | 1466 |
1262 // This will also cancel all outstanding requests. | 1467 // This will also cancel all outstanding requests. |
1263 STLDeleteValues(&jobs_); | 1468 STLDeleteValues(&jobs_); |
1264 | 1469 |
1265 NetworkChangeNotifier::RemoveIPAddressObserver(this); | 1470 NetworkChangeNotifier::RemoveIPAddressObserver(this); |
1266 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) | 1471 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1300 return rv; | 1505 return rv; |
1301 } | 1506 } |
1302 | 1507 |
1303 // Next we need to attach our request to a "job". This job is responsible for | 1508 // Next we need to attach our request to a "job". This job is responsible for |
1304 // calling "getaddrinfo(hostname)" on a worker thread. | 1509 // calling "getaddrinfo(hostname)" on a worker thread. |
1305 | 1510 |
1306 JobMap::iterator jobit = jobs_.find(key); | 1511 JobMap::iterator jobit = jobs_.find(key); |
1307 Job* job; | 1512 Job* job; |
1308 if (jobit == jobs_.end()) { | 1513 if (jobit == jobs_.end()) { |
1309 // Create new Job. | 1514 // Create new Job. |
1310 job = new Job(this, key, request_net_log); | 1515 job = new Job(this, key, request_net_log, info.priority()); |
1311 job->set_handle(dispatcher_.Add(job, info.priority())); | 1516 job->AddToDispatcher(&dispatcher_); |
1312 | 1517 |
1313 // Check for queue overflow. | 1518 // Check for queue overflow. |
1314 if (dispatcher_.num_queued_jobs() > max_queued_jobs_) { | 1519 if (dispatcher_.num_queued_jobs() > max_queued_jobs_) { |
1315 Job* evicted = static_cast<Job*>(dispatcher_.EvictOldestLowest()); | 1520 Job* evicted = static_cast<Job*>(dispatcher_.EvictOldestLowest()); |
1316 DCHECK(evicted); | 1521 DCHECK(evicted); |
1317 if (evicted == job) { | 1522 if (evicted == job) { |
1318 delete job; | 1523 delete job; |
1319 rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; | 1524 rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; |
1320 LogFinishRequest(source_net_log, request_net_log, info, rv, 0); | 1525 LogFinishRequest(source_net_log, request_net_log, info, rv, 0); |
1321 return rv; | 1526 return rv; |
1322 } | 1527 } |
1323 evicted->OnEvicted(); // Deletes |evicted|. | 1528 evicted->OnEvicted(); // Deletes |evicted|. |
1324 } | 1529 } |
1325 | 1530 |
1326 jobs_.insert(jobit, std::make_pair(key, job)); | 1531 jobs_.insert(jobit, std::make_pair(key, job)); |
1327 } else { | 1532 } else { |
1328 job = jobit->second; | 1533 job = jobit->second; |
1329 } | 1534 } |
1330 | 1535 |
1331 // Can't complete synchronously. Create and attach request. | 1536 // Can't complete synchronously. Create and attach request. |
1332 Request* req = new Request(source_net_log, request_net_log, info, callback, | 1537 Request* req = new Request(source_net_log, request_net_log, info, callback, |
1333 addresses); | 1538 addresses); |
1334 job->AddRequest(req); | 1539 job->AddRequest(req); |
1335 if (!job->handle().is_null()) | |
1336 job->set_handle(dispatcher_.ChangePriority(job->handle(), job->priority())); | |
1337 if (out_req) | 1540 if (out_req) |
1338 *out_req = reinterpret_cast<RequestHandle>(req); | 1541 *out_req = reinterpret_cast<RequestHandle>(req); |
1339 | 1542 |
1340 DCHECK_EQ(ERR_IO_PENDING, job->net_error()); | 1543 DCHECK_EQ(ERR_IO_PENDING, job->net_error()); |
1341 // Completion happens during Job::CompleteRequests(). | 1544 // Completion happens during Job::CompleteRequests(). |
1342 return ERR_IO_PENDING; | 1545 return ERR_IO_PENDING; |
1343 } | 1546 } |
1344 | 1547 |
1345 int HostResolverImpl::ResolveHelper(const Key& key, | 1548 int HostResolverImpl::ResolveHelper(const Key& key, |
1346 const RequestInfo& info, | 1549 const RequestInfo& info, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1384 void HostResolverImpl::CancelRequest(RequestHandle req_handle) { | 1587 void HostResolverImpl::CancelRequest(RequestHandle req_handle) { |
1385 DCHECK(CalledOnValidThread()); | 1588 DCHECK(CalledOnValidThread()); |
1386 Request* req = reinterpret_cast<Request*>(req_handle); | 1589 Request* req = reinterpret_cast<Request*>(req_handle); |
1387 DCHECK(req); | 1590 DCHECK(req); |
1388 | 1591 |
1389 Job* job = req->job(); | 1592 Job* job = req->job(); |
1390 DCHECK(job); | 1593 DCHECK(job); |
1391 | 1594 |
1392 job->CancelRequest(req); | 1595 job->CancelRequest(req); |
1393 | 1596 |
1394 if (!job->handle().is_null()) { | 1597 if (job->num_active_requests() == 0) { |
1395 // Still in queue. | 1598 if (job->is_running()) { |
1396 if (job->num_active_requests()) { | 1599 // Job is running (and could be in CompleteRequests right now). |
1397 job->set_handle(dispatcher_.ChangePriority(job->handle(), | 1600 // But to be in Request::OnComplete we would have to have a non-canceled |
1398 job->priority())); | 1601 // request. So it is safe to Abort it if it has no more active requests. |
| 1602 job->Abort(); |
1399 } else { | 1603 } else { |
1400 dispatcher_.Cancel(job->handle()); | |
1401 RemoveJob(job); | 1604 RemoveJob(job); |
1402 delete job; | 1605 delete job; |
1403 } | 1606 } |
1404 } else { | |
1405 // Job is running (and could be in CompleteRequests right now). | |
1406 // But to be in Request::OnComplete we would have to have a non-canceled | |
1407 // request. So it is safe to Abort it if it has no more active requests. | |
1408 if (!job->num_active_requests()) { | |
1409 job->Abort(); | |
1410 } | |
1411 } | 1607 } |
1412 } | 1608 } |
1413 | 1609 |
1414 void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) { | 1610 void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) { |
1415 DCHECK(CalledOnValidThread()); | 1611 DCHECK(CalledOnValidThread()); |
1416 ipv6_probe_monitoring_ = false; | 1612 ipv6_probe_monitoring_ = false; |
1417 DiscardIPv6ProbeJob(); | 1613 DiscardIPv6ProbeJob(); |
1418 default_address_family_ = address_family; | 1614 default_address_family_ = address_family; |
1419 } | 1615 } |
1420 | 1616 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1475 if (!cache_entry) | 1671 if (!cache_entry) |
1476 return false; | 1672 return false; |
1477 | 1673 |
1478 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL); | 1674 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL); |
1479 *net_error = cache_entry->error; | 1675 *net_error = cache_entry->error; |
1480 if (*net_error == OK) | 1676 if (*net_error == OK) |
1481 *addresses = CreateAddressListUsingPort(cache_entry->addrlist, info.port()); | 1677 *addresses = CreateAddressListUsingPort(cache_entry->addrlist, info.port()); |
1482 return true; | 1678 return true; |
1483 } | 1679 } |
1484 | 1680 |
1485 void HostResolverImpl::OnJobFinished(Job* job, const AddressList& addrlist) { | 1681 void HostResolverImpl::OnJobFinished(Job* job, |
| 1682 const AddressList& addrlist, |
| 1683 base::TimeDelta ttl) { |
1486 DCHECK(job); | 1684 DCHECK(job); |
1487 DCHECK(job->handle().is_null()); | 1685 DCHECK(!job->IsWaitingInDispatch()); |
1488 RemoveJob(job); | 1686 RemoveJob(job); |
1489 if (job->net_error() == ERR_HOST_RESOLVER_QUEUE_TOO_LARGE) | 1687 if (job->net_error() == ERR_HOST_RESOLVER_QUEUE_TOO_LARGE) |
1490 return; | 1688 return; |
1491 | 1689 |
1492 // Signal dispatcher that a slot has opened. | 1690 // Signal dispatcher that a slot has opened. |
1493 dispatcher_.OnJobFinished(); | 1691 dispatcher_.OnJobFinished(); |
1494 if (job->net_error() == ERR_ABORTED) | 1692 if (job->net_error() == ERR_ABORTED) |
1495 return; | 1693 return; |
1496 // Write result to the cache. | 1694 // Write result to the cache. |
1497 if (cache_.get()) { | 1695 if (cache_.get()) { |
1498 base::TimeDelta ttl = base::TimeDelta::FromSeconds(0); | |
1499 if (job->net_error() == OK) | |
1500 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); | |
1501 cache_->Set(job->key(), job->net_error(), addrlist, | 1696 cache_->Set(job->key(), job->net_error(), addrlist, |
1502 base::TimeTicks::Now(), ttl); | 1697 base::TimeTicks::Now(), ttl); |
1503 } | 1698 } |
1504 } | 1699 } |
1505 | 1700 |
1506 void HostResolverImpl::RemoveJob(Job* job) { | 1701 void HostResolverImpl::RemoveJob(Job* job) { |
1507 DCHECK(job); | 1702 DCHECK(job); |
1508 jobs_.erase(job->key()); | 1703 jobs_.erase(job->key()); |
1509 } | 1704 } |
1510 | 1705 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1550 Job* job = it->second; | 1745 Job* job = it->second; |
1551 // Advance the iterator before we might erase it. | 1746 // Advance the iterator before we might erase it. |
1552 ++it; | 1747 ++it; |
1553 if (job->is_running()) { | 1748 if (job->is_running()) { |
1554 job->Abort(); | 1749 job->Abort(); |
1555 // Check if resolver was deleted in a request callback. | 1750 // Check if resolver was deleted in a request callback. |
1556 if (!self) | 1751 if (!self) |
1557 return; | 1752 return; |
1558 } else { | 1753 } else { |
1559 // Keep it in |dispatch_|. | 1754 // Keep it in |dispatch_|. |
1560 DCHECK(!job->handle().is_null()); | 1755 DCHECK(job->IsWaitingInDispatch()); |
1561 } | 1756 } |
1562 } | 1757 } |
1563 } | 1758 } |
1564 | 1759 |
1565 void HostResolverImpl::OnIPAddressChanged() { | 1760 void HostResolverImpl::OnIPAddressChanged() { |
1566 if (cache_.get()) | 1761 if (cache_.get()) |
1567 cache_->clear(); | 1762 cache_->clear(); |
1568 if (ipv6_probe_monitoring_) { | 1763 if (ipv6_probe_monitoring_) { |
1569 DiscardIPv6ProbeJob(); | 1764 DiscardIPv6ProbeJob(); |
1570 ipv6_probe_job_ = new IPv6ProbeJob(this); | 1765 ipv6_probe_job_ = new IPv6ProbeJob(this); |
(...skipping 16 matching lines...) Expand all Loading... |
1587 // as NSCD's cache should be dropped automatically by the OS when | 1782 // as NSCD's cache should be dropped automatically by the OS when |
1588 // resolv.conf changes so we don't need to do anything to clear that cache. | 1783 // resolv.conf changes so we don't need to do anything to clear that cache. |
1589 if (cache_.get()) | 1784 if (cache_.get()) |
1590 cache_->clear(); | 1785 cache_->clear(); |
1591 // Existing jobs will have been sent to the original server so they need to | 1786 // Existing jobs will have been sent to the original server so they need to |
1592 // be aborted. TODO(Craig): Should these jobs be restarted? | 1787 // be aborted. TODO(Craig): Should these jobs be restarted? |
1593 AbortAllInProgressJobs(); | 1788 AbortAllInProgressJobs(); |
1594 // |this| may be deleted inside AbortAllInProgressJobs(). | 1789 // |this| may be deleted inside AbortAllInProgressJobs(). |
1595 } | 1790 } |
1596 | 1791 |
| 1792 void HostResolverImpl::OnConfigChanged(const DnsConfig& dns_config) { |
| 1793 // We want a new factory in place, before we Abort running Jobs, so that the |
| 1794 // newly started jobs use the new factory. |
| 1795 bool had_factory = (dns_transaction_factory_.get() != NULL); |
| 1796 if (dns_config.IsValid()) { |
| 1797 dns_transaction_factory_ = DnsTransactionFactory::CreateFactory( |
| 1798 new DnsSession(dns_config, |
| 1799 ClientSocketFactory::GetDefaultFactory(), |
| 1800 base::Bind(&base::RandInt), |
| 1801 net_log_)); |
| 1802 } else { |
| 1803 dns_transaction_factory_.reset(); |
| 1804 } |
| 1805 if (had_factory) { |
| 1806 OnDNSChanged(); |
| 1807 } |
| 1808 } |
| 1809 |
1597 } // namespace net | 1810 } // namespace net |
OLD | NEW |