OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 #include "net/base/net_log.h" | 6 #include "net/base/net_log.h" |
7 | 7 |
8 #include <cmath> | 8 #include <cmath> |
9 #include <deque> | 9 #include <deque> |
10 | 10 |
11 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
13 #include "base/debug_util.h" | 13 #include "base/debug_util.h" |
14 #include "base/lock.h" | 14 #include "base/lock.h" |
15 #include "base/message_loop.h" | 15 #include "base/message_loop.h" |
16 #include "base/stl_util-inl.h" | 16 #include "base/stl_util-inl.h" |
17 #include "base/string_util.h" | 17 #include "base/string_util.h" |
18 #include "base/time.h" | 18 #include "base/time.h" |
19 #include "base/worker_pool.h" | 19 #include "base/worker_pool.h" |
20 #include "net/base/address_list.h" | 20 #include "net/base/address_list.h" |
21 #include "net/base/host_resolver_proc.h" | 21 #include "net/base/host_resolver_proc.h" |
22 #include "net/base/net_log.h" | 22 #include "net/base/net_log.h" |
23 #include "net/base/net_errors.h" | 23 #include "net/base/net_errors.h" |
| 24 #include "net/base/net_util.h" |
24 #include "net/base/network_change_notifier.h" | 25 #include "net/base/network_change_notifier.h" |
25 | 26 |
26 #if defined(OS_WIN) | 27 #if defined(OS_WIN) |
27 #include "net/base/winsock_init.h" | 28 #include "net/base/winsock_init.h" |
28 #endif | 29 #endif |
29 | 30 |
30 namespace net { | 31 namespace net { |
31 | 32 |
32 namespace { | 33 namespace { |
33 | 34 |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 | 186 |
186 //----------------------------------------------------------------------------- | 187 //----------------------------------------------------------------------------- |
187 | 188 |
188 // This class represents a request to the worker pool for a "getaddrinfo()" | 189 // This class represents a request to the worker pool for a "getaddrinfo()" |
189 // call. | 190 // call. |
190 class HostResolverImpl::Job | 191 class HostResolverImpl::Job |
191 : public base::RefCountedThreadSafe<HostResolverImpl::Job> { | 192 : public base::RefCountedThreadSafe<HostResolverImpl::Job> { |
192 public: | 193 public: |
193 Job(int id, HostResolverImpl* resolver, const Key& key, | 194 Job(int id, HostResolverImpl* resolver, const Key& key, |
194 RequestsTrace* requests_trace) | 195 RequestsTrace* requests_trace) |
195 : id_(id), key_(key), | 196 : id_(id), |
| 197 key_(key), |
196 resolver_(resolver), | 198 resolver_(resolver), |
197 origin_loop_(MessageLoop::current()), | 199 origin_loop_(MessageLoop::current()), |
198 resolver_proc_(resolver->effective_resolver_proc()), | 200 resolver_proc_(resolver->effective_resolver_proc()), |
199 requests_trace_(requests_trace), | 201 requests_trace_(requests_trace), |
200 error_(OK), | 202 error_(OK), |
201 had_non_speculative_request_(false) { | 203 had_non_speculative_request_(false) { |
202 if (requests_trace_) { | 204 if (requests_trace_) { |
203 requests_trace_->Add(StringPrintf( | 205 requests_trace_->Add(StringPrintf( |
204 "Created job j%d for {hostname='%s', address_family=%d}", | 206 "Created job j%d for {hostname='%s', address_family=%d}", |
205 id_, key.hostname.c_str(), | 207 id_, key.hostname.c_str(), |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 AddressList results_; | 416 AddressList results_; |
415 | 417 |
416 // The time when the job was started. | 418 // The time when the job was started. |
417 base::TimeTicks start_time_; | 419 base::TimeTicks start_time_; |
418 | 420 |
419 DISALLOW_COPY_AND_ASSIGN(Job); | 421 DISALLOW_COPY_AND_ASSIGN(Job); |
420 }; | 422 }; |
421 | 423 |
422 //----------------------------------------------------------------------------- | 424 //----------------------------------------------------------------------------- |
423 | 425 |
| 426 // This class represents a request to the worker pool for a "probe for IPv6 |
| 427 // support" call. |
| 428 class HostResolverImpl::IPv6ProbeJob |
| 429 : public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> { |
| 430 public: |
| 431 explicit IPv6ProbeJob(HostResolverImpl* resolver) |
| 432 : resolver_(resolver), |
| 433 origin_loop_(MessageLoop::current()) { |
| 434 } |
| 435 |
| 436 void Start() { |
| 437 DCHECK(IsOnOriginThread()); |
| 438 const bool IS_SLOW = true; |
| 439 WorkerPool::PostTask( |
| 440 FROM_HERE, NewRunnableMethod(this, &IPv6ProbeJob::DoProbe), IS_SLOW); |
| 441 } |
| 442 |
| 443 // Cancels the current job. |
| 444 void Cancel() { |
| 445 DCHECK(IsOnOriginThread()); |
| 446 resolver_ = NULL; // Read/write ONLY on origin thread. |
| 447 { |
| 448 AutoLock locked(origin_loop_lock_); |
| 449 // Origin loop may be destroyed before we can use it! |
| 450 origin_loop_ = NULL; |
| 451 } |
| 452 } |
| 453 |
| 454 bool was_cancelled() const { |
| 455 DCHECK(IsOnOriginThread()); |
| 456 return resolver_ == NULL; |
| 457 } |
| 458 |
| 459 private: |
| 460 friend class base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob>; |
| 461 |
| 462 ~IPv6ProbeJob() { |
| 463 } |
| 464 |
| 465 // Run on worker thread. |
| 466 void DoProbe() { |
| 467 // Do actual testing on this thread, as it takes 40-100ms. |
| 468 AddressFamily family = IPv6Supported() ? ADDRESS_FAMILY_UNSPECIFIED |
| 469 : ADDRESS_FAMILY_IPV4; |
| 470 |
| 471 Task* reply = NewRunnableMethod(this, &IPv6ProbeJob::OnProbeComplete, |
| 472 family); |
| 473 |
| 474 // The origin loop could go away while we are trying to post to it, so we |
| 475 // need to call its PostTask method inside a lock. See ~HostResolver. |
| 476 { |
| 477 AutoLock locked(origin_loop_lock_); |
| 478 if (origin_loop_) { |
| 479 origin_loop_->PostTask(FROM_HERE, reply); |
| 480 return; |
| 481 } |
| 482 } |
| 483 |
| 484 // We didn't post, so delete the reply. |
| 485 delete reply; |
| 486 } |
| 487 |
| 488 // Callback for when DoProbe() completes (runs on origin thread). |
| 489 void OnProbeComplete(AddressFamily address_family) { |
| 490 DCHECK(IsOnOriginThread()); |
| 491 if (!was_cancelled()) |
| 492 resolver_->IPv6ProbeSetDefaultAddressFamily(address_family); |
| 493 } |
| 494 |
| 495 bool IsOnOriginThread() const { |
| 496 return !MessageLoop::current() || origin_loop_ == MessageLoop::current(); |
| 497 } |
| 498 |
| 499 // Used/set only on origin thread. |
| 500 HostResolverImpl* resolver_; |
| 501 |
| 502 // Used to post ourselves onto the origin thread. |
| 503 Lock origin_loop_lock_; |
| 504 MessageLoop* origin_loop_; |
| 505 |
| 506 DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); |
| 507 }; |
| 508 |
| 509 //----------------------------------------------------------------------------- |
| 510 |
424 // We rely on the priority enum values being sequential having starting at 0, | 511 // We rely on the priority enum values being sequential having starting at 0, |
425 // and increasing for lower priorities. | 512 // and increasing for lower priorities. |
426 COMPILE_ASSERT(HIGHEST == 0u && | 513 COMPILE_ASSERT(HIGHEST == 0u && |
427 LOWEST > HIGHEST && | 514 LOWEST > HIGHEST && |
428 NUM_PRIORITIES > LOWEST, | 515 NUM_PRIORITIES > LOWEST, |
429 priority_indexes_incompatible); | 516 priority_indexes_incompatible); |
430 | 517 |
431 // JobPool contains all the information relating to queued requests, including | 518 // JobPool contains all the information relating to queued requests, including |
432 // the limits on how many jobs are allowed to be used for this category of | 519 // the limits on how many jobs are allowed to be used for this category of |
433 // requests. | 520 // requests. |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 HostCache* cache, | 661 HostCache* cache, |
575 NetworkChangeNotifier* network_change_notifier, | 662 NetworkChangeNotifier* network_change_notifier, |
576 size_t max_jobs) | 663 size_t max_jobs) |
577 : cache_(cache), | 664 : cache_(cache), |
578 max_jobs_(max_jobs), | 665 max_jobs_(max_jobs), |
579 next_request_id_(0), | 666 next_request_id_(0), |
580 next_job_id_(0), | 667 next_job_id_(0), |
581 resolver_proc_(resolver_proc), | 668 resolver_proc_(resolver_proc), |
582 default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), | 669 default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), |
583 shutdown_(false), | 670 shutdown_(false), |
584 network_change_notifier_(network_change_notifier) { | 671 network_change_notifier_(network_change_notifier), |
| 672 ipv6_probe_monitoring_(false) { |
585 DCHECK_GT(max_jobs, 0u); | 673 DCHECK_GT(max_jobs, 0u); |
586 | 674 |
587 // It is cumbersome to expose all of the constraints in the constructor, | 675 // It is cumbersome to expose all of the constraints in the constructor, |
588 // so we choose some defaults, which users can override later. | 676 // so we choose some defaults, which users can override later. |
589 job_pools_[POOL_NORMAL] = new JobPool(max_jobs, 100u * max_jobs); | 677 job_pools_[POOL_NORMAL] = new JobPool(max_jobs, 100u * max_jobs); |
590 | 678 |
591 #if defined(OS_WIN) | 679 #if defined(OS_WIN) |
592 EnsureWinsockInit(); | 680 EnsureWinsockInit(); |
593 #endif | 681 #endif |
594 if (network_change_notifier_) | 682 if (network_change_notifier_) |
595 network_change_notifier_->AddObserver(this); | 683 network_change_notifier_->AddObserver(this); |
596 } | 684 } |
597 | 685 |
598 HostResolverImpl::~HostResolverImpl() { | 686 HostResolverImpl::~HostResolverImpl() { |
599 // Cancel the outstanding jobs. Those jobs may contain several attached | 687 // Cancel the outstanding jobs. Those jobs may contain several attached |
600 // requests, which will also be cancelled. | 688 // requests, which will also be cancelled. |
| 689 DiscardIPv6ProbeJob(); |
| 690 |
601 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it) | 691 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it) |
602 it->second->Cancel(); | 692 it->second->Cancel(); |
603 | 693 |
604 // In case we are being deleted during the processing of a callback. | 694 // In case we are being deleted during the processing of a callback. |
605 if (cur_completing_job_) | 695 if (cur_completing_job_) |
606 cur_completing_job_->Cancel(); | 696 cur_completing_job_->Cancel(); |
607 | 697 |
608 if (network_change_notifier_) | 698 if (network_change_notifier_) |
609 network_change_notifier_->RemoveObserver(this); | 699 network_change_notifier_->RemoveObserver(this); |
610 | 700 |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
735 void HostResolverImpl::RemoveObserver(HostResolver::Observer* observer) { | 825 void HostResolverImpl::RemoveObserver(HostResolver::Observer* observer) { |
736 ObserversList::iterator it = | 826 ObserversList::iterator it = |
737 std::find(observers_.begin(), observers_.end(), observer); | 827 std::find(observers_.begin(), observers_.end(), observer); |
738 | 828 |
739 // Observer must exist. | 829 // Observer must exist. |
740 DCHECK(it != observers_.end()); | 830 DCHECK(it != observers_.end()); |
741 | 831 |
742 observers_.erase(it); | 832 observers_.erase(it); |
743 } | 833 } |
744 | 834 |
| 835 void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) { |
| 836 ipv6_probe_monitoring_ = false; |
| 837 DiscardIPv6ProbeJob(); |
| 838 default_address_family_ = address_family; |
| 839 } |
| 840 |
| 841 void HostResolverImpl::ProbeIPv6Support() { |
| 842 DCHECK(!ipv6_probe_monitoring_); |
| 843 ipv6_probe_monitoring_ = true; |
| 844 OnIPAddressChanged(); // Give initial setup call. |
| 845 } |
| 846 |
745 void HostResolverImpl::Shutdown() { | 847 void HostResolverImpl::Shutdown() { |
746 shutdown_ = true; | 848 shutdown_ = true; |
747 | 849 |
748 // Cancel the outstanding jobs. | 850 // Cancel the outstanding jobs. |
749 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it) | 851 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it) |
750 it->second->Cancel(); | 852 it->second->Cancel(); |
751 jobs_.clear(); | 853 jobs_.clear(); |
752 } | 854 } |
753 | 855 |
754 void HostResolverImpl::ClearRequestsTrace() { | 856 void HostResolverImpl::ClearRequestsTrace() { |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
968 | 1070 |
969 net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_OBSERVER_ONCANCEL); | 1071 net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_OBSERVER_ONCANCEL); |
970 } | 1072 } |
971 | 1073 |
972 net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL); | 1074 net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL); |
973 } | 1075 } |
974 | 1076 |
975 void HostResolverImpl::OnIPAddressChanged() { | 1077 void HostResolverImpl::OnIPAddressChanged() { |
976 if (cache_.get()) | 1078 if (cache_.get()) |
977 cache_->clear(); | 1079 cache_->clear(); |
| 1080 if (ipv6_probe_monitoring_) { |
| 1081 DiscardIPv6ProbeJob(); |
| 1082 ipv6_probe_job_ = new IPv6ProbeJob(this); |
| 1083 ipv6_probe_job_->Start(); |
| 1084 } |
| 1085 } |
| 1086 |
| 1087 void HostResolverImpl::DiscardIPv6ProbeJob() { |
| 1088 if (ipv6_probe_job_.get()) { |
| 1089 ipv6_probe_job_->Cancel(); |
| 1090 ipv6_probe_job_ = NULL; |
| 1091 } |
| 1092 } |
| 1093 |
| 1094 void HostResolverImpl::IPv6ProbeSetDefaultAddressFamily( |
| 1095 AddressFamily address_family) { |
| 1096 DCHECK(address_family == ADDRESS_FAMILY_UNSPECIFIED || |
| 1097 address_family == ADDRESS_FAMILY_IPV4); |
| 1098 if (default_address_family_ != address_family) |
| 1099 LOG(INFO) << "IPv6Probe forced AddressFamily setting to " |
| 1100 << ((address_family == ADDRESS_FAMILY_UNSPECIFIED) |
| 1101 ? "ADDRESS_FAMILY_UNSPECIFIED" |
| 1102 : "ADDRESS_FAMILY_IPV4"); |
| 1103 default_address_family_ = address_family; |
| 1104 // Drop reference since the job has called us back. |
| 1105 DiscardIPv6ProbeJob(); |
978 } | 1106 } |
979 | 1107 |
980 // static | 1108 // static |
981 HostResolverImpl::JobPoolIndex HostResolverImpl::GetJobPoolIndexForRequest( | 1109 HostResolverImpl::JobPoolIndex HostResolverImpl::GetJobPoolIndexForRequest( |
982 const Request* req) { | 1110 const Request* req) { |
983 return POOL_NORMAL; | 1111 return POOL_NORMAL; |
984 } | 1112 } |
985 | 1113 |
986 bool HostResolverImpl::CanCreateJobForPool(const JobPool& pool) const { | 1114 bool HostResolverImpl::CanCreateJobForPool(const JobPool& pool) const { |
987 DCHECK_LE(jobs_.size(), max_jobs_); | 1115 DCHECK_LE(jobs_.size(), max_jobs_); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1055 if (r == req) | 1183 if (r == req) |
1056 return error; | 1184 return error; |
1057 | 1185 |
1058 r->OnComplete(error, AddressList()); | 1186 r->OnComplete(error, AddressList()); |
1059 } | 1187 } |
1060 | 1188 |
1061 return ERR_IO_PENDING; | 1189 return ERR_IO_PENDING; |
1062 } | 1190 } |
1063 | 1191 |
1064 } // namespace net | 1192 } // namespace net |
OLD | NEW |