| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/socket/client_socket_pool_base.h" | 5 #include "net/socket/client_socket_pool_base.h" |
| 6 | 6 |
| 7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 #include "base/format_macros.h" | 8 #include "base/format_macros.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/stats_counters.h" | 10 #include "base/stats_counters.h" |
| 11 #include "base/stl_util-inl.h" | 11 #include "base/stl_util-inl.h" |
| 12 #include "base/string_util.h" | 12 #include "base/string_util.h" |
| 13 #include "base/time.h" | 13 #include "base/time.h" |
| 14 #include "net/base/net_log.h" | 14 #include "net/base/net_log.h" |
| 15 #include "net/base/net_errors.h" | 15 #include "net/base/net_errors.h" |
| 16 #include "net/socket/client_socket_handle.h" | 16 #include "net/socket/client_socket_handle.h" |
| 17 | 17 |
| 18 using base::TimeDelta; | 18 using base::TimeDelta; |
| 19 | 19 |
| 20 namespace { | 20 namespace { |
| 21 | 21 |
| 22 // The timeout value, in seconds, used to clean up idle sockets that can't be | 22 // The timeout value, in seconds, used to clean up idle sockets that can't be |
| 23 // reused. | 23 // reused. |
| 24 // | 24 // |
| 25 // Note: It's important to close idle sockets that have received data as soon | 25 // Note: It's important to close idle sockets that have received data as soon |
| 26 // as possible because the received data may cause BSOD on Windows XP under | 26 // as possible because the received data may cause BSOD on Windows XP under |
| 27 // some conditions. See http://crbug.com/4606. | 27 // some conditions. See http://crbug.com/4606. |
| 28 const int kCleanupInterval = 10; // DO NOT INCREASE THIS TIMEOUT. | 28 const int kCleanupInterval = 10; // DO NOT INCREASE THIS TIMEOUT. |
| 29 | 29 |
| 30 // Indicate whether or not we should establish a new TCP connection after a |
| 31 // certain timeout has passed without receiving an ACK. |
| 32 bool g_connect_backup_jobs_enabled = true; |
| 33 |
| 30 } // namespace | 34 } // namespace |
| 31 | 35 |
| 32 namespace net { | 36 namespace net { |
| 33 | 37 |
| 34 ConnectJob::ConnectJob(const std::string& group_name, | 38 ConnectJob::ConnectJob(const std::string& group_name, |
| 35 base::TimeDelta timeout_duration, | 39 base::TimeDelta timeout_duration, |
| 36 Delegate* delegate, | 40 Delegate* delegate, |
| 37 const BoundNetLog& net_log) | 41 const BoundNetLog& net_log) |
| 38 : group_name_(group_name), | 42 : group_name_(group_name), |
| 39 timeout_duration_(timeout_duration), | 43 timeout_duration_(timeout_duration), |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 base::TimeDelta used_idle_socket_timeout, | 134 base::TimeDelta used_idle_socket_timeout, |
| 131 ConnectJobFactory* connect_job_factory) | 135 ConnectJobFactory* connect_job_factory) |
| 132 : idle_socket_count_(0), | 136 : idle_socket_count_(0), |
| 133 connecting_socket_count_(0), | 137 connecting_socket_count_(0), |
| 134 handed_out_socket_count_(0), | 138 handed_out_socket_count_(0), |
| 135 max_sockets_(max_sockets), | 139 max_sockets_(max_sockets), |
| 136 max_sockets_per_group_(max_sockets_per_group), | 140 max_sockets_per_group_(max_sockets_per_group), |
| 137 unused_idle_socket_timeout_(unused_idle_socket_timeout), | 141 unused_idle_socket_timeout_(unused_idle_socket_timeout), |
| 138 used_idle_socket_timeout_(used_idle_socket_timeout), | 142 used_idle_socket_timeout_(used_idle_socket_timeout), |
| 139 connect_job_factory_(connect_job_factory), | 143 connect_job_factory_(connect_job_factory), |
| 140 backup_jobs_enabled_(false), | 144 connect_backup_jobs_enabled_(false), |
| 141 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), | 145 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), |
| 142 pool_generation_number_(0), | 146 pool_generation_number_(0), |
| 143 in_destructor_(false) { | 147 in_destructor_(false) { |
| 144 DCHECK_LE(0, max_sockets_per_group); | 148 DCHECK_LE(0, max_sockets_per_group); |
| 145 DCHECK_LE(max_sockets_per_group, max_sockets); | 149 DCHECK_LE(max_sockets_per_group, max_sockets); |
| 146 | 150 |
| 147 NetworkChangeNotifier::AddObserver(this); | 151 NetworkChangeNotifier::AddObserver(this); |
| 148 } | 152 } |
| 149 | 153 |
| 150 ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() { | 154 ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 | 244 |
| 241 int rv = connect_job->Connect(); | 245 int rv = connect_job->Connect(); |
| 242 if (rv == OK) { | 246 if (rv == OK) { |
| 243 LogBoundConnectJobToRequest(connect_job->net_log().source(), request); | 247 LogBoundConnectJobToRequest(connect_job->net_log().source(), request); |
| 244 HandOutSocket(connect_job->ReleaseSocket(), false /* not reused */, | 248 HandOutSocket(connect_job->ReleaseSocket(), false /* not reused */, |
| 245 handle, base::TimeDelta(), &group, request->net_log()); | 249 handle, base::TimeDelta(), &group, request->net_log()); |
| 246 } else if (rv == ERR_IO_PENDING) { | 250 } else if (rv == ERR_IO_PENDING) { |
| 247 // If we don't have any sockets in this group, set a timer for potentially | 251 // If we don't have any sockets in this group, set a timer for potentially |
| 248 // creating a new one. If the SYN is lost, this backup socket may complete | 252 // creating a new one. If the SYN is lost, this backup socket may complete |
| 249 // before the slow socket, improving end user latency. | 253 // before the slow socket, improving end user latency. |
| 250 if (group.IsEmpty() && !group.backup_job && backup_jobs_enabled_) { | 254 if (group.IsEmpty() && !group.connect_backup_job && |
| 251 group.backup_job = connect_job_factory_->NewConnectJob(group_name, | 255 connect_backup_jobs_enabled_) { |
| 252 *request, | 256 group.connect_backup_job = connect_job_factory_->NewConnectJob(group_name, |
| 253 this); | 257 *request, |
| 258 this); |
| 254 StartBackupSocketTimer(group_name); | 259 StartBackupSocketTimer(group_name); |
| 255 } | 260 } |
| 256 | 261 |
| 257 connecting_socket_count_++; | 262 connecting_socket_count_++; |
| 258 | 263 |
| 259 ConnectJob* job = connect_job.release(); | 264 ConnectJob* job = connect_job.release(); |
| 260 group.jobs.insert(job); | 265 group.jobs.insert(job); |
| 261 } else { | 266 } else { |
| 262 LogBoundConnectJobToRequest(connect_job->net_log().source(), request); | 267 LogBoundConnectJobToRequest(connect_job->net_log().source(), request); |
| 263 connect_job->GetAdditionalErrorState(handle); | 268 connect_job->GetAdditionalErrorState(handle); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 | 325 |
| 321 void ClientSocketPoolBaseHelper::OnBackupSocketTimerFired( | 326 void ClientSocketPoolBaseHelper::OnBackupSocketTimerFired( |
| 322 const std::string& group_name) { | 327 const std::string& group_name) { |
| 323 CHECK(ContainsKey(group_map_, group_name)); | 328 CHECK(ContainsKey(group_map_, group_name)); |
| 324 | 329 |
| 325 Group& group = group_map_[group_name]; | 330 Group& group = group_map_[group_name]; |
| 326 | 331 |
| 327 CHECK(group.backup_task); | 332 CHECK(group.backup_task); |
| 328 group.backup_task = NULL; | 333 group.backup_task = NULL; |
| 329 | 334 |
| 330 CHECK(group.backup_job); | 335 CHECK(group.connect_backup_job); |
| 331 | 336 |
| 332 // If there are no more jobs pending, there is no work to do. | 337 // If there are no more jobs pending, there is no work to do. |
| 333 // If we've done our cleanups correctly, this should not happen. | 338 // If we've done our cleanups correctly, this should not happen. |
| 334 if (group.jobs.empty()) { | 339 if (group.jobs.empty()) { |
| 335 NOTREACHED(); | 340 NOTREACHED(); |
| 336 return; | 341 return; |
| 337 } | 342 } |
| 338 | 343 |
| 339 // If our backup job is waiting on DNS, or if we can't create any sockets | 344 // If our backup job is waiting on DNS, or if we can't create any sockets |
| 340 // right now due to limits, just reset the timer. | 345 // right now due to limits, just reset the timer. |
| 341 if (ReachedMaxSocketsLimit() || | 346 if (ReachedMaxSocketsLimit() || |
| 342 !group.HasAvailableSocketSlot(max_sockets_per_group_) || | 347 !group.HasAvailableSocketSlot(max_sockets_per_group_) || |
| 343 (*group.jobs.begin())->GetLoadState() == LOAD_STATE_RESOLVING_HOST) { | 348 (*group.jobs.begin())->GetLoadState() == LOAD_STATE_RESOLVING_HOST) { |
| 344 StartBackupSocketTimer(group_name); | 349 StartBackupSocketTimer(group_name); |
| 345 return; | 350 return; |
| 346 } | 351 } |
| 347 | 352 |
| 348 group.backup_job->net_log().AddEvent(NetLog::TYPE_SOCKET_BACKUP_CREATED, | 353 group.connect_backup_job->net_log().AddEvent( |
| 349 NULL); | 354 NetLog::TYPE_SOCKET_BACKUP_CREATED, |
| 355 NULL); |
| 350 SIMPLE_STATS_COUNTER("socket.backup_created"); | 356 SIMPLE_STATS_COUNTER("socket.backup_created"); |
| 351 int rv = group.backup_job->Connect(); | 357 int rv = group.connect_backup_job->Connect(); |
| 352 connecting_socket_count_++; | 358 connecting_socket_count_++; |
| 353 group.jobs.insert(group.backup_job); | 359 group.jobs.insert(group.connect_backup_job); |
| 354 ConnectJob* job = group.backup_job; | 360 ConnectJob* job = group.connect_backup_job; |
| 355 group.backup_job = NULL; | 361 group.connect_backup_job = NULL; |
| 356 if (rv != ERR_IO_PENDING) | 362 if (rv != ERR_IO_PENDING) |
| 357 OnConnectJobComplete(rv, job); | 363 OnConnectJobComplete(rv, job); |
| 358 } | 364 } |
| 359 | 365 |
| 360 void ClientSocketPoolBaseHelper::CancelRequest( | 366 void ClientSocketPoolBaseHelper::CancelRequest( |
| 361 const std::string& group_name, ClientSocketHandle* handle) { | 367 const std::string& group_name, ClientSocketHandle* handle) { |
| 362 PendingCallbackMap::iterator callback_it = pending_callback_map_.find(handle); | 368 PendingCallbackMap::iterator callback_it = pending_callback_map_.find(handle); |
| 363 if (callback_it != pending_callback_map_.end()) { | 369 if (callback_it != pending_callback_map_.end()) { |
| 364 int result = callback_it->second.result; | 370 int result = callback_it->second.result; |
| 365 pending_callback_map_.erase(callback_it); | 371 pending_callback_map_.erase(callback_it); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 | 494 |
| 489 // Delete group if no longer needed. | 495 // Delete group if no longer needed. |
| 490 if (group.IsEmpty()) { | 496 if (group.IsEmpty()) { |
| 491 group_map_.erase(i++); | 497 group_map_.erase(i++); |
| 492 } else { | 498 } else { |
| 493 ++i; | 499 ++i; |
| 494 } | 500 } |
| 495 } | 501 } |
| 496 } | 502 } |
| 497 | 503 |
| 504 // static |
| 505 void ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(bool enabled) { |
| 506 g_connect_backup_jobs_enabled = enabled; |
| 507 } |
| 508 |
| 509 void ClientSocketPoolBaseHelper::EnableConnectBackupJobs() { |
| 510 connect_backup_jobs_enabled_ = g_connect_backup_jobs_enabled; |
| 511 } |
| 512 |
| 498 void ClientSocketPoolBaseHelper::IncrementIdleCount() { | 513 void ClientSocketPoolBaseHelper::IncrementIdleCount() { |
| 499 if (++idle_socket_count_ == 1) | 514 if (++idle_socket_count_ == 1) |
| 500 timer_.Start(TimeDelta::FromSeconds(kCleanupInterval), this, | 515 timer_.Start(TimeDelta::FromSeconds(kCleanupInterval), this, |
| 501 &ClientSocketPoolBaseHelper::OnCleanupTimerFired); | 516 &ClientSocketPoolBaseHelper::OnCleanupTimerFired); |
| 502 } | 517 } |
| 503 | 518 |
| 504 void ClientSocketPoolBaseHelper::DecrementIdleCount() { | 519 void ClientSocketPoolBaseHelper::DecrementIdleCount() { |
| 505 if (--idle_socket_count_ == 0) | 520 if (--idle_socket_count_ == 0) |
| 506 timer_.Stop(); | 521 timer_.Stop(); |
| 507 } | 522 } |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 CHECK(!handle->is_initialized()); | 830 CHECK(!handle->is_initialized()); |
| 816 CompletionCallback* callback = it->second.callback; | 831 CompletionCallback* callback = it->second.callback; |
| 817 int result = it->second.result; | 832 int result = it->second.result; |
| 818 pending_callback_map_.erase(it); | 833 pending_callback_map_.erase(it); |
| 819 callback->Run(result); | 834 callback->Run(result); |
| 820 } | 835 } |
| 821 | 836 |
| 822 } // namespace internal | 837 } // namespace internal |
| 823 | 838 |
| 824 } // namespace net | 839 } // namespace net |
| OLD | NEW |