| 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 // A ClientSocketPoolBase is used to restrict the number of sockets open at | 5 // A ClientSocketPoolBase is used to restrict the number of sockets open at |
| 6 // a time. It also maintains a list of idle persistent sockets for reuse. | 6 // a time. It also maintains a list of idle persistent sockets for reuse. |
| 7 // Subclasses of ClientSocketPool should compose ClientSocketPoolBase to handle | 7 // Subclasses of ClientSocketPool should compose ClientSocketPoolBase to handle |
| 8 // the core logic of (1) restricting the number of active (connected or | 8 // the core logic of (1) restricting the number of active (connected or |
| 9 // connecting) sockets per "group" (generally speaking, the hostname), (2) | 9 // connecting) sockets per "group" (generally speaking, the hostname), (2) |
| 10 // maintaining a per-group list of idle, persistent sockets for reuse, and (3) | 10 // maintaining a per-group list of idle, persistent sockets for reuse, and (3) |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 // cannot complete synchronously without blocking, or another net error code | 84 // cannot complete synchronously without blocking, or another net error code |
| 85 // on error. In asynchronous completion, the ConnectJob will notify | 85 // on error. In asynchronous completion, the ConnectJob will notify |
| 86 // |delegate_| via OnConnectJobComplete. In both asynchronous and synchronous | 86 // |delegate_| via OnConnectJobComplete. In both asynchronous and synchronous |
| 87 // completion, ReleaseSocket() can be called to acquire the connected socket | 87 // completion, ReleaseSocket() can be called to acquire the connected socket |
| 88 // if it succeeded. | 88 // if it succeeded. |
| 89 int Connect(); | 89 int Connect(); |
| 90 | 90 |
| 91 virtual LoadState GetLoadState() const = 0; | 91 virtual LoadState GetLoadState() const = 0; |
| 92 | 92 |
| 93 protected: | 93 protected: |
| 94 void set_socket(ClientSocket* socket) { socket_.reset(socket); } | 94 void set_socket(ClientSocket* socket); |
| 95 ClientSocket* socket() { return socket_.get(); } | 95 ClientSocket* socket() { return socket_.get(); } |
| 96 void NotifyDelegateOfCompletion(int rv); | 96 void NotifyDelegateOfCompletion(int rv); |
| 97 void ResetTimer(base::TimeDelta remainingTime); | 97 void ResetTimer(base::TimeDelta remainingTime); |
| 98 | 98 |
| 99 private: | 99 private: |
| 100 virtual int ConnectInternal() = 0; | 100 virtual int ConnectInternal() = 0; |
| 101 | 101 |
| 102 void LogConnectStart(); |
| 103 void LogConnectCompletion(int net_error); |
| 104 |
| 102 // Alerts the delegate that the ConnectJob has timed out. | 105 // Alerts the delegate that the ConnectJob has timed out. |
| 103 void OnTimeout(); | 106 void OnTimeout(); |
| 104 | 107 |
| 105 const std::string group_name_; | 108 const std::string group_name_; |
| 106 const base::TimeDelta timeout_duration_; | 109 const base::TimeDelta timeout_duration_; |
| 107 // Timer to abort jobs that take too long. | 110 // Timer to abort jobs that take too long. |
| 108 base::OneShotTimer<ConnectJob> timer_; | 111 base::OneShotTimer<ConnectJob> timer_; |
| 109 Delegate* delegate_; | 112 Delegate* delegate_; |
| 110 scoped_ptr<ClientSocket> socket_; | 113 scoped_ptr<ClientSocket> socket_; |
| 111 BoundNetLog net_log_; | 114 BoundNetLog net_log_; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 }; | 154 }; |
| 152 | 155 |
| 153 class ConnectJobFactory { | 156 class ConnectJobFactory { |
| 154 public: | 157 public: |
| 155 ConnectJobFactory() {} | 158 ConnectJobFactory() {} |
| 156 virtual ~ConnectJobFactory() {} | 159 virtual ~ConnectJobFactory() {} |
| 157 | 160 |
| 158 virtual ConnectJob* NewConnectJob( | 161 virtual ConnectJob* NewConnectJob( |
| 159 const std::string& group_name, | 162 const std::string& group_name, |
| 160 const Request& request, | 163 const Request& request, |
| 161 ConnectJob::Delegate* delegate, | 164 ConnectJob::Delegate* delegate) const = 0; |
| 162 const BoundNetLog& net_log) const = 0; | |
| 163 | 165 |
| 164 virtual base::TimeDelta ConnectionTimeout() const = 0; | 166 virtual base::TimeDelta ConnectionTimeout() const = 0; |
| 165 | 167 |
| 166 private: | 168 private: |
| 167 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); | 169 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); |
| 168 }; | 170 }; |
| 169 | 171 |
| 170 ClientSocketPoolBaseHelper( | 172 ClientSocketPoolBaseHelper( |
| 171 int max_sockets, | 173 int max_sockets, |
| 172 int max_sockets_per_group, | 174 int max_sockets_per_group, |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 } | 226 } |
| 225 | 227 |
| 226 // Closes all idle sockets if |force| is true. Else, only closes idle | 228 // Closes all idle sockets if |force| is true. Else, only closes idle |
| 227 // sockets that timed out or can't be reused. Made public for testing. | 229 // sockets that timed out or can't be reused. Made public for testing. |
| 228 void CleanupIdleSockets(bool force); | 230 void CleanupIdleSockets(bool force); |
| 229 | 231 |
| 230 base::TimeDelta ConnectionTimeout() const { | 232 base::TimeDelta ConnectionTimeout() const { |
| 231 return connect_job_factory_->ConnectionTimeout(); | 233 return connect_job_factory_->ConnectionTimeout(); |
| 232 } | 234 } |
| 233 | 235 |
| 234 void enable_backup_jobs() { backup_jobs_enabled_ = true; }; | 236 void enable_backup_jobs() { backup_jobs_enabled_ = true; } |
| 235 | 237 |
| 236 private: | 238 private: |
| 237 friend class base::RefCounted<ClientSocketPoolBaseHelper>; | 239 friend class base::RefCounted<ClientSocketPoolBaseHelper>; |
| 238 | 240 |
| 239 ~ClientSocketPoolBaseHelper(); | 241 ~ClientSocketPoolBaseHelper(); |
| 240 | 242 |
| 241 // Entry for a persistent socket which became idle at time |start_time|. | 243 // Entry for a persistent socket which became idle at time |start_time|. |
| 242 struct IdleSocket { | 244 struct IdleSocket { |
| 243 IdleSocket() : socket(NULL), used(false) {} | 245 IdleSocket() : socket(NULL), used(false) {} |
| 244 ClientSocket* socket; | 246 ClientSocket* socket; |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 // Returns true if we can't create any more sockets due to the total limit. | 382 // Returns true if we can't create any more sockets due to the total limit. |
| 381 // TODO(phajdan.jr): Also take idle sockets into account. | 383 // TODO(phajdan.jr): Also take idle sockets into account. |
| 382 bool ReachedMaxSocketsLimit() const; | 384 bool ReachedMaxSocketsLimit() const; |
| 383 | 385 |
| 384 // This is the internal implementation of RequestSocket(). It differs in that | 386 // This is the internal implementation of RequestSocket(). It differs in that |
| 385 // it does not handle logging into NetLog of the queueing status of | 387 // it does not handle logging into NetLog of the queueing status of |
| 386 // |request|. | 388 // |request|. |
| 387 int RequestSocketInternal(const std::string& group_name, | 389 int RequestSocketInternal(const std::string& group_name, |
| 388 const Request* request); | 390 const Request* request); |
| 389 | 391 |
| 392 static void LogBoundConnectJobToRequest( |
| 393 const NetLog::Source& connect_job_source, const Request* request); |
| 394 |
| 390 // Set a timer to create a backup socket if it takes too long to create one. | 395 // Set a timer to create a backup socket if it takes too long to create one. |
| 391 void StartBackupSocketTimer(const std::string& group_name); | 396 void StartBackupSocketTimer(const std::string& group_name); |
| 392 | 397 |
| 393 // Called when the backup socket timer fires. | 398 // Called when the backup socket timer fires. |
| 394 void OnBackupSocketTimerFired(const std::string& group_name); | 399 void OnBackupSocketTimerFired(const std::string& group_name); |
| 395 | 400 |
| 396 GroupMap group_map_; | 401 GroupMap group_map_; |
| 397 | 402 |
| 398 // Timer used to periodically prune idle sockets that timed out or can't be | 403 // Timer used to periodically prune idle sockets that timed out or can't be |
| 399 // reused. | 404 // reused. |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 }; | 484 }; |
| 480 | 485 |
| 481 class ConnectJobFactory { | 486 class ConnectJobFactory { |
| 482 public: | 487 public: |
| 483 ConnectJobFactory() {} | 488 ConnectJobFactory() {} |
| 484 virtual ~ConnectJobFactory() {} | 489 virtual ~ConnectJobFactory() {} |
| 485 | 490 |
| 486 virtual ConnectJob* NewConnectJob( | 491 virtual ConnectJob* NewConnectJob( |
| 487 const std::string& group_name, | 492 const std::string& group_name, |
| 488 const Request& request, | 493 const Request& request, |
| 489 ConnectJob::Delegate* delegate, | 494 ConnectJob::Delegate* delegate) const = 0; |
| 490 const BoundNetLog& net_log) const = 0; | |
| 491 | 495 |
| 492 virtual base::TimeDelta ConnectionTimeout() const = 0; | 496 virtual base::TimeDelta ConnectionTimeout() const = 0; |
| 493 | 497 |
| 494 private: | 498 private: |
| 495 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); | 499 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); |
| 496 }; | 500 }; |
| 497 | 501 |
| 498 // |max_sockets| is the maximum number of sockets to be maintained by this | 502 // |max_sockets| is the maximum number of sockets to be maintained by this |
| 499 // ClientSocketPool. |max_sockets_per_group| specifies the maximum number of | 503 // ClientSocketPool. |max_sockets_per_group| specifies the maximum number of |
| 500 // sockets a "group" can have. |unused_idle_socket_timeout| specifies how | 504 // sockets a "group" can have. |unused_idle_socket_timeout| specifies how |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 } | 577 } |
| 574 | 578 |
| 575 base::TimeDelta ConnectionTimeout() const { | 579 base::TimeDelta ConnectionTimeout() const { |
| 576 return helper_->ConnectionTimeout(); | 580 return helper_->ConnectionTimeout(); |
| 577 } | 581 } |
| 578 | 582 |
| 579 scoped_refptr<ClientSocketPoolHistograms> histograms() const { | 583 scoped_refptr<ClientSocketPoolHistograms> histograms() const { |
| 580 return histograms_; | 584 return histograms_; |
| 581 } | 585 } |
| 582 | 586 |
| 583 void enable_backup_jobs() { helper_->enable_backup_jobs(); }; | 587 void enable_backup_jobs() { helper_->enable_backup_jobs(); } |
| 584 | 588 |
| 585 private: | 589 private: |
| 586 // This adaptor class exists to bridge the | 590 // This adaptor class exists to bridge the |
| 587 // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and | 591 // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and |
| 588 // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the | 592 // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the |
| 589 // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to | 593 // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to |
| 590 // static_cast themselves. | 594 // static_cast themselves. |
| 591 class ConnectJobFactoryAdaptor | 595 class ConnectJobFactoryAdaptor |
| 592 : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory { | 596 : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory { |
| 593 public: | 597 public: |
| 594 typedef typename ClientSocketPoolBase<SocketParams>::ConnectJobFactory | 598 typedef typename ClientSocketPoolBase<SocketParams>::ConnectJobFactory |
| 595 ConnectJobFactory; | 599 ConnectJobFactory; |
| 596 | 600 |
| 597 explicit ConnectJobFactoryAdaptor( | 601 explicit ConnectJobFactoryAdaptor( |
| 598 ConnectJobFactory* connect_job_factory) | 602 ConnectJobFactory* connect_job_factory) |
| 599 : connect_job_factory_(connect_job_factory) {} | 603 : connect_job_factory_(connect_job_factory) {} |
| 600 virtual ~ConnectJobFactoryAdaptor() {} | 604 virtual ~ConnectJobFactoryAdaptor() {} |
| 601 | 605 |
| 602 virtual ConnectJob* NewConnectJob( | 606 virtual ConnectJob* NewConnectJob( |
| 603 const std::string& group_name, | 607 const std::string& group_name, |
| 604 const internal::ClientSocketPoolBaseHelper::Request& request, | 608 const internal::ClientSocketPoolBaseHelper::Request& request, |
| 605 ConnectJob::Delegate* delegate, | 609 ConnectJob::Delegate* delegate) const { |
| 606 const BoundNetLog& net_log) const { | |
| 607 const Request* casted_request = static_cast<const Request*>(&request); | 610 const Request* casted_request = static_cast<const Request*>(&request); |
| 608 return connect_job_factory_->NewConnectJob( | 611 return connect_job_factory_->NewConnectJob( |
| 609 group_name, *casted_request, delegate, net_log); | 612 group_name, *casted_request, delegate); |
| 610 } | 613 } |
| 611 | 614 |
| 612 virtual base::TimeDelta ConnectionTimeout() const { | 615 virtual base::TimeDelta ConnectionTimeout() const { |
| 613 return connect_job_factory_->ConnectionTimeout(); | 616 return connect_job_factory_->ConnectionTimeout(); |
| 614 } | 617 } |
| 615 | 618 |
| 616 const scoped_ptr<ConnectJobFactory> connect_job_factory_; | 619 const scoped_ptr<ConnectJobFactory> connect_job_factory_; |
| 617 }; | 620 }; |
| 618 | 621 |
| 619 // Histograms for the pool | 622 // Histograms for the pool |
| 620 const scoped_refptr<ClientSocketPoolHistograms> histograms_; | 623 const scoped_refptr<ClientSocketPoolHistograms> histograms_; |
| 621 | 624 |
| 622 // One might ask why ClientSocketPoolBaseHelper is also refcounted if its | 625 // One might ask why ClientSocketPoolBaseHelper is also refcounted if its |
| 623 // containing ClientSocketPool is already refcounted. The reason is because | 626 // containing ClientSocketPool is already refcounted. The reason is because |
| 624 // DoReleaseSocket() posts a task. If ClientSocketPool gets deleted between | 627 // DoReleaseSocket() posts a task. If ClientSocketPool gets deleted between |
| 625 // the posting of the task and the execution, then we'll hit the DCHECK that | 628 // the posting of the task and the execution, then we'll hit the DCHECK that |
| 626 // |ClientSocketPoolBaseHelper::group_map_| is empty. | 629 // |ClientSocketPoolBaseHelper::group_map_| is empty. |
| 627 scoped_refptr<internal::ClientSocketPoolBaseHelper> helper_; | 630 scoped_refptr<internal::ClientSocketPoolBaseHelper> helper_; |
| 628 | 631 |
| 629 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); | 632 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); |
| 630 }; | 633 }; |
| 631 | 634 |
| 632 } // namespace net | 635 } // namespace net |
| 633 | 636 |
| 634 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 637 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
| OLD | NEW |