| 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 |
| 51 // some platform's resolvers. | 59 // some platform's resolvers. |
| 52 const size_t kMaxHostLength = 4096; | 60 const size_t kMaxHostLength = 4096; |
| 53 | 61 |
| 54 // Default TTL for successful resolutions with ProcTask. | 62 // Default TTL for successful resolutions with ProcTask. |
| 55 const unsigned kCacheEntryTTLSeconds = 60; | 63 const unsigned kCacheEntryTTLSeconds = 60; |
| 56 | 64 |
| 65 // Default TTL for unsuccessful resolutions with ProcTask. |
| 66 const unsigned kNegativeCacheEntryTTLSeconds = 0; |
| 67 |
| 57 // Maximum of 8 concurrent resolver threads (excluding retries). | 68 // Maximum of 8 concurrent resolver threads (excluding retries). |
| 58 // Some routers (or resolvers) appear to start to provide host-not-found if | 69 // Some routers (or resolvers) appear to start to provide host-not-found if |
| 59 // too many simultaneous resolutions are pending. This number needs to be | 70 // too many simultaneous resolutions are pending. This number needs to be |
| 60 // further optimized, but 8 is what FF currently does. | 71 // further optimized, but 8 is what FF currently does. |
| 61 static const size_t kDefaultMaxProcTasks = 8u; | 72 static const size_t kDefaultMaxProcTasks = 8u; |
| 62 | 73 |
| 63 // Helper to mutate the linked list contained by AddressList to the given | 74 // Helper to mutate the linked list contained by AddressList to the given |
| 64 // port. Note that in general this is dangerous since the AddressList's | 75 // port. Note that in general this is dangerous since the AddressList's |
| 65 // data might be shared (and you should use AddressList::SetPort). | 76 // data might be shared (and you should use AddressList::SetPort). |
| 66 // | 77 // |
| 67 // However since we allocated the AddressList ourselves we can safely | 78 // However since we allocated the AddressList ourselves we can safely |
| 68 // do this optimization and avoid reallocating the list. | 79 // do this optimization and avoid reallocating the list. |
| 69 void MutableSetPort(int port, AddressList* addrlist) { | 80 void MutableSetPort(int port, AddressList* addr_list) { |
| 70 struct addrinfo* mutable_head = | 81 struct addrinfo* mutable_head = |
| 71 const_cast<struct addrinfo*>(addrlist->head()); | 82 const_cast<struct addrinfo*>(addr_list->head()); |
| 72 SetPortForAllAddrinfos(mutable_head, port); | 83 SetPortForAllAddrinfos(mutable_head, port); |
| 73 } | 84 } |
| 74 | 85 |
| 75 // We use a separate histogram name for each platform to facilitate the | 86 // We use a separate histogram name for each platform to facilitate the |
| 76 // display of error codes by their symbolic name (since each platform has | 87 // display of error codes by their symbolic name (since each platform has |
| 77 // different mappings). | 88 // different mappings). |
| 78 const char kOSErrorsForGetAddrinfoHistogramName[] = | 89 const char kOSErrorsForGetAddrinfoHistogramName[] = |
| 79 #if defined(OS_WIN) | 90 #if defined(OS_WIN) |
| 80 "Net.OSErrorsForGetAddrinfo_Win"; | 91 "Net.OSErrorsForGetAddrinfo_Win"; |
| 81 #elif defined(OS_MACOSX) | 92 #elif defined(OS_MACOSX) |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 } | 148 } |
| 138 | 149 |
| 139 // Wraps call to SystemHostResolverProc as an instance of HostResolverProc. | 150 // Wraps call to SystemHostResolverProc as an instance of HostResolverProc. |
| 140 // TODO(szym): This should probably be declared in host_resolver_proc.h. | 151 // TODO(szym): This should probably be declared in host_resolver_proc.h. |
| 141 class CallSystemHostResolverProc : public HostResolverProc { | 152 class CallSystemHostResolverProc : public HostResolverProc { |
| 142 public: | 153 public: |
| 143 CallSystemHostResolverProc() : HostResolverProc(NULL) {} | 154 CallSystemHostResolverProc() : HostResolverProc(NULL) {} |
| 144 virtual int Resolve(const std::string& hostname, | 155 virtual int Resolve(const std::string& hostname, |
| 145 AddressFamily address_family, | 156 AddressFamily address_family, |
| 146 HostResolverFlags host_resolver_flags, | 157 HostResolverFlags host_resolver_flags, |
| 147 AddressList* addrlist, | 158 AddressList* addr_list, |
| 148 int* os_error) OVERRIDE { | 159 int* os_error) OVERRIDE { |
| 149 return SystemHostResolverProc(hostname, | 160 return SystemHostResolverProc(hostname, |
| 150 address_family, | 161 address_family, |
| 151 host_resolver_flags, | 162 host_resolver_flags, |
| 152 addrlist, | 163 addr_list, |
| 153 os_error); | 164 os_error); |
| 154 } | 165 } |
| 155 }; | 166 }; |
| 156 | 167 |
| 157 // Extra parameters to attach to the NetLog when the resolve failed. | 168 // Extra parameters to attach to the NetLog when the resolve failed. |
| 158 class HostResolveFailedParams : public NetLog::EventParameters { | 169 class ProcTaskFailedParams : public NetLog::EventParameters { |
| 159 public: | 170 public: |
| 160 HostResolveFailedParams(uint32 attempt_number, | 171 ProcTaskFailedParams(uint32 attempt_number, int net_error, int os_error) |
| 161 int net_error, | |
| 162 int os_error) | |
| 163 : attempt_number_(attempt_number), | 172 : attempt_number_(attempt_number), |
| 164 net_error_(net_error), | 173 net_error_(net_error), |
| 165 os_error_(os_error) { | 174 os_error_(os_error) { |
| 166 } | 175 } |
| 167 | 176 |
| 168 virtual Value* ToValue() const OVERRIDE { | 177 virtual Value* ToValue() const OVERRIDE { |
| 169 DictionaryValue* dict = new DictionaryValue(); | 178 DictionaryValue* dict = new DictionaryValue(); |
| 170 if (attempt_number_) | 179 if (attempt_number_) |
| 171 dict->SetInteger("attempt_number", attempt_number_); | 180 dict->SetInteger("attempt_number", attempt_number_); |
| 172 | 181 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 194 | 203 |
| 195 return dict; | 204 return dict; |
| 196 } | 205 } |
| 197 | 206 |
| 198 private: | 207 private: |
| 199 const uint32 attempt_number_; | 208 const uint32 attempt_number_; |
| 200 const int net_error_; | 209 const int net_error_; |
| 201 const int os_error_; | 210 const int os_error_; |
| 202 }; | 211 }; |
| 203 | 212 |
| 213 // Extra parameters to attach to the NetLog when the DnsTask failed. |
| 214 class DnsTaskFailedParams : public NetLog::EventParameters { |
| 215 public: |
| 216 DnsTaskFailedParams(int net_error, int dns_error) |
| 217 : net_error_(net_error), dns_error_(dns_error) { |
| 218 } |
| 219 |
| 220 virtual Value* ToValue() const OVERRIDE { |
| 221 DictionaryValue* dict = new DictionaryValue(); |
| 222 dict->SetInteger("net_error", net_error_); |
| 223 if (dns_error_) |
| 224 dict->SetInteger("dns_error", dns_error_); |
| 225 return dict; |
| 226 } |
| 227 |
| 228 private: |
| 229 const int net_error_; |
| 230 const int dns_error_; |
| 231 }; |
| 232 |
| 204 // Parameters representing the information in a RequestInfo object, along with | 233 // Parameters representing the information in a RequestInfo object, along with |
| 205 // the associated NetLog::Source. | 234 // the associated NetLog::Source. |
| 206 class RequestInfoParameters : public NetLog::EventParameters { | 235 class RequestInfoParameters : public NetLog::EventParameters { |
| 207 public: | 236 public: |
| 208 RequestInfoParameters(const HostResolver::RequestInfo& info, | 237 RequestInfoParameters(const HostResolver::RequestInfo& info, |
| 209 const NetLog::Source& source) | 238 const NetLog::Source& source) |
| 210 : info_(info), source_(source) {} | 239 : info_(info), source_(source) {} |
| 211 | 240 |
| 212 virtual Value* ToValue() const OVERRIDE { | 241 virtual Value* ToValue() const OVERRIDE { |
| 213 DictionaryValue* dict = new DictionaryValue(); | 242 DictionaryValue* dict = new DictionaryValue(); |
| 214 dict->SetString("host", info_.host_port_pair().ToString()); | 243 dict->SetString("host", info_.host_port_pair().ToString()); |
| 215 dict->SetInteger("address_family", | 244 dict->SetInteger("address_family", |
| 216 static_cast<int>(info_.address_family())); | 245 static_cast<int>(info_.address_family())); |
| 217 dict->SetBoolean("allow_cached_response", info_.allow_cached_response()); | 246 dict->SetBoolean("allow_cached_response", info_.allow_cached_response()); |
| 218 dict->SetBoolean("is_speculative", info_.is_speculative()); | 247 dict->SetBoolean("is_speculative", info_.is_speculative()); |
| 219 dict->SetInteger("priority", info_.priority()); | 248 dict->SetInteger("priority", info_.priority()); |
| 220 | 249 |
| 221 if (source_.is_valid()) | 250 if (source_.is_valid()) |
| 222 dict->Set("source_dependency", source_.ToValue()); | 251 dict->Set("source_dependency", source_.ToValue()); |
| 223 | 252 |
| 224 return dict; | 253 return dict; |
| 225 } | 254 } |
| 226 | 255 |
| 227 private: | 256 private: |
| 228 const HostResolver::RequestInfo info_; | 257 const HostResolver::RequestInfo info_; |
| 229 const NetLog::Source source_; | 258 const NetLog::Source source_; |
| 230 }; | 259 }; |
| 231 | 260 |
| 232 // Parameters associated with the creation of a HostResolverImpl::Job | 261 // Parameters associated with the creation of a HostResolverImpl::Job. |
| 233 // or a HostResolverImpl::ProcTask. | |
| 234 class JobCreationParameters : public NetLog::EventParameters { | 262 class JobCreationParameters : public NetLog::EventParameters { |
| 235 public: | 263 public: |
| 236 JobCreationParameters(const std::string& host, | 264 JobCreationParameters(const std::string& host, |
| 237 const NetLog::Source& source) | 265 const NetLog::Source& source) |
| 238 : host_(host), source_(source) {} | 266 : host_(host), source_(source) {} |
| 239 | 267 |
| 240 virtual Value* ToValue() const OVERRIDE { | 268 virtual Value* ToValue() const OVERRIDE { |
| 241 DictionaryValue* dict = new DictionaryValue(); | 269 DictionaryValue* dict = new DictionaryValue(); |
| 242 dict->SetString("host", host_); | 270 dict->SetString("host", host_); |
| 243 dict->Set("source_dependency", source_.ToValue()); | 271 dict->Set("source_dependency", source_.ToValue()); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 request_net_log.BeginEvent( | 311 request_net_log.BeginEvent( |
| 284 NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, | 312 NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, |
| 285 make_scoped_refptr(new RequestInfoParameters( | 313 make_scoped_refptr(new RequestInfoParameters( |
| 286 info, source_net_log.source()))); | 314 info, source_net_log.source()))); |
| 287 } | 315 } |
| 288 | 316 |
| 289 // Logs when a request has just completed (before its callback is run). | 317 // Logs when a request has just completed (before its callback is run). |
| 290 void LogFinishRequest(const BoundNetLog& source_net_log, | 318 void LogFinishRequest(const BoundNetLog& source_net_log, |
| 291 const BoundNetLog& request_net_log, | 319 const BoundNetLog& request_net_log, |
| 292 const HostResolver::RequestInfo& info, | 320 const HostResolver::RequestInfo& info, |
| 293 int net_error, | 321 int net_error) { |
| 294 int os_error) { | 322 request_net_log.EndEventWithNetErrorCode( |
| 295 scoped_refptr<NetLog::EventParameters> params; | 323 NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, net_error); |
| 296 if (net_error != OK) { | |
| 297 params = new HostResolveFailedParams(0, net_error, os_error); | |
| 298 } | |
| 299 | |
| 300 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, params); | |
| 301 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); | 324 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); |
| 302 } | 325 } |
| 303 | 326 |
| 304 // Logs when a request has been cancelled. | 327 // Logs when a request has been cancelled. |
| 305 void LogCancelRequest(const BoundNetLog& source_net_log, | 328 void LogCancelRequest(const BoundNetLog& source_net_log, |
| 306 const BoundNetLog& request_net_log, | 329 const BoundNetLog& request_net_log, |
| 307 const HostResolverImpl::RequestInfo& info) { | 330 const HostResolverImpl::RequestInfo& info) { |
| 308 request_net_log.AddEvent(NetLog::TYPE_CANCELLED, NULL); | 331 request_net_log.AddEvent(NetLog::TYPE_CANCELLED, NULL); |
| 309 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, NULL); | 332 request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, NULL); |
| 310 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); | 333 source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL, NULL); |
| 311 } | 334 } |
| 312 | 335 |
| 313 //----------------------------------------------------------------------------- | 336 //----------------------------------------------------------------------------- |
| 314 | 337 |
| 315 // Keeps track of the highest priority. | 338 // Keeps track of the highest priority. |
| 316 class PriorityTracker { | 339 class PriorityTracker { |
| 317 public: | 340 public: |
| 318 PriorityTracker() | 341 explicit PriorityTracker(RequestPriority priority) |
| 319 : highest_priority_(IDLE), total_count_(0) { | 342 : highest_priority_(priority), total_count_(0) { |
| 320 memset(counts_, 0, sizeof(counts_)); | 343 memset(counts_, 0, sizeof(counts_)); |
| 321 } | 344 } |
| 322 | 345 |
| 323 RequestPriority highest_priority() const { | 346 RequestPriority highest_priority() const { |
| 324 return highest_priority_; | 347 return highest_priority_; |
| 325 } | 348 } |
| 326 | 349 |
| 327 size_t total_count() const { | 350 size_t total_count() const { |
| 328 return total_count_; | 351 return total_count_; |
| 329 } | 352 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 354 private: | 377 private: |
| 355 RequestPriority highest_priority_; | 378 RequestPriority highest_priority_; |
| 356 size_t total_count_; | 379 size_t total_count_; |
| 357 size_t counts_[NUM_PRIORITIES]; | 380 size_t counts_[NUM_PRIORITIES]; |
| 358 }; | 381 }; |
| 359 | 382 |
| 360 //----------------------------------------------------------------------------- | 383 //----------------------------------------------------------------------------- |
| 361 | 384 |
| 362 HostResolver* CreateHostResolver(size_t max_concurrent_resolves, | 385 HostResolver* CreateHostResolver(size_t max_concurrent_resolves, |
| 363 size_t max_retry_attempts, | 386 size_t max_retry_attempts, |
| 364 bool use_cache, | 387 HostCache* cache, |
| 388 scoped_ptr<DnsConfigService> config_service, |
| 365 NetLog* net_log) { | 389 NetLog* net_log) { |
| 366 if (max_concurrent_resolves == HostResolver::kDefaultParallelism) | 390 if (max_concurrent_resolves == HostResolver::kDefaultParallelism) |
| 367 max_concurrent_resolves = kDefaultMaxProcTasks; | 391 max_concurrent_resolves = kDefaultMaxProcTasks; |
| 368 | 392 |
| 369 // TODO(szym): Add experiments with reserved slots for higher priority | 393 // TODO(szym): Add experiments with reserved slots for higher priority |
| 370 // requests. | 394 // requests. |
| 371 | 395 |
| 372 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, max_concurrent_resolves); | 396 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, max_concurrent_resolves); |
| 373 | 397 |
| 374 HostResolverImpl* resolver = new HostResolverImpl( | 398 HostResolverImpl* resolver = new HostResolverImpl( |
| 375 use_cache ? HostCache::CreateDefaultCache() : NULL, | 399 cache, |
| 376 limits, | 400 limits, |
| 377 HostResolverImpl::ProcTaskParams(NULL, max_retry_attempts), | 401 HostResolverImpl::ProcTaskParams(NULL, max_retry_attempts), |
| 402 config_service.Pass(), |
| 378 net_log); | 403 net_log); |
| 379 | 404 |
| 380 return resolver; | 405 return resolver; |
| 381 } | 406 } |
| 382 | 407 |
| 383 } // anonymous namespace | 408 } // anonymous namespace |
| 384 | 409 |
| 385 //----------------------------------------------------------------------------- | 410 //----------------------------------------------------------------------------- |
| 386 | 411 |
| 387 HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves, | 412 HostResolver* CreateSystemHostResolver(size_t max_concurrent_resolves, |
| 388 size_t max_retry_attempts, | 413 size_t max_retry_attempts, |
| 389 NetLog* net_log) { | 414 NetLog* net_log) { |
| 390 return CreateHostResolver(max_concurrent_resolves, | 415 return CreateHostResolver(max_concurrent_resolves, |
| 391 max_retry_attempts, | 416 max_retry_attempts, |
| 392 true /* use_cache */, | 417 HostCache::CreateDefaultCache(), |
| 418 scoped_ptr<DnsConfigService>(NULL), |
| 393 net_log); | 419 net_log); |
| 394 } | 420 } |
| 395 | 421 |
| 396 HostResolver* CreateNonCachingSystemHostResolver(size_t max_concurrent_resolves, | 422 HostResolver* CreateNonCachingSystemHostResolver(size_t max_concurrent_resolves, |
| 397 size_t max_retry_attempts, | 423 size_t max_retry_attempts, |
| 398 NetLog* net_log) { | 424 NetLog* net_log) { |
| 399 return CreateHostResolver(max_concurrent_resolves, | 425 return CreateHostResolver(max_concurrent_resolves, |
| 400 max_retry_attempts, | 426 max_retry_attempts, |
| 401 false /* use_cache */, | 427 NULL, |
| 428 scoped_ptr<DnsConfigService>(NULL), |
| 402 net_log); | 429 net_log); |
| 403 } | 430 } |
| 404 | 431 |
| 432 HostResolver* CreateAsyncHostResolver(size_t max_concurrent_resolves, |
| 433 size_t max_retry_attempts, |
| 434 NetLog* net_log) { |
| 435 scoped_ptr<DnsConfigService> config_service = |
| 436 DnsConfigService::CreateSystemService(); |
| 437 config_service->Watch(); |
| 438 return CreateHostResolver(max_concurrent_resolves, |
| 439 max_retry_attempts, |
| 440 HostCache::CreateDefaultCache(), |
| 441 config_service.Pass(), |
| 442 net_log); |
| 443 } |
| 444 |
| 405 //----------------------------------------------------------------------------- | 445 //----------------------------------------------------------------------------- |
| 406 | 446 |
| 407 // Holds the data for a request that could not be completed synchronously. | 447 // 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 | 448 // It is owned by a Job. Canceled Requests are only marked as canceled rather |
| 409 // than removed from the Job's |requests_| list. | 449 // than removed from the Job's |requests_| list. |
| 410 class HostResolverImpl::Request { | 450 class HostResolverImpl::Request { |
| 411 public: | 451 public: |
| 412 Request(const BoundNetLog& source_net_log, | 452 Request(const BoundNetLog& source_net_log, |
| 413 const BoundNetLog& request_net_log, | 453 const BoundNetLog& request_net_log, |
| 414 const RequestInfo& info, | 454 const RequestInfo& info, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 433 return callback_.is_null(); | 473 return callback_.is_null(); |
| 434 } | 474 } |
| 435 | 475 |
| 436 void set_job(Job* job) { | 476 void set_job(Job* job) { |
| 437 DCHECK(job); | 477 DCHECK(job); |
| 438 // Identify which job the request is waiting on. | 478 // Identify which job the request is waiting on. |
| 439 job_ = job; | 479 job_ = job; |
| 440 } | 480 } |
| 441 | 481 |
| 442 // Prepare final AddressList and call completion callback. | 482 // Prepare final AddressList and call completion callback. |
| 443 void OnComplete(int error, const AddressList& addrlist) { | 483 void OnComplete(int error, const AddressList& addr_list) { |
| 444 if (error == OK) | 484 if (error == OK) |
| 445 *addresses_ = CreateAddressListUsingPort(addrlist, info_.port()); | 485 *addresses_ = CreateAddressListUsingPort(addr_list, info_.port()); |
| 446 CompletionCallback callback = callback_; | 486 CompletionCallback callback = callback_; |
| 447 MarkAsCanceled(); | 487 MarkAsCanceled(); |
| 448 callback.Run(error); | 488 callback.Run(error); |
| 449 } | 489 } |
| 450 | 490 |
| 451 Job* job() const { | 491 Job* job() const { |
| 452 return job_; | 492 return job_; |
| 453 } | 493 } |
| 454 | 494 |
| 455 // NetLog for the source, passed in HostResolver::Resolve. | 495 // NetLog for the source, passed in HostResolver::Resolve. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 // resolution (OnLookupComplete) is completed or not. If the original attempt | 538 // resolution (OnLookupComplete) is completed or not. If the original attempt |
| 499 // hasn't completed, then we start another attempt for host resolution. We take | 539 // 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 | 540 // the results from the first attempt that finishes and ignore the results from |
| 501 // all other attempts. | 541 // all other attempts. |
| 502 // | 542 // |
| 503 // TODO(szym): Move to separate source file for testing and mocking. | 543 // TODO(szym): Move to separate source file for testing and mocking. |
| 504 // | 544 // |
| 505 class HostResolverImpl::ProcTask | 545 class HostResolverImpl::ProcTask |
| 506 : public base::RefCountedThreadSafe<HostResolverImpl::ProcTask> { | 546 : public base::RefCountedThreadSafe<HostResolverImpl::ProcTask> { |
| 507 public: | 547 public: |
| 508 typedef base::Callback<void(int, int, const AddressList&)> Callback; | 548 typedef base::Callback<void(int net_error, |
| 549 const AddressList& addr_list)> Callback; |
| 509 | 550 |
| 510 ProcTask(const Key& key, | 551 ProcTask(const Key& key, |
| 511 const ProcTaskParams& params, | 552 const ProcTaskParams& params, |
| 512 const Callback& callback, | 553 const Callback& callback, |
| 513 const BoundNetLog& job_net_log) | 554 const BoundNetLog& job_net_log) |
| 514 : key_(key), | 555 : key_(key), |
| 515 params_(params), | 556 params_(params), |
| 516 callback_(callback), | 557 callback_(callback), |
| 517 origin_loop_(base::MessageLoopProxy::current()), | 558 origin_loop_(base::MessageLoopProxy::current()), |
| 518 attempt_number_(0), | 559 attempt_number_(0), |
| 519 completed_attempt_number_(0), | 560 completed_attempt_number_(0), |
| 520 completed_attempt_error_(ERR_UNEXPECTED), | 561 completed_attempt_error_(ERR_UNEXPECTED), |
| 521 had_non_speculative_request_(false), | 562 had_non_speculative_request_(false), |
| 522 net_log_(BoundNetLog::Make( | 563 net_log_(job_net_log) { |
| 523 job_net_log.net_log(), | |
| 524 NetLog::SOURCE_HOST_RESOLVER_IMPL_PROC_TASK)) { | |
| 525 if (!params_.resolver_proc) | 564 if (!params_.resolver_proc) |
| 526 params_.resolver_proc = HostResolverProc::GetDefault(); | 565 params_.resolver_proc = HostResolverProc::GetDefault(); |
| 527 // If default is unset, use the system proc. | 566 // If default is unset, use the system proc. |
| 528 if (!params_.resolver_proc) | 567 if (!params_.resolver_proc) |
| 529 params_.resolver_proc = new CallSystemHostResolverProc(); | 568 params_.resolver_proc = new CallSystemHostResolverProc(); |
| 530 | 569 |
| 531 job_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_PROC_TASK, | 570 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, NULL); |
| 532 new NetLogSourceParameter("source_dependency", | |
| 533 net_log_.source())); | |
| 534 | |
| 535 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, | |
| 536 new JobCreationParameters(key_.hostname, | |
| 537 job_net_log.source())); | |
| 538 } | 571 } |
| 539 | 572 |
| 540 void Start() { | 573 void Start() { |
| 541 DCHECK(origin_loop_->BelongsToCurrentThread()); | 574 DCHECK(origin_loop_->BelongsToCurrentThread()); |
| 542 StartLookupAttempt(); | 575 StartLookupAttempt(); |
| 543 } | 576 } |
| 544 | 577 |
| 545 // Cancels this ProcTask. It will be orphaned. Any outstanding resolve | 578 // Cancels this ProcTask. It will be orphaned. Any outstanding resolve |
| 546 // attempts running on worker threads will continue running. Only once all the | 579 // attempts running on worker threads will continue running. Only once all the |
| 547 // attempts complete will the final reference to this ProcTask be released. | 580 // attempts complete will the final reference to this ProcTask be released. |
| 548 void Cancel() { | 581 void Cancel() { |
| 549 DCHECK(origin_loop_->BelongsToCurrentThread()); | 582 DCHECK(origin_loop_->BelongsToCurrentThread()); |
| 550 | 583 |
| 551 if (was_canceled()) | 584 if (was_canceled()) |
| 552 return; | 585 return; |
| 553 | 586 |
| 554 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); | |
| 555 | |
| 556 callback_.Reset(); | 587 callback_.Reset(); |
| 557 | 588 |
| 558 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, NULL); | 589 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, NULL); |
| 559 } | 590 } |
| 560 | 591 |
| 561 void set_had_non_speculative_request() { | 592 void set_had_non_speculative_request() { |
| 562 DCHECK(origin_loop_->BelongsToCurrentThread()); | 593 DCHECK(origin_loop_->BelongsToCurrentThread()); |
| 563 had_non_speculative_request_ = true; | 594 had_non_speculative_request_ = true; |
| 564 } | 595 } |
| 565 | 596 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 614 // WARNING: This code runs inside a worker pool. The shutdown code cannot | 645 // WARNING: This code runs inside a worker pool. The shutdown code cannot |
| 615 // wait for it to finish, so we must be very careful here about using other | 646 // wait for it to finish, so we must be very careful here about using other |
| 616 // objects (like MessageLoops, Singletons, etc). During shutdown these objects | 647 // objects (like MessageLoops, Singletons, etc). During shutdown these objects |
| 617 // may no longer exist. Multiple DoLookups() could be running in parallel, so | 648 // may no longer exist. Multiple DoLookups() could be running in parallel, so |
| 618 // any state inside of |this| must not mutate . | 649 // any state inside of |this| must not mutate . |
| 619 void DoLookup(const base::TimeTicks& start_time, | 650 void DoLookup(const base::TimeTicks& start_time, |
| 620 const uint32 attempt_number) { | 651 const uint32 attempt_number) { |
| 621 AddressList results; | 652 AddressList results; |
| 622 int os_error = 0; | 653 int os_error = 0; |
| 623 // Running on the worker thread | 654 // Running on the worker thread |
| 624 | |
| 625 int error = params_.resolver_proc->Resolve(key_.hostname, | 655 int error = params_.resolver_proc->Resolve(key_.hostname, |
| 626 key_.address_family, | 656 key_.address_family, |
| 627 key_.host_resolver_flags, | 657 key_.host_resolver_flags, |
| 628 &results, | 658 &results, |
| 629 &os_error); | 659 &os_error); |
| 630 | 660 |
| 631 origin_loop_->PostTask( | 661 origin_loop_->PostTask( |
| 632 FROM_HERE, | 662 FROM_HERE, |
| 633 base::Bind(&ProcTask::OnLookupComplete, this, results, start_time, | 663 base::Bind(&ProcTask::OnLookupComplete, this, results, start_time, |
| 634 attempt_number, error, os_error)); | 664 attempt_number, error, os_error)); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 650 const base::TimeTicks& start_time, | 680 const base::TimeTicks& start_time, |
| 651 const uint32 attempt_number, | 681 const uint32 attempt_number, |
| 652 int error, | 682 int error, |
| 653 const int os_error) { | 683 const int os_error) { |
| 654 DCHECK(origin_loop_->BelongsToCurrentThread()); | 684 DCHECK(origin_loop_->BelongsToCurrentThread()); |
| 655 DCHECK(error || results.head()); | 685 DCHECK(error || results.head()); |
| 656 | 686 |
| 657 bool was_retry_attempt = attempt_number > 1; | 687 bool was_retry_attempt = attempt_number > 1; |
| 658 | 688 |
| 659 // Ideally the following code would be part of host_resolver_proc.cc, | 689 // Ideally the following code would be part of host_resolver_proc.cc, |
| 660 // however it isn't safe to call NetworkChangeNotifier from worker | 690 // however it isn't safe to call NetworkChangeNotifier from worker threads. |
| 661 // threads. So we do it here on the IO thread instead. | 691 // So we do it here on the IO thread instead. |
| 662 if (error != OK && NetworkChangeNotifier::IsOffline()) | 692 if (error != OK && NetworkChangeNotifier::IsOffline()) |
| 663 error = ERR_INTERNET_DISCONNECTED; | 693 error = ERR_INTERNET_DISCONNECTED; |
| 664 | 694 |
| 665 // If this is the first attempt that is finishing later, then record | 695 // If this is the first attempt that is finishing later, then record data |
| 666 // data for the first attempt. Won't contaminate with retry attempt's | 696 // for the first attempt. Won't contaminate with retry attempt's data. |
| 667 // data. | |
| 668 if (!was_retry_attempt) | 697 if (!was_retry_attempt) |
| 669 RecordPerformanceHistograms(start_time, error, os_error); | 698 RecordPerformanceHistograms(start_time, error, os_error); |
| 670 | 699 |
| 671 RecordAttemptHistograms(start_time, attempt_number, error, os_error); | 700 RecordAttemptHistograms(start_time, attempt_number, error, os_error); |
| 672 | 701 |
| 673 if (was_canceled()) | 702 if (was_canceled()) |
| 674 return; | 703 return; |
| 675 | 704 |
| 676 scoped_refptr<NetLog::EventParameters> params; | 705 scoped_refptr<NetLog::EventParameters> params; |
| 677 if (error != OK) { | 706 if (error != OK) { |
| 678 params = new HostResolveFailedParams(attempt_number, error, os_error); | 707 params = new ProcTaskFailedParams(attempt_number, error, os_error); |
| 679 } else { | 708 } else { |
| 680 params = new NetLogIntegerParameter("attempt_number", attempt_number); | 709 params = new NetLogIntegerParameter("attempt_number", attempt_number); |
| 681 } | 710 } |
| 682 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_FINISHED, params); | 711 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_FINISHED, params); |
| 683 | 712 |
| 684 if (was_completed()) | 713 if (was_completed()) |
| 685 return; | 714 return; |
| 686 | 715 |
| 687 // Copy the results from the first worker thread that resolves the host. | 716 // Copy the results from the first worker thread that resolves the host. |
| 688 results_ = results; | 717 results_ = results; |
| 689 completed_attempt_number_ = attempt_number; | 718 completed_attempt_number_ = attempt_number; |
| 690 completed_attempt_error_ = error; | 719 completed_attempt_error_ = error; |
| 691 | 720 |
| 692 if (was_retry_attempt) { | 721 if (was_retry_attempt) { |
| 693 // If retry attempt finishes before 1st attempt, then get stats on how | 722 // If retry attempt finishes before 1st attempt, then get stats on how |
| 694 // much time is saved by having spawned an extra attempt. | 723 // much time is saved by having spawned an extra attempt. |
| 695 retry_attempt_finished_time_ = base::TimeTicks::Now(); | 724 retry_attempt_finished_time_ = base::TimeTicks::Now(); |
| 696 } | 725 } |
| 697 | 726 |
| 698 if (error != OK) { | 727 if (error != OK) { |
| 699 params = new HostResolveFailedParams(0, error, os_error); | 728 params = new ProcTaskFailedParams(0, error, os_error); |
| 700 } else { | 729 } else { |
| 701 params = new AddressListNetLogParam(results_); | 730 params = new AddressListNetLogParam(results_); |
| 702 } | 731 } |
| 703 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, params); | 732 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, params); |
| 704 | 733 |
| 705 callback_.Run(error, os_error, results_); | 734 callback_.Run(error, results_); |
| 706 } | 735 } |
| 707 | 736 |
| 708 void RecordPerformanceHistograms(const base::TimeTicks& start_time, | 737 void RecordPerformanceHistograms(const base::TimeTicks& start_time, |
| 709 const int error, | 738 const int error, |
| 710 const int os_error) const { | 739 const int os_error) const { |
| 711 DCHECK(origin_loop_->BelongsToCurrentThread()); | 740 DCHECK(origin_loop_->BelongsToCurrentThread()); |
| 712 enum Category { // Used in HISTOGRAM_ENUMERATION. | 741 enum Category { // Used in HISTOGRAM_ENUMERATION. |
| 713 RESOLVE_SUCCESS, | 742 RESOLVE_SUCCESS, |
| 714 RESOLVE_FAIL, | 743 RESOLVE_FAIL, |
| 715 RESOLVE_SPECULATIVE_SUCCESS, | 744 RESOLVE_SPECULATIVE_SUCCESS, |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 884 AddressList results_; | 913 AddressList results_; |
| 885 | 914 |
| 886 BoundNetLog net_log_; | 915 BoundNetLog net_log_; |
| 887 | 916 |
| 888 DISALLOW_COPY_AND_ASSIGN(ProcTask); | 917 DISALLOW_COPY_AND_ASSIGN(ProcTask); |
| 889 }; | 918 }; |
| 890 | 919 |
| 891 //----------------------------------------------------------------------------- | 920 //----------------------------------------------------------------------------- |
| 892 | 921 |
| 893 // Represents a request to the worker pool for a "probe for IPv6 support" call. | 922 // Represents a request to the worker pool for a "probe for IPv6 support" call. |
| 923 // |
| 924 // TODO(szym): This could also be replaced with PostTaskAndReply and Callbacks. |
| 894 class HostResolverImpl::IPv6ProbeJob | 925 class HostResolverImpl::IPv6ProbeJob |
| 895 : public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> { | 926 : public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> { |
| 896 public: | 927 public: |
| 897 explicit IPv6ProbeJob(HostResolverImpl* resolver) | 928 explicit IPv6ProbeJob(HostResolverImpl* resolver) |
| 898 : resolver_(resolver), | 929 : resolver_(resolver), |
| 899 origin_loop_(base::MessageLoopProxy::current()) { | 930 origin_loop_(base::MessageLoopProxy::current()) { |
| 900 DCHECK(resolver); | 931 DCHECK(resolver); |
| 901 } | 932 } |
| 902 | 933 |
| 903 void Start() { | 934 void Start() { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 951 HostResolverImpl* resolver_; | 982 HostResolverImpl* resolver_; |
| 952 | 983 |
| 953 // Used to post ourselves onto the origin thread. | 984 // Used to post ourselves onto the origin thread. |
| 954 scoped_refptr<base::MessageLoopProxy> origin_loop_; | 985 scoped_refptr<base::MessageLoopProxy> origin_loop_; |
| 955 | 986 |
| 956 DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); | 987 DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); |
| 957 }; | 988 }; |
| 958 | 989 |
| 959 //----------------------------------------------------------------------------- | 990 //----------------------------------------------------------------------------- |
| 960 | 991 |
| 992 // Resolves the hostname using DnsTransaction. |
| 993 // TODO(szym): This could be moved to separate source file as well. |
| 994 class HostResolverImpl::DnsTask { |
| 995 public: |
| 996 typedef base::Callback<void(int net_error, |
| 997 const AddressList& addr_list, |
| 998 base::TimeDelta ttl)> Callback; |
| 999 |
| 1000 DnsTask(DnsTransactionFactory* factory, |
| 1001 const Key& key, |
| 1002 const Callback& callback, |
| 1003 const BoundNetLog& job_net_log) |
| 1004 : callback_(callback), net_log_(job_net_log) { |
| 1005 DCHECK(factory); |
| 1006 DCHECK(!callback.is_null()); |
| 1007 |
| 1008 // For now we treat ADDRESS_FAMILY_UNSPEC as if it was IPV4. |
| 1009 uint16 qtype = (key.address_family == ADDRESS_FAMILY_IPV6) |
| 1010 ? dns_protocol::kTypeAAAA |
| 1011 : dns_protocol::kTypeA; |
| 1012 // TODO(szym): Implement "happy eyeballs". |
| 1013 transaction_ = factory->CreateTransaction( |
| 1014 key.hostname, |
| 1015 qtype, |
| 1016 base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this)), |
| 1017 net_log_); |
| 1018 DCHECK(transaction_.get()); |
| 1019 } |
| 1020 |
| 1021 int Start() { |
| 1022 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, NULL); |
| 1023 return transaction_->Start(); |
| 1024 } |
| 1025 |
| 1026 void OnTransactionComplete(DnsTransaction* transaction, |
| 1027 int net_error, |
| 1028 const DnsResponse* response) { |
| 1029 // TODO(szym): Record performance histograms. |
| 1030 // Run |callback_| last since the owning Job will then delete this DnsTask. |
| 1031 DnsResponse::Result result = DnsResponse::DNS_SUCCESS; |
| 1032 if (net_error == OK) { |
| 1033 AddressList addr_list; |
| 1034 base::TimeDelta ttl; |
| 1035 result = response->ParseToAddressList(&addr_list, &ttl); |
| 1036 if (result == DnsResponse::DNS_SUCCESS) { |
| 1037 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, |
| 1038 new AddressListNetLogParam(addr_list)); |
| 1039 callback_.Run(net_error, addr_list, ttl); |
| 1040 return; |
| 1041 } |
| 1042 net_error = ERR_DNS_MALFORMED_RESPONSE; |
| 1043 } |
| 1044 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, |
| 1045 new DnsTaskFailedParams(net_error, result)); |
| 1046 callback_.Run(net_error, AddressList(), base::TimeDelta()); |
| 1047 } |
| 1048 |
| 1049 private: |
| 1050 // The listener to the results of this DnsTask. |
| 1051 Callback callback_; |
| 1052 |
| 1053 const BoundNetLog net_log_; |
| 1054 |
| 1055 scoped_ptr<DnsTransaction> transaction_; |
| 1056 }; |
| 1057 |
| 1058 //----------------------------------------------------------------------------- |
| 1059 |
| 961 // Aggregates all Requests for the same Key. Dispatched via PriorityDispatch. | 1060 // Aggregates all Requests for the same Key. Dispatched via PriorityDispatch. |
| 962 // Spawns ProcTask when started. | |
| 963 class HostResolverImpl::Job : public PrioritizedDispatcher::Job { | 1061 class HostResolverImpl::Job : public PrioritizedDispatcher::Job { |
| 964 public: | 1062 public: |
| 965 // Creates new job for |key| where |request_net_log| is bound to the | 1063 // Creates new job for |key| where |request_net_log| is bound to the |
| 966 // request that spawned it. | 1064 // request that spawned it and |priority| is the initial priority. |
| 967 Job(HostResolverImpl* resolver, | 1065 Job(HostResolverImpl* resolver, |
| 968 const Key& key, | 1066 const Key& key, |
| 969 const BoundNetLog& request_net_log) | 1067 const BoundNetLog& request_net_log, |
| 1068 RequestPriority priority) |
| 970 : resolver_(resolver->AsWeakPtr()), | 1069 : resolver_(resolver->AsWeakPtr()), |
| 971 key_(key), | 1070 key_(key), |
| 1071 priority_tracker_(priority), |
| 972 had_non_speculative_request_(false), | 1072 had_non_speculative_request_(false), |
| 973 net_log_(BoundNetLog::Make(request_net_log.net_log(), | 1073 net_log_(BoundNetLog::Make(request_net_log.net_log(), |
| 974 NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)), | 1074 NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)) { |
| 975 net_error_(ERR_IO_PENDING), | |
| 976 os_error_(0) { | |
| 977 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB, NULL); | 1075 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB, NULL); |
| 978 | 1076 |
| 979 net_log_.BeginEvent( | 1077 net_log_.BeginEvent( |
| 980 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, | 1078 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, |
| 981 make_scoped_refptr(new JobCreationParameters( | 1079 make_scoped_refptr(new JobCreationParameters( |
| 982 key_.hostname, request_net_log.source()))); | 1080 key_.hostname, request_net_log.source()))); |
| 1081 |
| 1082 handle_ = resolver_->dispatcher_.Add(this, priority); |
| 983 } | 1083 } |
| 984 | 1084 |
| 985 virtual ~Job() { | 1085 virtual ~Job() { |
| 986 if (net_error_ == ERR_IO_PENDING) { | 1086 if (is_running()) { |
| 987 if (is_running()) { | 1087 // |resolver_| was destroyed with this Job still in flight. |
| 988 DCHECK_EQ(ERR_IO_PENDING, net_error_); | 1088 // Clean-up, record in the log, but don't run any callbacks. |
| 1089 if (is_proc_running()) { |
| 989 proc_task_->Cancel(); | 1090 proc_task_->Cancel(); |
| 990 proc_task_ = NULL; | 1091 proc_task_ = NULL; |
| 991 net_error_ = ERR_ABORTED; | |
| 992 } else { | |
| 993 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); | |
| 994 net_error_ = OK; // For NetLog. | |
| 995 } | 1092 } |
| 1093 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, |
| 1094 ERR_ABORTED); |
| 1095 } else if (is_queued()) { |
| 1096 // This Job was cancelled without running. |
| 1097 // TODO(szym): is there's any benefit in having this distinction? |
| 1098 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); |
| 1099 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, NULL); |
| 1100 } |
| 1101 // else CompleteRequests logged EndEvent. |
| 996 | 1102 |
| 997 for (RequestsList::const_iterator it = requests_.begin(); | 1103 // Log any remaining Requests as cancelled. |
| 998 it != requests_.end(); ++it) { | 1104 for (RequestsList::const_iterator it = requests_.begin(); |
| 999 Request* req = *it; | 1105 it != requests_.end(); ++it) { |
| 1000 if (req->was_canceled()) | 1106 Request* req = *it; |
| 1001 continue; | 1107 if (req->was_canceled()) |
| 1002 DCHECK_EQ(this, req->job()); | 1108 continue; |
| 1003 LogCancelRequest(req->source_net_log(), req->request_net_log(), | 1109 DCHECK_EQ(this, req->job()); |
| 1004 req->info()); | 1110 LogCancelRequest(req->source_net_log(), req->request_net_log(), |
| 1005 } | 1111 req->info()); |
| 1006 } | 1112 } |
| 1007 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, | |
| 1008 net_error_); | |
| 1009 STLDeleteElements(&requests_); | 1113 STLDeleteElements(&requests_); |
| 1010 } | 1114 } |
| 1011 | 1115 |
| 1012 HostResolverImpl* resolver() const { | |
| 1013 return resolver_; | |
| 1014 } | |
| 1015 | |
| 1016 RequestPriority priority() const { | 1116 RequestPriority priority() const { |
| 1017 return priority_tracker_.highest_priority(); | 1117 return priority_tracker_.highest_priority(); |
| 1018 } | 1118 } |
| 1019 | 1119 |
| 1020 // Number of non-canceled requests in |requests_|. | 1120 // Number of non-canceled requests in |requests_|. |
| 1021 size_t num_active_requests() const { | 1121 size_t num_active_requests() const { |
| 1022 return priority_tracker_.total_count(); | 1122 return priority_tracker_.total_count(); |
| 1023 } | 1123 } |
| 1024 | 1124 |
| 1025 const Key& key() const { | 1125 const Key& key() const { |
| 1026 return key_; | 1126 return key_; |
| 1027 } | 1127 } |
| 1028 | 1128 |
| 1029 int net_error() const { | 1129 bool is_queued() const { |
| 1030 return net_error_; | 1130 return !handle_.is_null(); |
| 1031 } | 1131 } |
| 1032 | 1132 |
| 1033 // Used by HostResolverImpl with |dispatcher_|. | 1133 void AddRequest(scoped_ptr<Request> req) { |
| 1034 const PrioritizedDispatcher::Handle& handle() const { | |
| 1035 return handle_; | |
| 1036 } | |
| 1037 | |
| 1038 void set_handle(const PrioritizedDispatcher::Handle& handle) { | |
| 1039 handle_ = handle; | |
| 1040 } | |
| 1041 | |
| 1042 // The Job will own |req| and destroy it in ~Job. | |
| 1043 void AddRequest(Request* req) { | |
| 1044 DCHECK_EQ(key_.hostname, req->info().hostname()); | 1134 DCHECK_EQ(key_.hostname, req->info().hostname()); |
| 1045 | 1135 |
| 1046 req->set_job(this); | 1136 req->set_job(this); |
| 1047 requests_.push_back(req); | |
| 1048 | |
| 1049 priority_tracker_.Add(req->info().priority()); | 1137 priority_tracker_.Add(req->info().priority()); |
| 1050 | 1138 |
| 1051 req->request_net_log().AddEvent( | 1139 req->request_net_log().AddEvent( |
| 1052 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, | 1140 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, |
| 1053 make_scoped_refptr(new NetLogSourceParameter( | 1141 make_scoped_refptr(new NetLogSourceParameter( |
| 1054 "source_dependency", net_log_.source()))); | 1142 "source_dependency", net_log_.source()))); |
| 1055 | 1143 |
| 1056 net_log_.AddEvent( | 1144 net_log_.AddEvent( |
| 1057 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_ATTACH, | 1145 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_ATTACH, |
| 1058 make_scoped_refptr(new JobAttachParameters( | 1146 make_scoped_refptr(new JobAttachParameters( |
| 1059 req->request_net_log().source(), priority()))); | 1147 req->request_net_log().source(), priority()))); |
| 1060 | 1148 |
| 1061 // TODO(szym): Check if this is still needed. | 1149 // TODO(szym): Check if this is still needed. |
| 1062 if (!req->info().is_speculative()) { | 1150 if (!req->info().is_speculative()) { |
| 1063 had_non_speculative_request_ = true; | 1151 had_non_speculative_request_ = true; |
| 1064 if (proc_task_) | 1152 if (proc_task_) |
| 1065 proc_task_->set_had_non_speculative_request(); | 1153 proc_task_->set_had_non_speculative_request(); |
| 1066 } | 1154 } |
| 1155 |
| 1156 requests_.push_back(req.release()); |
| 1157 |
| 1158 if (!handle_.is_null()) |
| 1159 handle_ = resolver_->dispatcher_.ChangePriority(handle_, priority()); |
| 1067 } | 1160 } |
| 1068 | 1161 |
| 1069 void CancelRequest(Request* req) { | 1162 void CancelRequest(Request* req) { |
| 1070 DCHECK_EQ(key_.hostname, req->info().hostname()); | 1163 DCHECK_EQ(key_.hostname, req->info().hostname()); |
| 1071 DCHECK(!req->was_canceled()); | 1164 DCHECK(!req->was_canceled()); |
| 1072 // Don't remove it from |requests_| just mark it canceled. | 1165 // Don't remove it from |requests_| just mark it canceled. |
| 1073 req->MarkAsCanceled(); | 1166 req->MarkAsCanceled(); |
| 1074 LogCancelRequest(req->source_net_log(), req->request_net_log(), | 1167 LogCancelRequest(req->source_net_log(), req->request_net_log(), |
| 1075 req->info()); | 1168 req->info()); |
| 1076 priority_tracker_.Remove(req->info().priority()); | 1169 priority_tracker_.Remove(req->info().priority()); |
| 1077 net_log_.AddEvent( | 1170 net_log_.AddEvent( |
| 1078 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_DETACH, | 1171 NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_DETACH, |
| 1079 make_scoped_refptr(new JobAttachParameters( | 1172 make_scoped_refptr(new JobAttachParameters( |
| 1080 req->request_net_log().source(), priority()))); | 1173 req->request_net_log().source(), priority()))); |
| 1174 |
| 1175 if (!handle_.is_null()) { |
| 1176 if (num_active_requests() > 0) { |
| 1177 handle_ = resolver_->dispatcher_.ChangePriority(handle_, priority()); |
| 1178 } else { |
| 1179 resolver_->dispatcher_.Cancel(handle_); |
| 1180 handle_.Reset(); |
| 1181 } |
| 1182 } |
| 1081 } | 1183 } |
| 1082 | 1184 |
| 1083 // Aborts and destroys the job, completes all requests as aborted. | 1185 // Aborts and destroys the job, completes all requests as aborted. |
| 1186 // The caller should clean up. |
| 1084 void Abort() { | 1187 void Abort() { |
| 1085 // Job should only be aborted if it's running. | 1188 // Job should only be aborted if it's running. |
| 1086 DCHECK(is_running()); | 1189 DCHECK(is_running()); |
| 1087 proc_task_->Cancel(); | 1190 if (is_proc_running()) { |
| 1088 proc_task_ = NULL; | 1191 proc_task_->Cancel(); |
| 1089 net_error_ = ERR_ABORTED; | 1192 proc_task_ = NULL; |
| 1090 os_error_ = 0; | 1193 } |
| 1091 CompleteRequests(AddressList()); | 1194 dns_task_.reset(); |
| 1195 CompleteRequests(ERR_ABORTED, AddressList(), base::TimeDelta()); |
| 1196 } |
| 1197 |
| 1198 bool is_dns_running() const { |
| 1199 return dns_task_.get() != NULL; |
| 1200 } |
| 1201 |
| 1202 bool is_proc_running() const { |
| 1203 return proc_task_.get() != NULL; |
| 1092 } | 1204 } |
| 1093 | 1205 |
| 1094 bool is_running() const { | 1206 bool is_running() const { |
| 1095 return proc_task_.get() != NULL; | 1207 return is_dns_running() || is_proc_running(); |
| 1096 } | 1208 } |
| 1097 | 1209 |
| 1098 // Called by HostResolverImpl when this job is evicted due to queue overflow. | 1210 // Called by HostResolverImpl when this job is evicted due to queue overflow. |
| 1099 void OnEvicted() { | 1211 void OnEvicted() { |
| 1100 // Must not be running. | 1212 // Must not be running. |
| 1101 DCHECK(!is_running()); | 1213 DCHECK(!is_running()); |
| 1102 handle_ = PrioritizedDispatcher::Handle(); | 1214 handle_.Reset(); |
| 1103 | 1215 |
| 1104 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED, NULL); | 1216 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED, NULL); |
| 1105 | 1217 |
| 1218 scoped_ptr<Job> self_deleter(this); |
| 1219 resolver_->RemoveJob(this); |
| 1220 |
| 1106 // This signals to CompleteRequests that this job never ran. | 1221 // This signals to CompleteRequests that this job never ran. |
| 1107 net_error_ = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; | 1222 CompleteRequests(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, |
| 1108 os_error_ = 0; | 1223 AddressList(), |
| 1109 CompleteRequests(AddressList()); | 1224 base::TimeDelta()); |
| 1110 } | 1225 } |
| 1111 | 1226 |
| 1112 // PriorityDispatch::Job interface. | 1227 // PriorityDispatch::Job interface. |
| 1113 virtual void Start() OVERRIDE { | 1228 virtual void Start() OVERRIDE { |
| 1114 DCHECK(!is_running()); | 1229 DCHECK(!is_running()); |
| 1115 handle_ = PrioritizedDispatcher::Handle(); | 1230 handle_.Reset(); |
| 1116 | 1231 |
| 1117 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED, NULL); | 1232 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED, NULL); |
| 1118 | 1233 |
| 1234 if (resolver_->dns_transaction_factory_.get()) { |
| 1235 StartDnsTask(); |
| 1236 } else { |
| 1237 StartProcTask(); |
| 1238 } |
| 1239 } |
| 1240 |
| 1241 private: |
| 1242 // TODO(szym): Since DnsTransaction does not consume threads, we can increase |
| 1243 // the limits on |dispatcher_|. But in order to keep the number of WorkerPool |
| 1244 // threads low, we will need to use an "inner" PrioritizedDispatcher with |
| 1245 // tighter limits. |
| 1246 void StartProcTask() { |
| 1247 DCHECK(!dns_task_.get()); |
| 1119 proc_task_ = new ProcTask( | 1248 proc_task_ = new ProcTask( |
| 1120 key_, | 1249 key_, |
| 1121 resolver_->proc_params_, | 1250 resolver_->proc_params_, |
| 1122 base::Bind(&Job::OnProcTaskComplete, base::Unretained(this)), | 1251 base::Bind(&Job::OnProcTaskComplete, base::Unretained(this)), |
| 1123 net_log_); | 1252 net_log_); |
| 1124 | 1253 |
| 1125 if (had_non_speculative_request_) | 1254 if (had_non_speculative_request_) |
| 1126 proc_task_->set_had_non_speculative_request(); | 1255 proc_task_->set_had_non_speculative_request(); |
| 1127 // Start() could be called from within Resolve(), hence it must NOT directly | 1256 // Start() could be called from within Resolve(), hence it must NOT directly |
| 1128 // call OnProcTaskComplete, for example, on synchronous failure. | 1257 // call OnProcTaskComplete, for example, on synchronous failure. |
| 1129 proc_task_->Start(); | 1258 proc_task_->Start(); |
| 1130 } | 1259 } |
| 1131 | 1260 |
| 1132 private: | |
| 1133 // Called by ProcTask when it completes. | 1261 // Called by ProcTask when it completes. |
| 1134 void OnProcTaskComplete(int net_error, int os_error, | 1262 void OnProcTaskComplete(int net_error, const AddressList& addr_list) { |
| 1135 const AddressList& addrlist) { | 1263 DCHECK(is_proc_running()); |
| 1136 DCHECK(is_running()); | 1264 // |addr_list| will be destroyed once we destroy |proc_task_|. |
| 1265 AddressList list = addr_list; |
| 1137 proc_task_ = NULL; | 1266 proc_task_ = NULL; |
| 1138 net_error_ = net_error; | |
| 1139 os_error_ = os_error; | |
| 1140 | 1267 |
| 1141 // We are the only consumer of |addrlist|, so we can safely change the port | 1268 base::TimeDelta ttl = base::TimeDelta::FromSeconds( |
| 1142 // without copy-on-write. This pays off, when job has only one request. | 1269 kNegativeCacheEntryTTLSeconds); |
| 1143 AddressList list = addrlist; | 1270 if (net_error == OK) |
| 1144 if (net_error == OK && !requests_.empty()) | 1271 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); |
| 1145 MutableSetPort(requests_.front()->info().port(), &list); | |
| 1146 CompleteRequests(list); | |
| 1147 } | |
| 1148 | |
| 1149 // Completes all Requests. Calls OnJobFinished and deletes self. | |
| 1150 void CompleteRequests(const AddressList& addrlist) { | |
| 1151 CHECK(resolver_); | |
| 1152 | 1272 |
| 1153 // This job must be removed from resolver's |jobs_| now to make room for a | 1273 // 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 | 1274 // 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 | 1275 // to spawn one. Consequently, the job deletes itself when CompleteRequests |
| 1156 // is done. | 1276 // is done. |
| 1157 scoped_ptr<Job> self_deleter(this); | 1277 scoped_ptr<Job> self_deleter(this); |
| 1158 resolver_->OnJobFinished(this, addrlist); | 1278 resolver_->OnJobFinished(this, net_error, list, ttl); |
| 1279 |
| 1280 CompleteRequests(net_error, list, ttl); |
| 1281 } |
| 1282 |
| 1283 void StartDnsTask() { |
| 1284 dns_task_.reset(new DnsTask( |
| 1285 resolver_->dns_transaction_factory_.get(), |
| 1286 key_, |
| 1287 base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this)), |
| 1288 net_log_)); |
| 1289 |
| 1290 int rv = dns_task_->Start(); |
| 1291 if (rv != ERR_IO_PENDING) { |
| 1292 DCHECK_NE(OK, rv); |
| 1293 dns_task_.reset(); |
| 1294 StartProcTask(); |
| 1295 } |
| 1296 } |
| 1297 |
| 1298 // Called by DnsTask when it completes. |
| 1299 void OnDnsTaskComplete(int net_error, |
| 1300 const AddressList& addr_list, |
| 1301 base::TimeDelta ttl) { |
| 1302 DCHECK(is_dns_running()); |
| 1303 // |addr_list| will be destroyed once we destroy |dns_task_|. |
| 1304 AddressList list = addr_list; |
| 1305 dns_task_.reset(); |
| 1306 |
| 1307 if (net_error != OK) { |
| 1308 // TODO(szym): Some net errors indicate lack of connectivity. Starting |
| 1309 // ProcTask in that case is a waste of time. |
| 1310 StartProcTask(); |
| 1311 return; |
| 1312 } |
| 1313 |
| 1314 // As in OnProcTaskComplete |
| 1315 scoped_ptr<Job> self_deleter(this); |
| 1316 resolver_->OnJobFinished(this, net_error, list, ttl); |
| 1317 |
| 1318 CompleteRequests(net_error, list, ttl); |
| 1319 } |
| 1320 |
| 1321 // Completes all Requests. Calls OnJobFinished and deletes self. |
| 1322 void CompleteRequests(int net_error, |
| 1323 const AddressList& addr_list, |
| 1324 base::TimeDelta ttl) { |
| 1325 CHECK(resolver_); |
| 1326 DCHECK(!is_running()); |
| 1327 DCHECK(!is_queued()); |
| 1328 |
| 1329 // We are the only consumer of |addr_list|, so we can safely change the port |
| 1330 // without copy-on-write. This pays off, when job has only one request. |
| 1331 AddressList list = addr_list; |
| 1332 if (net_error == OK && !requests_.empty()) |
| 1333 MutableSetPort(requests_.front()->info().port(), &list); |
| 1334 |
| 1335 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, |
| 1336 net_error); |
| 1159 | 1337 |
| 1160 // Complete all of the requests that were attached to the job. | 1338 // Complete all of the requests that were attached to the job. |
| 1161 for (RequestsList::const_iterator it = requests_.begin(); | 1339 for (RequestsList::const_iterator it = requests_.begin(); |
| 1162 it != requests_.end(); ++it) { | 1340 it != requests_.end(); ++it) { |
| 1163 Request* req = *it; | 1341 Request* req = *it; |
| 1164 | 1342 |
| 1165 if (req->was_canceled()) | 1343 if (req->was_canceled()) |
| 1166 continue; | 1344 continue; |
| 1167 | 1345 |
| 1168 DCHECK_EQ(this, req->job()); | 1346 DCHECK_EQ(this, req->job()); |
| 1169 // Update the net log and notify registered observers. | 1347 // Update the net log and notify registered observers. |
| 1170 LogFinishRequest(req->source_net_log(), req->request_net_log(), | 1348 LogFinishRequest(req->source_net_log(), req->request_net_log(), |
| 1171 req->info(), net_error_, os_error_); | 1349 req->info(), net_error); |
| 1172 | 1350 |
| 1173 req->OnComplete(net_error_, addrlist); | 1351 req->OnComplete(net_error, list); |
| 1174 | 1352 |
| 1175 // Check if the resolver was destroyed as a result of running the | 1353 // 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. | 1354 // callback. If it was, we could continue, but we choose to bail. |
| 1177 if (!resolver_) | 1355 if (!resolver_) |
| 1178 return; | 1356 return; |
| 1179 } | 1357 } |
| 1180 } | 1358 } |
| 1181 | 1359 |
| 1182 // Used to call OnJobFinished and RemoveJob. | 1360 // Used to call OnJobFinished. |
| 1183 base::WeakPtr<HostResolverImpl> resolver_; | 1361 base::WeakPtr<HostResolverImpl> resolver_; |
| 1184 | 1362 |
| 1185 Key key_; | 1363 Key key_; |
| 1186 | 1364 |
| 1187 // Tracks the highest priority across |requests_|. | 1365 // Tracks the highest priority across |requests_|. |
| 1188 PriorityTracker priority_tracker_; | 1366 PriorityTracker priority_tracker_; |
| 1189 | 1367 |
| 1190 bool had_non_speculative_request_; | 1368 bool had_non_speculative_request_; |
| 1191 | 1369 |
| 1192 BoundNetLog net_log_; | 1370 BoundNetLog net_log_; |
| 1193 | 1371 |
| 1194 // Store result here in case the job fails fast in Resolve(). | 1372 // Resolves the host using a HostResolverProc. |
| 1195 int net_error_; | 1373 scoped_refptr<ProcTask> proc_task_; |
| 1196 int os_error_; | |
| 1197 | 1374 |
| 1198 // A ProcTask created and started when this Job is dispatched.. | 1375 // Resolves the host using a DnsTransaction. |
| 1199 scoped_refptr<ProcTask> proc_task_; | 1376 scoped_ptr<DnsTask> dns_task_; |
| 1200 | 1377 |
| 1201 // All Requests waiting for the result of this Job. Some can be canceled. | 1378 // All Requests waiting for the result of this Job. Some can be canceled. |
| 1202 RequestsList requests_; | 1379 RequestsList requests_; |
| 1203 | 1380 |
| 1204 // A handle used by HostResolverImpl in |dispatcher_|. | 1381 // A handle used by |HostResolverImpl::dispatcher_|. |
| 1205 PrioritizedDispatcher::Handle handle_; | 1382 PrioritizedDispatcher::Handle handle_; |
| 1206 }; | 1383 }; |
| 1207 | 1384 |
| 1208 //----------------------------------------------------------------------------- | 1385 //----------------------------------------------------------------------------- |
| 1209 | 1386 |
| 1210 HostResolverImpl::ProcTaskParams::ProcTaskParams( | 1387 HostResolverImpl::ProcTaskParams::ProcTaskParams( |
| 1211 HostResolverProc* resolver_proc, | 1388 HostResolverProc* resolver_proc, |
| 1212 size_t max_retry_attempts) | 1389 size_t max_retry_attempts) |
| 1213 : resolver_proc(resolver_proc), | 1390 : resolver_proc(resolver_proc), |
| 1214 max_retry_attempts(max_retry_attempts), | 1391 max_retry_attempts(max_retry_attempts), |
| 1215 unresponsive_delay(base::TimeDelta::FromMilliseconds(6000)), | 1392 unresponsive_delay(base::TimeDelta::FromMilliseconds(6000)), |
| 1216 retry_factor(2) { | 1393 retry_factor(2) { |
| 1217 } | 1394 } |
| 1218 | 1395 |
| 1219 HostResolverImpl::ProcTaskParams::~ProcTaskParams() {} | 1396 HostResolverImpl::ProcTaskParams::~ProcTaskParams() {} |
| 1220 | 1397 |
| 1221 HostResolverImpl::HostResolverImpl( | 1398 HostResolverImpl::HostResolverImpl( |
| 1222 HostCache* cache, | 1399 HostCache* cache, |
| 1223 const PrioritizedDispatcher::Limits& job_limits, | 1400 const PrioritizedDispatcher::Limits& job_limits, |
| 1224 const ProcTaskParams& proc_params, | 1401 const ProcTaskParams& proc_params, |
| 1402 scoped_ptr<DnsConfigService> dns_config_service, |
| 1225 NetLog* net_log) | 1403 NetLog* net_log) |
| 1226 : cache_(cache), | 1404 : cache_(cache), |
| 1227 dispatcher_(job_limits), | 1405 dispatcher_(job_limits), |
| 1228 max_queued_jobs_(job_limits.total_jobs * 100u), | 1406 max_queued_jobs_(job_limits.total_jobs * 100u), |
| 1229 proc_params_(proc_params), | 1407 proc_params_(proc_params), |
| 1230 default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), | 1408 default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), |
| 1409 dns_config_service_(dns_config_service.Pass()), |
| 1231 ipv6_probe_monitoring_(false), | 1410 ipv6_probe_monitoring_(false), |
| 1232 additional_resolver_flags_(0), | 1411 additional_resolver_flags_(0), |
| 1233 net_log_(net_log) { | 1412 net_log_(net_log) { |
| 1234 | 1413 |
| 1235 DCHECK_GE(dispatcher_.num_priorities(), static_cast<size_t>(NUM_PRIORITIES)); | 1414 DCHECK_GE(dispatcher_.num_priorities(), static_cast<size_t>(NUM_PRIORITIES)); |
| 1236 | 1415 |
| 1237 // Maximum of 4 retry attempts for host resolution. | 1416 // Maximum of 4 retry attempts for host resolution. |
| 1238 static const size_t kDefaultMaxRetryAttempts = 4u; | 1417 static const size_t kDefaultMaxRetryAttempts = 4u; |
| 1239 | 1418 |
| 1240 if (proc_params_.max_retry_attempts == HostResolver::kDefaultRetryAttempts) | 1419 if (proc_params_.max_retry_attempts == HostResolver::kDefaultRetryAttempts) |
| 1241 proc_params_.max_retry_attempts = kDefaultMaxRetryAttempts; | 1420 proc_params_.max_retry_attempts = kDefaultMaxRetryAttempts; |
| 1242 | 1421 |
| 1243 #if defined(OS_WIN) | 1422 #if defined(OS_WIN) |
| 1244 EnsureWinsockInit(); | 1423 EnsureWinsockInit(); |
| 1245 #endif | 1424 #endif |
| 1246 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 1425 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
| 1247 if (HaveOnlyLoopbackAddresses()) | 1426 if (HaveOnlyLoopbackAddresses()) |
| 1248 additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; | 1427 additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; |
| 1249 #endif | 1428 #endif |
| 1250 NetworkChangeNotifier::AddIPAddressObserver(this); | 1429 NetworkChangeNotifier::AddIPAddressObserver(this); |
| 1251 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) | 1430 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) |
| 1252 #if !defined(OS_ANDROID) | 1431 #if !defined(OS_ANDROID) |
| 1253 EnsureDnsReloaderInit(); | 1432 EnsureDnsReloaderInit(); |
| 1254 #endif | 1433 #endif |
| 1255 NetworkChangeNotifier::AddDNSObserver(this); | 1434 NetworkChangeNotifier::AddDNSObserver(this); |
| 1256 #endif | 1435 #endif |
| 1436 |
| 1437 if (dns_config_service_.get()) |
| 1438 dns_config_service_->AddObserver(this); |
| 1257 } | 1439 } |
| 1258 | 1440 |
| 1259 HostResolverImpl::~HostResolverImpl() { | 1441 HostResolverImpl::~HostResolverImpl() { |
| 1260 DiscardIPv6ProbeJob(); | 1442 DiscardIPv6ProbeJob(); |
| 1261 | 1443 |
| 1262 // This will also cancel all outstanding requests. | 1444 // This will also cancel all outstanding requests. |
| 1263 STLDeleteValues(&jobs_); | 1445 STLDeleteValues(&jobs_); |
| 1264 | 1446 |
| 1265 NetworkChangeNotifier::RemoveIPAddressObserver(this); | 1447 NetworkChangeNotifier::RemoveIPAddressObserver(this); |
| 1266 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) | 1448 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1288 NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST); | 1470 NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST); |
| 1289 | 1471 |
| 1290 LogStartRequest(source_net_log, request_net_log, info); | 1472 LogStartRequest(source_net_log, request_net_log, info); |
| 1291 | 1473 |
| 1292 // Build a key that identifies the request in the cache and in the | 1474 // Build a key that identifies the request in the cache and in the |
| 1293 // outstanding jobs map. | 1475 // outstanding jobs map. |
| 1294 Key key = GetEffectiveKeyForRequest(info); | 1476 Key key = GetEffectiveKeyForRequest(info); |
| 1295 | 1477 |
| 1296 int rv = ResolveHelper(key, info, addresses, request_net_log); | 1478 int rv = ResolveHelper(key, info, addresses, request_net_log); |
| 1297 if (rv != ERR_DNS_CACHE_MISS) { | 1479 if (rv != ERR_DNS_CACHE_MISS) { |
| 1298 LogFinishRequest(source_net_log, request_net_log, info, rv, | 1480 LogFinishRequest(source_net_log, request_net_log, info, rv); |
| 1299 0 /* os_error (unknown since from cache) */); | |
| 1300 return rv; | 1481 return rv; |
| 1301 } | 1482 } |
| 1302 | 1483 |
| 1303 // Next we need to attach our request to a "job". This job is responsible for | 1484 // Next we need to attach our request to a "job". This job is responsible for |
| 1304 // calling "getaddrinfo(hostname)" on a worker thread. | 1485 // calling "getaddrinfo(hostname)" on a worker thread. |
| 1305 | 1486 |
| 1306 JobMap::iterator jobit = jobs_.find(key); | 1487 JobMap::iterator jobit = jobs_.find(key); |
| 1307 Job* job; | 1488 Job* job; |
| 1308 if (jobit == jobs_.end()) { | 1489 if (jobit == jobs_.end()) { |
| 1309 // Create new Job. | 1490 // Create new Job. |
| 1310 job = new Job(this, key, request_net_log); | 1491 job = new Job(this, key, request_net_log, info.priority()); |
| 1311 job->set_handle(dispatcher_.Add(job, info.priority())); | |
| 1312 | 1492 |
| 1313 // Check for queue overflow. | 1493 // Check for queue overflow. |
| 1314 if (dispatcher_.num_queued_jobs() > max_queued_jobs_) { | 1494 if (dispatcher_.num_queued_jobs() > max_queued_jobs_) { |
| 1315 Job* evicted = static_cast<Job*>(dispatcher_.EvictOldestLowest()); | 1495 Job* evicted = static_cast<Job*>(dispatcher_.EvictOldestLowest()); |
| 1316 DCHECK(evicted); | 1496 DCHECK(evicted); |
| 1317 if (evicted == job) { | 1497 if (evicted == job) { |
| 1318 delete job; | 1498 delete job; |
| 1319 rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; | 1499 rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; |
| 1320 LogFinishRequest(source_net_log, request_net_log, info, rv, 0); | 1500 LogFinishRequest(source_net_log, request_net_log, info, rv); |
| 1321 return rv; | 1501 return rv; |
| 1322 } | 1502 } |
| 1323 evicted->OnEvicted(); // Deletes |evicted|. | 1503 evicted->OnEvicted(); // Deletes |evicted|. |
| 1324 } | 1504 } |
| 1325 | |
| 1326 jobs_.insert(jobit, std::make_pair(key, job)); | 1505 jobs_.insert(jobit, std::make_pair(key, job)); |
| 1327 } else { | 1506 } else { |
| 1328 job = jobit->second; | 1507 job = jobit->second; |
| 1329 } | 1508 } |
| 1330 | 1509 |
| 1331 // Can't complete synchronously. Create and attach request. | 1510 // Can't complete synchronously. Create and attach request. |
| 1332 Request* req = new Request(source_net_log, request_net_log, info, callback, | 1511 scoped_ptr<Request> req(new Request(source_net_log, |
| 1333 addresses); | 1512 request_net_log, |
| 1334 job->AddRequest(req); | 1513 info, |
| 1335 if (!job->handle().is_null()) | 1514 callback, |
| 1336 job->set_handle(dispatcher_.ChangePriority(job->handle(), job->priority())); | 1515 addresses)); |
| 1337 if (out_req) | 1516 if (out_req) |
| 1338 *out_req = reinterpret_cast<RequestHandle>(req); | 1517 *out_req = reinterpret_cast<RequestHandle>(req.get()); |
| 1339 | 1518 |
| 1340 DCHECK_EQ(ERR_IO_PENDING, job->net_error()); | 1519 job->AddRequest(req.Pass()); |
| 1341 // Completion happens during Job::CompleteRequests(). | 1520 // Completion happens during Job::CompleteRequests(). |
| 1342 return ERR_IO_PENDING; | 1521 return ERR_IO_PENDING; |
| 1343 } | 1522 } |
| 1344 | 1523 |
| 1345 int HostResolverImpl::ResolveHelper(const Key& key, | 1524 int HostResolverImpl::ResolveHelper(const Key& key, |
| 1346 const RequestInfo& info, | 1525 const RequestInfo& info, |
| 1347 AddressList* addresses, | 1526 AddressList* addresses, |
| 1348 const BoundNetLog& request_net_log) { | 1527 const BoundNetLog& request_net_log) { |
| 1349 // The result of |getaddrinfo| for empty hosts is inconsistent across systems. | 1528 // The result of |getaddrinfo| for empty hosts is inconsistent across systems. |
| 1350 // On Windows it gives the default interface's address, whereas on Linux it | 1529 // On Windows it gives the default interface's address, whereas on Linux it |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1369 // Make a log item for the request. | 1548 // Make a log item for the request. |
| 1370 BoundNetLog request_net_log = BoundNetLog::Make(net_log_, | 1549 BoundNetLog request_net_log = BoundNetLog::Make(net_log_, |
| 1371 NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST); | 1550 NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST); |
| 1372 | 1551 |
| 1373 // Update the net log and notify registered observers. | 1552 // Update the net log and notify registered observers. |
| 1374 LogStartRequest(source_net_log, request_net_log, info); | 1553 LogStartRequest(source_net_log, request_net_log, info); |
| 1375 | 1554 |
| 1376 Key key = GetEffectiveKeyForRequest(info); | 1555 Key key = GetEffectiveKeyForRequest(info); |
| 1377 | 1556 |
| 1378 int rv = ResolveHelper(key, info, addresses, request_net_log); | 1557 int rv = ResolveHelper(key, info, addresses, request_net_log); |
| 1379 LogFinishRequest(source_net_log, request_net_log, info, rv, | 1558 LogFinishRequest(source_net_log, request_net_log, info, rv); |
| 1380 0 /* os_error (unknown since from cache) */); | |
| 1381 return rv; | 1559 return rv; |
| 1382 } | 1560 } |
| 1383 | 1561 |
| 1384 void HostResolverImpl::CancelRequest(RequestHandle req_handle) { | 1562 void HostResolverImpl::CancelRequest(RequestHandle req_handle) { |
| 1385 DCHECK(CalledOnValidThread()); | 1563 DCHECK(CalledOnValidThread()); |
| 1386 Request* req = reinterpret_cast<Request*>(req_handle); | 1564 Request* req = reinterpret_cast<Request*>(req_handle); |
| 1387 DCHECK(req); | 1565 DCHECK(req); |
| 1388 | 1566 |
| 1389 Job* job = req->job(); | 1567 Job* job = req->job(); |
| 1390 DCHECK(job); | 1568 DCHECK(job); |
| 1391 | 1569 |
| 1392 job->CancelRequest(req); | 1570 job->CancelRequest(req); |
| 1393 | 1571 |
| 1394 if (!job->handle().is_null()) { | 1572 if (job->num_active_requests() == 0) { |
| 1395 // Still in queue. | 1573 // If we were called from a Requests' callback within Job::CompleteRequests, |
| 1396 if (job->num_active_requests()) { | 1574 // that Request could not have been cancelled, so job->num_active_requests() |
| 1397 job->set_handle(dispatcher_.ChangePriority(job->handle(), | 1575 // could not be 0. Therefore, we are not in Job::CompleteRequests(). |
| 1398 job->priority())); | 1576 RemoveJob(job); |
| 1399 } else { | 1577 if (job->is_running()) |
| 1400 dispatcher_.Cancel(job->handle()); | |
| 1401 RemoveJob(job); | |
| 1402 delete job; | |
| 1403 } | |
| 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(); | 1578 job->Abort(); |
| 1410 } | 1579 delete job; |
| 1411 } | 1580 } |
| 1412 } | 1581 } |
| 1413 | 1582 |
| 1414 void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) { | 1583 void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) { |
| 1415 DCHECK(CalledOnValidThread()); | 1584 DCHECK(CalledOnValidThread()); |
| 1416 ipv6_probe_monitoring_ = false; | 1585 ipv6_probe_monitoring_ = false; |
| 1417 DiscardIPv6ProbeJob(); | 1586 DiscardIPv6ProbeJob(); |
| 1418 default_address_family_ = address_family; | 1587 default_address_family_ = address_family; |
| 1419 } | 1588 } |
| 1420 | 1589 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1475 if (!cache_entry) | 1644 if (!cache_entry) |
| 1476 return false; | 1645 return false; |
| 1477 | 1646 |
| 1478 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL); | 1647 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL); |
| 1479 *net_error = cache_entry->error; | 1648 *net_error = cache_entry->error; |
| 1480 if (*net_error == OK) | 1649 if (*net_error == OK) |
| 1481 *addresses = CreateAddressListUsingPort(cache_entry->addrlist, info.port()); | 1650 *addresses = CreateAddressListUsingPort(cache_entry->addrlist, info.port()); |
| 1482 return true; | 1651 return true; |
| 1483 } | 1652 } |
| 1484 | 1653 |
| 1485 void HostResolverImpl::OnJobFinished(Job* job, const AddressList& addrlist) { | 1654 void HostResolverImpl::OnJobFinished(Job* job, |
| 1655 int net_error, |
| 1656 const AddressList& addr_list, |
| 1657 base::TimeDelta ttl) { |
| 1486 DCHECK(job); | 1658 DCHECK(job); |
| 1487 DCHECK(job->handle().is_null()); | 1659 DCHECK(!job->is_queued()); |
| 1660 DCHECK_NE(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, net_error); |
| 1661 DCHECK_NE(ERR_ABORTED, net_error); |
| 1662 |
| 1488 RemoveJob(job); | 1663 RemoveJob(job); |
| 1489 if (job->net_error() == ERR_HOST_RESOLVER_QUEUE_TOO_LARGE) | |
| 1490 return; | |
| 1491 | |
| 1492 // Signal dispatcher that a slot has opened. | 1664 // Signal dispatcher that a slot has opened. |
| 1493 dispatcher_.OnJobFinished(); | 1665 dispatcher_.OnJobFinished(); |
| 1494 if (job->net_error() == ERR_ABORTED) | |
| 1495 return; | |
| 1496 // Write result to the cache. | 1666 // Write result to the cache. |
| 1497 if (cache_.get()) { | 1667 if (cache_.get()) { |
| 1498 base::TimeDelta ttl = base::TimeDelta::FromSeconds(0); | 1668 cache_->Set(job->key(), net_error, addr_list, |
| 1499 if (job->net_error() == OK) | |
| 1500 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); | |
| 1501 cache_->Set(job->key(), job->net_error(), addrlist, | |
| 1502 base::TimeTicks::Now(), ttl); | 1669 base::TimeTicks::Now(), ttl); |
| 1503 } | 1670 } |
| 1504 } | 1671 } |
| 1505 | 1672 |
| 1506 void HostResolverImpl::RemoveJob(Job* job) { | 1673 void HostResolverImpl::RemoveJob(Job* job) { |
| 1507 DCHECK(job); | 1674 DCHECK(job); |
| 1508 jobs_.erase(job->key()); | 1675 jobs_.erase(job->key()); |
| 1509 } | 1676 } |
| 1510 | 1677 |
| 1511 void HostResolverImpl::DiscardIPv6ProbeJob() { | 1678 void HostResolverImpl::DiscardIPv6ProbeJob() { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1538 default_address_family_ != ADDRESS_FAMILY_UNSPECIFIED) { | 1705 default_address_family_ != ADDRESS_FAMILY_UNSPECIFIED) { |
| 1539 effective_address_family = default_address_family_; | 1706 effective_address_family = default_address_family_; |
| 1540 if (ipv6_probe_monitoring_) | 1707 if (ipv6_probe_monitoring_) |
| 1541 effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; | 1708 effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; |
| 1542 } | 1709 } |
| 1543 return Key(info.hostname(), effective_address_family, effective_flags); | 1710 return Key(info.hostname(), effective_address_family, effective_flags); |
| 1544 } | 1711 } |
| 1545 | 1712 |
| 1546 void HostResolverImpl::AbortAllInProgressJobs() { | 1713 void HostResolverImpl::AbortAllInProgressJobs() { |
| 1547 base::WeakPtr<HostResolverImpl> self = AsWeakPtr(); | 1714 base::WeakPtr<HostResolverImpl> self = AsWeakPtr(); |
| 1548 // Scan |jobs_| for running jobs and abort them. | 1715 // In Abort, a Request callback could spawn new Jobs with matching keys, so |
| 1716 // first collect and remove all running jobs from |jobs_|. |
| 1717 std::vector<Job*> jobs_to_abort; |
| 1549 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ) { | 1718 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ) { |
| 1550 Job* job = it->second; | 1719 Job* job = it->second; |
| 1551 // Advance the iterator before we might erase it. | |
| 1552 ++it; | |
| 1553 if (job->is_running()) { | 1720 if (job->is_running()) { |
| 1554 job->Abort(); | 1721 jobs_to_abort.push_back(job); |
| 1555 // Check if resolver was deleted in a request callback. | 1722 jobs_.erase(it++); |
| 1556 if (!self) | |
| 1557 return; | |
| 1558 } else { | 1723 } else { |
| 1559 // Keep it in |dispatch_|. | 1724 DCHECK(job->is_queued()); |
| 1560 DCHECK(!job->handle().is_null()); | 1725 ++it; |
| 1561 } | 1726 } |
| 1562 } | 1727 } |
| 1728 |
| 1729 // Then Abort them and dispatch new Jobs. |
| 1730 for (size_t i = 0; i < jobs_to_abort.size(); ++i) { |
| 1731 jobs_to_abort[i]->Abort(); |
| 1732 dispatcher_.OnJobFinished(); |
| 1733 } |
| 1734 STLDeleteElements(&jobs_to_abort); |
| 1563 } | 1735 } |
| 1564 | 1736 |
| 1565 void HostResolverImpl::OnIPAddressChanged() { | 1737 void HostResolverImpl::OnIPAddressChanged() { |
| 1566 if (cache_.get()) | 1738 if (cache_.get()) |
| 1567 cache_->clear(); | 1739 cache_->clear(); |
| 1568 if (ipv6_probe_monitoring_) { | 1740 if (ipv6_probe_monitoring_) { |
| 1569 DiscardIPv6ProbeJob(); | 1741 DiscardIPv6ProbeJob(); |
| 1570 ipv6_probe_job_ = new IPv6ProbeJob(this); | 1742 ipv6_probe_job_ = new IPv6ProbeJob(this); |
| 1571 ipv6_probe_job_->Start(); | 1743 ipv6_probe_job_->Start(); |
| 1572 } | 1744 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1587 // as NSCD's cache should be dropped automatically by the OS when | 1759 // 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. | 1760 // resolv.conf changes so we don't need to do anything to clear that cache. |
| 1589 if (cache_.get()) | 1761 if (cache_.get()) |
| 1590 cache_->clear(); | 1762 cache_->clear(); |
| 1591 // Existing jobs will have been sent to the original server so they need to | 1763 // Existing jobs will have been sent to the original server so they need to |
| 1592 // be aborted. TODO(Craig): Should these jobs be restarted? | 1764 // be aborted. TODO(Craig): Should these jobs be restarted? |
| 1593 AbortAllInProgressJobs(); | 1765 AbortAllInProgressJobs(); |
| 1594 // |this| may be deleted inside AbortAllInProgressJobs(). | 1766 // |this| may be deleted inside AbortAllInProgressJobs(). |
| 1595 } | 1767 } |
| 1596 | 1768 |
| 1769 void HostResolverImpl::OnConfigChanged(const DnsConfig& dns_config) { |
| 1770 // We want a new factory in place, before we Abort running Jobs, so that the |
| 1771 // newly started jobs use the new factory. |
| 1772 bool had_factory = (dns_transaction_factory_.get() != NULL); |
| 1773 if (dns_config.IsValid()) { |
| 1774 dns_transaction_factory_ = DnsTransactionFactory::CreateFactory( |
| 1775 new DnsSession(dns_config, |
| 1776 ClientSocketFactory::GetDefaultFactory(), |
| 1777 base::Bind(&base::RandInt), |
| 1778 net_log_)); |
| 1779 } else { |
| 1780 dns_transaction_factory_.reset(); |
| 1781 } |
| 1782 // Don't Abort running Jobs unless they were running on DnsTransaction. |
| 1783 // TODO(szym): This will change once http://crbug.com/114827 is fixed. |
| 1784 if (had_factory) |
| 1785 OnDNSChanged(); |
| 1786 } |
| 1787 |
| 1597 } // namespace net | 1788 } // namespace net |
| OLD | NEW |