| 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 #ifndef NET_BASE_CLIENT_SOCKET_POOL_H_ | 5 #ifndef NET_BASE_CLIENT_SOCKET_POOL_H_ |
| 6 #define NET_BASE_CLIENT_SOCKET_POOL_H_ | 6 #define NET_BASE_CLIENT_SOCKET_POOL_H_ |
| 7 | 7 |
| 8 #include <deque> | 8 #include <deque> |
| 9 #include <map> | 9 #include <map> |
| 10 #include <string> | 10 #include <string> |
| 11 | 11 |
| 12 #include "base/ref_counted.h" | 12 #include "base/ref_counted.h" |
| 13 #include "base/scoped_ptr.h" | 13 #include "base/scoped_ptr.h" |
| 14 #include "base/timer.h" | 14 #include "base/timer.h" |
| 15 #include "net/base/address_list.h" | |
| 16 #include "net/base/completion_callback.h" | 15 #include "net/base/completion_callback.h" |
| 17 #include "net/base/host_resolver.h" | |
| 18 #include "net/base/load_states.h" | |
| 19 | 16 |
| 20 namespace net { | 17 namespace net { |
| 21 | 18 |
| 22 class ClientSocket; | 19 class ClientSocket; |
| 23 class ClientSocketFactory; | |
| 24 class ClientSocketHandle; | 20 class ClientSocketHandle; |
| 25 | 21 |
| 26 // A ClientSocketPool is used to restrict the number of sockets open at a time. | 22 // A ClientSocketPool is used to restrict the number of sockets open at a time. |
| 27 // It also maintains a list of idle persistent sockets. | 23 // It also maintains a list of idle persistent sockets. |
| 28 // | 24 // |
| 25 // The ClientSocketPool allocates scoped_ptr<ClientSocket> objects, but it is |
| 26 // not responsible for allocating the associated ClientSocket objects. The |
| 27 // consumer must do so if it gets a scoped_ptr<ClientSocket> with a null value. |
| 28 // |
| 29 class ClientSocketPool : public base::RefCounted<ClientSocketPool> { | 29 class ClientSocketPool : public base::RefCounted<ClientSocketPool> { |
| 30 public: | 30 public: |
| 31 ClientSocketPool(int max_sockets_per_group, | 31 explicit ClientSocketPool(int max_sockets_per_group); |
| 32 ClientSocketFactory* client_socket_factory); | |
| 33 | 32 |
| 34 // Requests a connected socket for a group_name. | 33 // Called to request a socket for the given handle. There are three possible |
| 35 // | 34 // results: 1) the handle will be initialized with a socket to reuse, 2) the |
| 36 // There are four possible results from calling this function: | 35 // handle will be initialized without a socket such that the consumer needs |
| 37 // 1) RequestSocket returns OK and initializes |handle| with a reused socket. | 36 // to supply a socket, or 3) the handle will be added to a wait list until a |
| 38 // 2) RequestSocket returns OK with a newly connected socket. | 37 // socket is available to reuse or the opportunity to create a new socket |
| 39 // 3) RequestSocket returns ERR_IO_PENDING. The handle will be added to a | 38 // arises. The completion callback is notified in the 3rd case. |priority| |
| 40 // wait list until a socket is available to reuse or a new socket finishes | 39 // will determine the placement into the wait list. |
| 41 // connecting. |priority| will determine the placement into the wait list. | |
| 42 // 4) An error occurred early on, so RequestSocket returns an error code. | |
| 43 // | 40 // |
| 44 // If this function returns OK, then |handle| is initialized upon return. | 41 // If this function returns OK, then |handle| is initialized upon return. |
| 45 // The |handle|'s is_initialized method will return true in this case. If a | 42 // The |handle|'s is_initialized method will return true in this case. If a |
| 46 // ClientSocket was reused, then ClientSocketPool will call | 43 // ClientSocket was reused, then |handle|'s socket member will be non-NULL. |
| 47 // |handle|->set_reused(true). In either case, the socket will have been | 44 // Otherwise, the consumer will need to supply |handle| with a socket by |
| 48 // allocated and will be connected. A client might want to know whether or | 45 // allocating a new ClientSocket object and calling the |handle|'s set_socket |
| 49 // not the socket is reused in order to know whether or not he needs to | 46 // method. |
| 50 // perform SSL connection or tunnel setup or to request a new socket if he | |
| 51 // encounters an error with the reused socket. | |
| 52 // | 47 // |
| 53 // If ERR_IO_PENDING is returned, then the callback will be used to notify the | 48 // If ERR_IO_PENDING is returned, then the completion callback will be called |
| 54 // client of completion. | 49 // when |handle| has been initialized. |
| 55 // | 50 // |
| 56 int RequestSocket(const std::string& group_name, | 51 int RequestSocket(ClientSocketHandle* handle, |
| 57 const std::string& host, | |
| 58 int port, | |
| 59 int priority, | 52 int priority, |
| 60 ClientSocketHandle* handle, | |
| 61 CompletionCallback* callback); | 53 CompletionCallback* callback); |
| 62 | 54 |
| 63 // Called to cancel a RequestSocket call that returned ERR_IO_PENDING. The | 55 // Called to cancel a RequestSocket call that returned ERR_IO_PENDING. The |
| 64 // same handle parameter must be passed to this method as was passed to the | 56 // same handle parameter must be passed to this method as was passed to the |
| 65 // RequestSocket call being cancelled. The associated CompletionCallback is | 57 // RequestSocket call being cancelled. The associated CompletionCallback is |
| 66 // not run. | 58 // not run. |
| 67 void CancelRequest(const std::string& group_name, | 59 void CancelRequest(ClientSocketHandle* handle); |
| 68 const ClientSocketHandle* handle); | |
| 69 | 60 |
| 70 // Called to release a socket once the socket is no longer needed. If the | 61 // Called to release the socket member of an initialized ClientSocketHandle |
| 71 // socket still has an established connection, then it will be added to the | 62 // once the socket is no longer needed. If the socket member is non-null and |
| 72 // set of idle sockets to be used to satisfy future RequestSocket calls. | 63 // still has an established connection, then it will be added to the idle set |
| 73 // Otherwise, the ClientSocket is destroyed. | 64 // of sockets to be used to satisfy future RequestSocket calls. Otherwise, |
| 74 void ReleaseSocket(const std::string& group_name, ClientSocket* socket); | 65 // the ClientSocket is destroyed. |
| 66 void ReleaseSocket(ClientSocketHandle* handle); |
| 75 | 67 |
| 76 // Called to close any idle connections held by the connection manager. | 68 // Called to close any idle connections held by the connection manager. |
| 77 void CloseIdleSockets(); | 69 void CloseIdleSockets(); |
| 78 | 70 |
| 79 // The total number of idle sockets in the pool. | 71 // The total number of idle sockets in the pool. |
| 80 int idle_socket_count() const { | 72 int idle_socket_count() const { |
| 81 return idle_socket_count_; | 73 return idle_socket_count_; |
| 82 } | 74 } |
| 83 | 75 |
| 84 // The total number of idle sockets in a connection group. | 76 // The total number of idle sockets in a connection group. |
| 85 int IdleSocketCountInGroup(const std::string& group_name) const; | 77 int IdleSocketCountInGroup(const std::string& group_name) const; |
| 86 | 78 |
| 87 // Determine the LoadState of a connecting ClientSocketHandle. | |
| 88 LoadState GetLoadState(const std::string& group_name, | |
| 89 const ClientSocketHandle* handle) const; | |
| 90 | |
| 91 private: | 79 private: |
| 92 friend class base::RefCounted<ClientSocketPool>; | 80 friend class base::RefCounted<ClientSocketPool>; |
| 93 | 81 |
| 82 typedef scoped_ptr<ClientSocket> ClientSocketPtr; |
| 83 |
| 94 // A Request is allocated per call to RequestSocket that results in | 84 // A Request is allocated per call to RequestSocket that results in |
| 95 // ERR_IO_PENDING. | 85 // ERR_IO_PENDING. |
| 96 struct Request { | 86 struct Request { |
| 97 ClientSocketHandle* handle; | 87 ClientSocketHandle* handle; |
| 98 CompletionCallback* callback; | 88 CompletionCallback* callback; |
| 99 int priority; | 89 int priority; |
| 100 std::string host; | |
| 101 int port; | |
| 102 LoadState load_state; | |
| 103 }; | 90 }; |
| 104 | 91 |
| 105 // Entry for a persistent socket which became idle at time |start_time|. | 92 // Entry for a persistent socket which became idle at time |start_time|. |
| 106 struct IdleSocket { | 93 struct IdleSocket { |
| 107 ClientSocket* socket; | 94 ClientSocketPtr* ptr; |
| 108 base::TimeTicks start_time; | 95 base::TimeTicks start_time; |
| 109 | 96 |
| 110 // An idle socket should be removed if it can't be reused, or has been idle | 97 // An idle socket should be removed if it can't be reused, or has been idle |
| 111 // for too long. |now| is the current time value (TimeTicks::Now()). | 98 // for too long. |now| is the current time value (TimeTicks::Now()). |
| 112 // | 99 // |
| 113 // An idle socket can't be reused if it is disconnected or has received | 100 // An idle socket can't be reused if it is disconnected or has received |
| 114 // data unexpectedly (hence no longer idle). The unread data would be | 101 // data unexpectedly (hence no longer idle). The unread data would be |
| 115 // mistaken for the beginning of the next response if we were to reuse the | 102 // mistaken for the beginning of the next response if we were to reuse the |
| 116 // socket for a new request. | 103 // socket for a new request. |
| 117 bool ShouldCleanup(base::TimeTicks now) const; | 104 bool ShouldCleanup(base::TimeTicks now) const; |
| 118 }; | 105 }; |
| 119 | 106 |
| 120 typedef std::deque<Request> RequestQueue; | 107 typedef std::deque<Request> RequestQueue; |
| 121 typedef std::map<const ClientSocketHandle*, Request> RequestMap; | |
| 122 | 108 |
| 123 // A Group is allocated per group_name when there are idle sockets or pending | 109 // A Group is allocated per group_name when there are idle sockets or pending |
| 124 // requests. Otherwise, the Group object is removed from the map. | 110 // requests. Otherwise, the Group object is removed from the map. |
| 125 struct Group { | 111 struct Group { |
| 126 Group() : active_socket_count(0) {} | 112 Group() : active_socket_count(0) {} |
| 127 std::deque<IdleSocket> idle_sockets; | 113 std::deque<IdleSocket> idle_sockets; |
| 128 RequestQueue pending_requests; | 114 RequestQueue pending_requests; |
| 129 RequestMap connecting_requests; | |
| 130 int active_socket_count; | 115 int active_socket_count; |
| 131 }; | 116 }; |
| 132 | 117 |
| 133 typedef std::map<std::string, Group> GroupMap; | 118 typedef std::map<std::string, Group> GroupMap; |
| 134 | 119 |
| 135 // ConnectingSocket handles the host resolution necessary for socket creation | |
| 136 // and the Connect(). | |
| 137 class ConnectingSocket { | |
| 138 public: | |
| 139 enum State { | |
| 140 STATE_RESOLVE_HOST, | |
| 141 STATE_CONNECT | |
| 142 }; | |
| 143 | |
| 144 ConnectingSocket(const std::string& group_name, | |
| 145 const ClientSocketHandle* handle, | |
| 146 ClientSocketFactory* client_socket_factory, | |
| 147 ClientSocketPool* pool); | |
| 148 ~ConnectingSocket(); | |
| 149 | |
| 150 // Begins the host resolution and the TCP connect. Returns OK on success, | |
| 151 // in which case |callback| is not called. On pending IO, Connect returns | |
| 152 // ERR_IO_PENDING and runs |callback| on completion. | |
| 153 int Connect(const std::string& host, | |
| 154 int port, | |
| 155 CompletionCallback* callback); | |
| 156 | |
| 157 // If Connect() returns OK, ClientSocketPool may invoke this method to get | |
| 158 // the ConnectingSocket to release |socket_| to be set into the | |
| 159 // ClientSocketHandle immediately. | |
| 160 ClientSocket* ReleaseSocket(); | |
| 161 | |
| 162 private: | |
| 163 void OnIOComplete(int result); | |
| 164 | |
| 165 const std::string group_name_; | |
| 166 const ClientSocketHandle* const handle_; | |
| 167 ClientSocketFactory* const client_socket_factory_; | |
| 168 CompletionCallbackImpl<ConnectingSocket> callback_; | |
| 169 scoped_ptr<ClientSocket> socket_; | |
| 170 scoped_refptr<ClientSocketPool> pool_; | |
| 171 HostResolver resolver_; | |
| 172 AddressList addresses_; | |
| 173 | |
| 174 // The time the Connect() method was called (if it got called). | |
| 175 base::Time connect_start_time_; | |
| 176 | |
| 177 DISALLOW_COPY_AND_ASSIGN(ConnectingSocket); | |
| 178 }; | |
| 179 | |
| 180 ~ClientSocketPool(); | 120 ~ClientSocketPool(); |
| 181 | 121 |
| 182 static void InsertRequestIntoQueue(const Request& r, | 122 static void InsertRequestIntoQueue(const Request& r, |
| 183 RequestQueue* pending_requests); | 123 RequestQueue* pending_requests); |
| 184 | 124 |
| 185 // Closes all idle sockets if |force| is true. Else, only closes idle | 125 // Closes all idle sockets if |force| is true. Else, only closes idle |
| 186 // sockets that timed out or can't be reused. | 126 // sockets that timed out or can't be reused. |
| 187 void CleanupIdleSockets(bool force); | 127 void CleanupIdleSockets(bool force); |
| 188 | 128 |
| 189 // Called when the number of idle sockets changes. | 129 // Called when the number of idle sockets changes. |
| 190 void IncrementIdleCount(); | 130 void IncrementIdleCount(); |
| 191 void DecrementIdleCount(); | 131 void DecrementIdleCount(); |
| 192 | 132 |
| 193 // Called via PostTask by ReleaseSocket. | 133 // Called via PostTask by ReleaseSocket. |
| 194 void DoReleaseSocket(const std::string& group_name, ClientSocket* socket); | 134 void DoReleaseSocket(const std::string& group_name, ClientSocketPtr* ptr); |
| 195 | 135 |
| 196 // Called when timer_ fires. This method scans the idle sockets removing | 136 // Called when timer_ fires. This method scans the idle sockets removing |
| 197 // sockets that timed out or can't be reused. | 137 // sockets that timed out or can't be reused. |
| 198 void OnCleanupTimerFired() { | 138 void OnCleanupTimerFired() { |
| 199 CleanupIdleSockets(false); | 139 CleanupIdleSockets(false); |
| 200 } | 140 } |
| 201 | 141 |
| 202 ClientSocketFactory* const client_socket_factory_; | |
| 203 | |
| 204 GroupMap group_map_; | 142 GroupMap group_map_; |
| 205 | 143 |
| 206 // Timer used to periodically prune idle sockets that timed out or can't be | 144 // Timer used to periodically prune idle sockets that timed out or can't be |
| 207 // reused. | 145 // reused. |
| 208 base::RepeatingTimer<ClientSocketPool> timer_; | 146 base::RepeatingTimer<ClientSocketPool> timer_; |
| 209 | 147 |
| 210 // The total number of idle sockets in the system. | 148 // The total number of idle sockets in the system. |
| 211 int idle_socket_count_; | 149 int idle_socket_count_; |
| 212 | 150 |
| 213 // The maximum number of sockets kept per group. | 151 // The maximum number of sockets kept per group. |
| 214 const int max_sockets_per_group_; | 152 int max_sockets_per_group_; |
| 215 | 153 |
| 216 DISALLOW_COPY_AND_ASSIGN(ClientSocketPool); | 154 DISALLOW_COPY_AND_ASSIGN(ClientSocketPool); |
| 217 }; | 155 }; |
| 218 | 156 |
| 219 } // namespace net | 157 } // namespace net |
| 220 | 158 |
| 221 #endif // NET_BASE_CLIENT_SOCKET_POOL_H_ | 159 #endif // NET_BASE_CLIENT_SOCKET_POOL_H_ |
| OLD | NEW |