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