| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 20 matching lines...) Expand all Loading... |
| 31 #include "base/compiler_specific.h" | 31 #include "base/compiler_specific.h" |
| 32 #include "base/ref_counted.h" | 32 #include "base/ref_counted.h" |
| 33 #include "base/scoped_ptr.h" | 33 #include "base/scoped_ptr.h" |
| 34 #include "base/task.h" | 34 #include "base/task.h" |
| 35 #include "base/time.h" | 35 #include "base/time.h" |
| 36 #include "base/timer.h" | 36 #include "base/timer.h" |
| 37 #include "net/base/address_list.h" | 37 #include "net/base/address_list.h" |
| 38 #include "net/base/completion_callback.h" | 38 #include "net/base/completion_callback.h" |
| 39 #include "net/base/load_states.h" | 39 #include "net/base/load_states.h" |
| 40 #include "net/base/net_errors.h" | 40 #include "net/base/net_errors.h" |
| 41 #include "net/base/net_log.h" |
| 41 #include "net/base/network_change_notifier.h" | 42 #include "net/base/network_change_notifier.h" |
| 42 #include "net/base/request_priority.h" | 43 #include "net/base/request_priority.h" |
| 43 #include "net/socket/client_socket.h" | 44 #include "net/socket/client_socket.h" |
| 44 #include "net/socket/client_socket_pool.h" | 45 #include "net/socket/client_socket_pool.h" |
| 45 | 46 |
| 46 namespace net { | 47 namespace net { |
| 47 | 48 |
| 48 class ClientSocketHandle; | 49 class ClientSocketHandle; |
| 49 class LoadLog; | |
| 50 | 50 |
| 51 // ConnectJob provides an abstract interface for "connecting" a socket. | 51 // ConnectJob provides an abstract interface for "connecting" a socket. |
| 52 // The connection may involve host resolution, tcp connection, ssl connection, | 52 // The connection may involve host resolution, tcp connection, ssl connection, |
| 53 // etc. | 53 // etc. |
| 54 class ConnectJob { | 54 class ConnectJob { |
| 55 public: | 55 public: |
| 56 class Delegate { | 56 class Delegate { |
| 57 public: | 57 public: |
| 58 Delegate() {} | 58 Delegate() {} |
| 59 virtual ~Delegate() {} | 59 virtual ~Delegate() {} |
| 60 | 60 |
| 61 // Alerts the delegate that the connection completed. | 61 // Alerts the delegate that the connection completed. |
| 62 virtual void OnConnectJobComplete(int result, ConnectJob* job) = 0; | 62 virtual void OnConnectJobComplete(int result, ConnectJob* job) = 0; |
| 63 | 63 |
| 64 private: | 64 private: |
| 65 DISALLOW_COPY_AND_ASSIGN(Delegate); | 65 DISALLOW_COPY_AND_ASSIGN(Delegate); |
| 66 }; | 66 }; |
| 67 | 67 |
| 68 // A |timeout_duration| of 0 corresponds to no timeout. | 68 // A |timeout_duration| of 0 corresponds to no timeout. |
| 69 ConnectJob(const std::string& group_name, | 69 ConnectJob(const std::string& group_name, |
| 70 base::TimeDelta timeout_duration, | 70 base::TimeDelta timeout_duration, |
| 71 Delegate* delegate, | 71 Delegate* delegate, |
| 72 LoadLog* load_log); | 72 const BoundNetLog& net_log); |
| 73 virtual ~ConnectJob(); | 73 virtual ~ConnectJob(); |
| 74 | 74 |
| 75 // Accessors | 75 // Accessors |
| 76 const std::string& group_name() const { return group_name_; } | 76 const std::string& group_name() const { return group_name_; } |
| 77 LoadLog* load_log() { return load_log_; } | 77 const BoundNetLog& net_log() { return net_log_; } |
| 78 | 78 |
| 79 // Releases |socket_| to the client. On connection error, this should return | 79 // Releases |socket_| to the client. On connection error, this should return |
| 80 // NULL. | 80 // NULL. |
| 81 ClientSocket* ReleaseSocket() { return socket_.release(); } | 81 ClientSocket* ReleaseSocket() { return socket_.release(); } |
| 82 | 82 |
| 83 // Begins connecting the socket. Returns OK on success, ERR_IO_PENDING if it | 83 // Begins connecting the socket. Returns OK on success, ERR_IO_PENDING if it |
| 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 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 100 | 100 |
| 101 // Alerts the delegate that the ConnectJob has timed out. | 101 // Alerts the delegate that the ConnectJob has timed out. |
| 102 void OnTimeout(); | 102 void OnTimeout(); |
| 103 | 103 |
| 104 const std::string group_name_; | 104 const std::string group_name_; |
| 105 const base::TimeDelta timeout_duration_; | 105 const base::TimeDelta timeout_duration_; |
| 106 // Timer to abort jobs that take too long. | 106 // Timer to abort jobs that take too long. |
| 107 base::OneShotTimer<ConnectJob> timer_; | 107 base::OneShotTimer<ConnectJob> timer_; |
| 108 Delegate* delegate_; | 108 Delegate* delegate_; |
| 109 scoped_ptr<ClientSocket> socket_; | 109 scoped_ptr<ClientSocket> socket_; |
| 110 scoped_refptr<LoadLog> load_log_; | 110 BoundNetLog net_log_; |
| 111 | 111 |
| 112 DISALLOW_COPY_AND_ASSIGN(ConnectJob); | 112 DISALLOW_COPY_AND_ASSIGN(ConnectJob); |
| 113 }; | 113 }; |
| 114 | 114 |
| 115 namespace internal { | 115 namespace internal { |
| 116 | 116 |
| 117 // ClientSocketPoolBaseHelper is an internal class that implements almost all | 117 // ClientSocketPoolBaseHelper is an internal class that implements almost all |
| 118 // the functionality from ClientSocketPoolBase without using templates. | 118 // the functionality from ClientSocketPoolBase without using templates. |
| 119 // ClientSocketPoolBase adds templated definitions built on top of | 119 // ClientSocketPoolBase adds templated definitions built on top of |
| 120 // ClientSocketPoolBaseHelper. This class is not for external use, please use | 120 // ClientSocketPoolBaseHelper. This class is not for external use, please use |
| 121 // ClientSocketPoolBase instead. | 121 // ClientSocketPoolBase instead. |
| 122 class ClientSocketPoolBaseHelper | 122 class ClientSocketPoolBaseHelper |
| 123 : public base::RefCounted<ClientSocketPoolBaseHelper>, | 123 : public base::RefCounted<ClientSocketPoolBaseHelper>, |
| 124 public ConnectJob::Delegate, | 124 public ConnectJob::Delegate, |
| 125 public NetworkChangeNotifier::Observer { | 125 public NetworkChangeNotifier::Observer { |
| 126 public: | 126 public: |
| 127 class Request { | 127 class Request { |
| 128 public: | 128 public: |
| 129 Request(ClientSocketHandle* handle, | 129 Request(ClientSocketHandle* handle, |
| 130 CompletionCallback* callback, | 130 CompletionCallback* callback, |
| 131 RequestPriority priority, | 131 RequestPriority priority, |
| 132 LoadLog* load_log); | 132 const BoundNetLog& net_log); |
| 133 | 133 |
| 134 virtual ~Request(); | 134 virtual ~Request(); |
| 135 | 135 |
| 136 ClientSocketHandle* handle() const { return handle_; } | 136 ClientSocketHandle* handle() const { return handle_; } |
| 137 CompletionCallback* callback() const { return callback_; } | 137 CompletionCallback* callback() const { return callback_; } |
| 138 RequestPriority priority() const { return priority_; } | 138 RequestPriority priority() const { return priority_; } |
| 139 LoadLog* load_log() const { return load_log_.get(); } | 139 const BoundNetLog& net_log() const { return net_log_; } |
| 140 | 140 |
| 141 private: | 141 private: |
| 142 ClientSocketHandle* const handle_; | 142 ClientSocketHandle* const handle_; |
| 143 CompletionCallback* const callback_; | 143 CompletionCallback* const callback_; |
| 144 const RequestPriority priority_; | 144 const RequestPriority priority_; |
| 145 const scoped_refptr<LoadLog> load_log_; | 145 BoundNetLog net_log_; |
| 146 | 146 |
| 147 DISALLOW_COPY_AND_ASSIGN(Request); | 147 DISALLOW_COPY_AND_ASSIGN(Request); |
| 148 }; | 148 }; |
| 149 | 149 |
| 150 class ConnectJobFactory { | 150 class ConnectJobFactory { |
| 151 public: | 151 public: |
| 152 ConnectJobFactory() {} | 152 ConnectJobFactory() {} |
| 153 virtual ~ConnectJobFactory() {} | 153 virtual ~ConnectJobFactory() {} |
| 154 | 154 |
| 155 virtual ConnectJob* NewConnectJob( | 155 virtual ConnectJob* NewConnectJob( |
| 156 const std::string& group_name, | 156 const std::string& group_name, |
| 157 const Request& request, | 157 const Request& request, |
| 158 ConnectJob::Delegate* delegate, | 158 ConnectJob::Delegate* delegate, |
| 159 LoadLog* load_log) const = 0; | 159 const BoundNetLog& net_log) const = 0; |
| 160 | 160 |
| 161 private: | 161 private: |
| 162 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); | 162 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); |
| 163 }; | 163 }; |
| 164 | 164 |
| 165 ClientSocketPoolBaseHelper( | 165 ClientSocketPoolBaseHelper( |
| 166 int max_sockets, | 166 int max_sockets, |
| 167 int max_sockets_per_group, | 167 int max_sockets_per_group, |
| 168 base::TimeDelta unused_idle_socket_timeout, | 168 base::TimeDelta unused_idle_socket_timeout, |
| 169 base::TimeDelta used_idle_socket_timeout, | 169 base::TimeDelta used_idle_socket_timeout, |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 | 348 |
| 349 // Process a request from a group's pending_requests queue. | 349 // Process a request from a group's pending_requests queue. |
| 350 void ProcessPendingRequest(const std::string& group_name, Group* group); | 350 void ProcessPendingRequest(const std::string& group_name, Group* group); |
| 351 | 351 |
| 352 // Assigns |socket| to |handle| and updates |group|'s counters appropriately. | 352 // Assigns |socket| to |handle| and updates |group|'s counters appropriately. |
| 353 void HandOutSocket(ClientSocket* socket, | 353 void HandOutSocket(ClientSocket* socket, |
| 354 bool reused, | 354 bool reused, |
| 355 ClientSocketHandle* handle, | 355 ClientSocketHandle* handle, |
| 356 base::TimeDelta time_idle, | 356 base::TimeDelta time_idle, |
| 357 Group* group, | 357 Group* group, |
| 358 LoadLog* load_log); | 358 const BoundNetLog& net_log); |
| 359 | 359 |
| 360 // Adds |socket| to the list of idle sockets for |group|. |used| indicates | 360 // Adds |socket| to the list of idle sockets for |group|. |used| indicates |
| 361 // whether or not the socket has previously been used. | 361 // whether or not the socket has previously been used. |
| 362 void AddIdleSocket(ClientSocket* socket, bool used, Group* group); | 362 void AddIdleSocket(ClientSocket* socket, bool used, Group* group); |
| 363 | 363 |
| 364 // Iterates through |connect_job_map_|, canceling all ConnectJobs. | 364 // Iterates through |connect_job_map_|, canceling all ConnectJobs. |
| 365 // Afterwards, it iterates through all groups and deletes them if they are no | 365 // Afterwards, it iterates through all groups and deletes them if they are no |
| 366 // longer needed. | 366 // longer needed. |
| 367 void CancelAllConnectJobs(); | 367 void CancelAllConnectJobs(); |
| 368 | 368 |
| 369 // Returns true if we can't create any more sockets due to the total limit. | 369 // Returns true if we can't create any more sockets due to the total limit. |
| 370 // TODO(phajdan.jr): Also take idle sockets into account. | 370 // TODO(phajdan.jr): Also take idle sockets into account. |
| 371 bool ReachedMaxSocketsLimit() const; | 371 bool ReachedMaxSocketsLimit() const; |
| 372 | 372 |
| 373 // This is the internal implementation of RequestSocket(). It differs in that | 373 // This is the internal implementation of RequestSocket(). It differs in that |
| 374 // it does not handle logging into LoadLog of the queueing status of | 374 // it does not handle logging into NetLog of the queueing status of |
| 375 // |request|. | 375 // |request|. |
| 376 int RequestSocketInternal(const std::string& group_name, | 376 int RequestSocketInternal(const std::string& group_name, |
| 377 const Request* request); | 377 const Request* request); |
| 378 | 378 |
| 379 // Set a timer to create a backup socket if it takes too long to create one. | 379 // Set a timer to create a backup socket if it takes too long to create one. |
| 380 void StartBackupSocketTimer(const std::string& group_name); | 380 void StartBackupSocketTimer(const std::string& group_name); |
| 381 | 381 |
| 382 // Called when the backup socket timer fires. | 382 // Called when the backup socket timer fires. |
| 383 void OnBackupSocketTimerFired(const std::string& group_name); | 383 void OnBackupSocketTimerFired(const std::string& group_name); |
| 384 | 384 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 | 443 |
| 444 template <typename SocketParams> | 444 template <typename SocketParams> |
| 445 class ClientSocketPoolBase { | 445 class ClientSocketPoolBase { |
| 446 public: | 446 public: |
| 447 class Request : public internal::ClientSocketPoolBaseHelper::Request { | 447 class Request : public internal::ClientSocketPoolBaseHelper::Request { |
| 448 public: | 448 public: |
| 449 Request(ClientSocketHandle* handle, | 449 Request(ClientSocketHandle* handle, |
| 450 CompletionCallback* callback, | 450 CompletionCallback* callback, |
| 451 RequestPriority priority, | 451 RequestPriority priority, |
| 452 const SocketParams& params, | 452 const SocketParams& params, |
| 453 LoadLog* load_log) | 453 const BoundNetLog& net_log) |
| 454 : internal::ClientSocketPoolBaseHelper::Request( | 454 : internal::ClientSocketPoolBaseHelper::Request( |
| 455 handle, callback, priority, load_log), | 455 handle, callback, priority, net_log), |
| 456 params_(params) {} | 456 params_(params) {} |
| 457 | 457 |
| 458 const SocketParams& params() const { return params_; } | 458 const SocketParams& params() const { return params_; } |
| 459 | 459 |
| 460 private: | 460 private: |
| 461 SocketParams params_; | 461 SocketParams params_; |
| 462 }; | 462 }; |
| 463 | 463 |
| 464 class ConnectJobFactory { | 464 class ConnectJobFactory { |
| 465 public: | 465 public: |
| 466 ConnectJobFactory() {} | 466 ConnectJobFactory() {} |
| 467 virtual ~ConnectJobFactory() {} | 467 virtual ~ConnectJobFactory() {} |
| 468 | 468 |
| 469 virtual ConnectJob* NewConnectJob( | 469 virtual ConnectJob* NewConnectJob( |
| 470 const std::string& group_name, | 470 const std::string& group_name, |
| 471 const Request& request, | 471 const Request& request, |
| 472 ConnectJob::Delegate* delegate, | 472 ConnectJob::Delegate* delegate, |
| 473 LoadLog* load_log) const = 0; | 473 const BoundNetLog& net_log) const = 0; |
| 474 | 474 |
| 475 private: | 475 private: |
| 476 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); | 476 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); |
| 477 }; | 477 }; |
| 478 | 478 |
| 479 // |max_sockets| is the maximum number of sockets to be maintained by this | 479 // |max_sockets| is the maximum number of sockets to be maintained by this |
| 480 // ClientSocketPool. |max_sockets_per_group| specifies the maximum number of | 480 // ClientSocketPool. |max_sockets_per_group| specifies the maximum number of |
| 481 // sockets a "group" can have. |unused_idle_socket_timeout| specifies how | 481 // sockets a "group" can have. |unused_idle_socket_timeout| specifies how |
| 482 // long to leave an unused idle socket open before closing it. | 482 // long to leave an unused idle socket open before closing it. |
| 483 // |used_idle_socket_timeout| specifies how long to leave a previously used | 483 // |used_idle_socket_timeout| specifies how long to leave a previously used |
| (...skipping 16 matching lines...) Expand all Loading... |
| 500 // These member functions simply forward to ClientSocketPoolBaseHelper. | 500 // These member functions simply forward to ClientSocketPoolBaseHelper. |
| 501 | 501 |
| 502 // RequestSocket bundles up the parameters into a Request and then forwards to | 502 // RequestSocket bundles up the parameters into a Request and then forwards to |
| 503 // ClientSocketPoolBaseHelper::RequestSocket(). Note that the memory | 503 // ClientSocketPoolBaseHelper::RequestSocket(). Note that the memory |
| 504 // ownership is transferred in the asynchronous (ERR_IO_PENDING) case. | 504 // ownership is transferred in the asynchronous (ERR_IO_PENDING) case. |
| 505 int RequestSocket(const std::string& group_name, | 505 int RequestSocket(const std::string& group_name, |
| 506 const SocketParams& params, | 506 const SocketParams& params, |
| 507 RequestPriority priority, | 507 RequestPriority priority, |
| 508 ClientSocketHandle* handle, | 508 ClientSocketHandle* handle, |
| 509 CompletionCallback* callback, | 509 CompletionCallback* callback, |
| 510 LoadLog* load_log) { | 510 const BoundNetLog& net_log) { |
| 511 scoped_ptr<Request> request( | 511 scoped_ptr<Request> request( |
| 512 new Request(handle, callback, priority, params, load_log)); | 512 new Request(handle, callback, priority, params, net_log)); |
| 513 int rv = helper_->RequestSocket(group_name, request.get()); | 513 int rv = helper_->RequestSocket(group_name, request.get()); |
| 514 if (rv == ERR_IO_PENDING) | 514 if (rv == ERR_IO_PENDING) |
| 515 request.release(); | 515 request.release(); |
| 516 return rv; | 516 return rv; |
| 517 } | 517 } |
| 518 | 518 |
| 519 void CancelRequest(const std::string& group_name, | 519 void CancelRequest(const std::string& group_name, |
| 520 const ClientSocketHandle* handle) { | 520 const ClientSocketHandle* handle) { |
| 521 return helper_->CancelRequest(group_name, handle); | 521 return helper_->CancelRequest(group_name, handle); |
| 522 } | 522 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 569 | 569 |
| 570 explicit ConnectJobFactoryAdaptor( | 570 explicit ConnectJobFactoryAdaptor( |
| 571 ConnectJobFactory* connect_job_factory) | 571 ConnectJobFactory* connect_job_factory) |
| 572 : connect_job_factory_(connect_job_factory) {} | 572 : connect_job_factory_(connect_job_factory) {} |
| 573 virtual ~ConnectJobFactoryAdaptor() {} | 573 virtual ~ConnectJobFactoryAdaptor() {} |
| 574 | 574 |
| 575 virtual ConnectJob* NewConnectJob( | 575 virtual ConnectJob* NewConnectJob( |
| 576 const std::string& group_name, | 576 const std::string& group_name, |
| 577 const internal::ClientSocketPoolBaseHelper::Request& request, | 577 const internal::ClientSocketPoolBaseHelper::Request& request, |
| 578 ConnectJob::Delegate* delegate, | 578 ConnectJob::Delegate* delegate, |
| 579 LoadLog* load_log) const { | 579 const BoundNetLog& net_log) const { |
| 580 const Request* casted_request = static_cast<const Request*>(&request); | 580 const Request* casted_request = static_cast<const Request*>(&request); |
| 581 return connect_job_factory_->NewConnectJob( | 581 return connect_job_factory_->NewConnectJob( |
| 582 group_name, *casted_request, delegate, load_log); | 582 group_name, *casted_request, delegate, net_log); |
| 583 } | 583 } |
| 584 | 584 |
| 585 const scoped_ptr<ConnectJobFactory> connect_job_factory_; | 585 const scoped_ptr<ConnectJobFactory> connect_job_factory_; |
| 586 }; | 586 }; |
| 587 | 587 |
| 588 // One might ask why ClientSocketPoolBaseHelper is also refcounted if its | 588 // One might ask why ClientSocketPoolBaseHelper is also refcounted if its |
| 589 // containing ClientSocketPool is already refcounted. The reason is because | 589 // containing ClientSocketPool is already refcounted. The reason is because |
| 590 // DoReleaseSocket() posts a task. If ClientSocketPool gets deleted between | 590 // DoReleaseSocket() posts a task. If ClientSocketPool gets deleted between |
| 591 // the posting of the task and the execution, then we'll hit the DCHECK that | 591 // the posting of the task and the execution, then we'll hit the DCHECK that |
| 592 // |ClientSocketPoolBaseHelper::group_map_| is empty. | 592 // |ClientSocketPoolBaseHelper::group_map_| is empty. |
| 593 scoped_refptr<internal::ClientSocketPoolBaseHelper> helper_; | 593 scoped_refptr<internal::ClientSocketPoolBaseHelper> helper_; |
| 594 | 594 |
| 595 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); | 595 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); |
| 596 }; | 596 }; |
| 597 | 597 |
| 598 } // namespace net | 598 } // namespace net |
| 599 | 599 |
| 600 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 600 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
| OLD | NEW |