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_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 5 #ifndef NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
6 #define NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 6 #define NET_SOCKET_CLIENT_SOCKET_POOL_BASE_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/basictypes.h" | 12 #include "base/basictypes.h" |
13 #include "base/scoped_ptr.h" | 13 #include "base/scoped_ptr.h" |
14 #include "base/time.h" | 14 #include "base/time.h" |
15 #include "base/timer.h" | 15 #include "base/timer.h" |
16 #include "net/base/address_list.h" | 16 #include "net/base/address_list.h" |
17 #include "net/base/completion_callback.h" | 17 #include "net/base/completion_callback.h" |
18 #include "net/base/host_resolver.h" | 18 #include "net/base/host_resolver.h" |
19 #include "net/base/load_states.h" | 19 #include "net/base/load_states.h" |
| 20 #include "net/socket/client_socket.h" |
20 #include "net/socket/client_socket_pool.h" | 21 #include "net/socket/client_socket_pool.h" |
21 | 22 |
22 namespace net { | 23 namespace net { |
23 | 24 |
24 class ClientSocket; | |
25 class ClientSocketHandle; | 25 class ClientSocketHandle; |
26 class ClientSocketPoolBase; | 26 class ClientSocketPoolBase; |
27 | 27 |
28 // ConnectJob provides an abstract interface for "connecting" a socket. | 28 // ConnectJob provides an abstract interface for "connecting" a socket. |
29 // The connection may involve host resolution, tcp connection, ssl connection, | 29 // The connection may involve host resolution, tcp connection, ssl connection, |
30 // etc. | 30 // etc. |
31 class ConnectJob { | 31 class ConnectJob { |
32 public: | 32 public: |
33 class Delegate { | 33 class Delegate { |
34 public: | 34 public: |
35 Delegate() {} | 35 Delegate() {} |
36 virtual ~Delegate() {} | 36 virtual ~Delegate() {} |
37 | 37 |
38 // Alerts the delegate that the connection completed (though not necessarily | 38 // Alerts the delegate that the connection completed. |
39 // successfully). |group_name| indicates the connection group this | 39 virtual void OnConnectJobComplete(int result, ConnectJob* job) = 0; |
40 // ConnectJob corresponds to. |key_handle| uniquely identifies the | |
41 // ClientSocketHandle that this job is coupled to. |socket| is non-NULL if | |
42 // the connection completed successfully, and ownership is transferred to | |
43 // the delegate. |was_async| indicates whether or not the connect job | |
44 // completed asynchronously. | |
45 virtual void OnConnectJobComplete( | |
46 const std::string& group_name, | |
47 const ClientSocketHandle* key_handle, | |
48 ClientSocket* socket, | |
49 int result, | |
50 bool was_async) = 0; | |
51 | 40 |
52 private: | 41 private: |
53 DISALLOW_COPY_AND_ASSIGN(Delegate); | 42 DISALLOW_COPY_AND_ASSIGN(Delegate); |
54 }; | 43 }; |
55 | 44 |
56 ConnectJob() {} | 45 ConnectJob(const std::string& group_name, |
57 virtual ~ConnectJob() {} | 46 const ClientSocketHandle* key_handle, |
| 47 Delegate* delegate); |
| 48 virtual ~ConnectJob(); |
58 | 49 |
59 // Returns the LoadState of this ConnectJob. | 50 // Accessors |
| 51 const std::string& group_name() const { return group_name_; } |
60 LoadState load_state() const { return load_state_; } | 52 LoadState load_state() const { return load_state_; } |
| 53 const ClientSocketHandle* key_handle() const { return key_handle_; } |
| 54 |
| 55 // Releases |socket_| to the client. |
| 56 ClientSocket* ReleaseSocket() { return socket_.release(); } |
61 | 57 |
62 // Begins connecting the socket. Returns OK on success, ERR_IO_PENDING if it | 58 // Begins connecting the socket. Returns OK on success, ERR_IO_PENDING if it |
63 // cannot complete synchronously without blocking, or another net error code | 59 // cannot complete synchronously without blocking, or another net error code |
64 // on error. | 60 // on error. In asynchronous completion, the ConnectJob will notify |
| 61 // |delegate_| via OnConnectJobComplete. In both asynchronous and synchronous |
| 62 // completion, ReleaseSocket() can be called to acquire the connected socket |
| 63 // if it succeeded. |
65 virtual int Connect() = 0; | 64 virtual int Connect() = 0; |
66 | 65 |
67 protected: | 66 protected: |
68 void set_load_state(LoadState load_state) { load_state_ = load_state; } | 67 void set_load_state(LoadState load_state) { load_state_ = load_state; } |
| 68 void set_socket(ClientSocket* socket) { socket_.reset(socket); } |
| 69 ClientSocket* socket() { return socket_.get(); } |
| 70 Delegate* delegate() { return delegate_; } |
69 | 71 |
70 private: | 72 private: |
| 73 const std::string group_name_; |
| 74 // Temporarily needed until we switch to late binding. |
| 75 const ClientSocketHandle* const key_handle_; |
| 76 Delegate* const delegate_; |
71 LoadState load_state_; | 77 LoadState load_state_; |
| 78 scoped_ptr<ClientSocket> socket_; |
72 | 79 |
73 DISALLOW_COPY_AND_ASSIGN(ConnectJob); | 80 DISALLOW_COPY_AND_ASSIGN(ConnectJob); |
74 }; | 81 }; |
75 | 82 |
76 // A ClientSocketPoolBase is used to restrict the number of sockets open at | 83 // A ClientSocketPoolBase is used to restrict the number of sockets open at |
77 // a time. It also maintains a list of idle persistent sockets. | 84 // a time. It also maintains a list of idle persistent sockets. |
78 // | 85 // |
79 class ClientSocketPoolBase | 86 class ClientSocketPoolBase |
80 : public base::RefCounted<ClientSocketPoolBase>, | 87 : public base::RefCounted<ClientSocketPoolBase>, |
81 public ConnectJob::Delegate { | 88 public ConnectJob::Delegate { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 | 142 |
136 int idle_socket_count() const { | 143 int idle_socket_count() const { |
137 return idle_socket_count_; | 144 return idle_socket_count_; |
138 } | 145 } |
139 | 146 |
140 int IdleSocketCountInGroup(const std::string& group_name) const; | 147 int IdleSocketCountInGroup(const std::string& group_name) const; |
141 | 148 |
142 LoadState GetLoadState(const std::string& group_name, | 149 LoadState GetLoadState(const std::string& group_name, |
143 const ClientSocketHandle* handle) const; | 150 const ClientSocketHandle* handle) const; |
144 | 151 |
145 // If |was_async| is true, then ClientSocketPoolBase will pick a callback to | 152 virtual void OnConnectJobComplete(int result, ConnectJob* job); |
146 // run from a request associated with |group_name|. | |
147 virtual void OnConnectJobComplete( | |
148 const std::string& group_name, | |
149 const ClientSocketHandle* key_handle, | |
150 ClientSocket* socket, | |
151 int result, | |
152 bool was_async); | |
153 | 153 |
154 private: | 154 private: |
155 // Entry for a persistent socket which became idle at time |start_time|. | 155 // Entry for a persistent socket which became idle at time |start_time|. |
156 struct IdleSocket { | 156 struct IdleSocket { |
157 ClientSocket* socket; | 157 ClientSocket* socket; |
158 base::TimeTicks start_time; | 158 base::TimeTicks start_time; |
159 | 159 |
160 // An idle socket should be removed if it can't be reused, or has been idle | 160 // An idle socket should be removed if it can't be reused, or has been idle |
161 // for too long. |now| is the current time value (TimeTicks::Now()). | 161 // for too long. |now| is the current time value (TimeTicks::Now()). |
162 // | 162 // |
163 // An idle socket can't be reused if it is disconnected or has received | 163 // An idle socket can't be reused if it is disconnected or has received |
164 // data unexpectedly (hence no longer idle). The unread data would be | 164 // data unexpectedly (hence no longer idle). The unread data would be |
165 // mistaken for the beginning of the next response if we were to reuse the | 165 // mistaken for the beginning of the next response if we were to reuse the |
166 // socket for a new request. | 166 // socket for a new request. |
167 bool ShouldCleanup(base::TimeTicks now) const; | 167 bool ShouldCleanup(base::TimeTicks now) const; |
168 }; | 168 }; |
169 | 169 |
170 typedef std::deque<Request> RequestQueue; | 170 typedef std::deque<Request> RequestQueue; |
171 typedef std::map<const ClientSocketHandle*, Request> RequestMap; | 171 typedef std::map<const ClientSocketHandle*, Request> RequestMap; |
172 | 172 |
173 // A Group is allocated per group_name when there are idle sockets or pending | 173 // A Group is allocated per group_name when there are idle sockets or pending |
174 // requests. Otherwise, the Group object is removed from the map. | 174 // requests. Otherwise, the Group object is removed from the map. |
175 struct Group { | 175 struct Group { |
176 Group() : active_socket_count(0), sockets_handed_out_count(0) {} | 176 Group() : active_socket_count(0) {} |
| 177 |
| 178 bool IsEmpty() const { |
| 179 return active_socket_count == 0 && idle_sockets.empty() && |
| 180 connecting_requests.empty(); |
| 181 } |
| 182 |
| 183 bool HasAvailableSocketSlot(int max_sockets_per_group) const { |
| 184 return active_socket_count + |
| 185 static_cast<int>(connecting_requests.size()) < |
| 186 max_sockets_per_group; |
| 187 } |
| 188 |
177 std::deque<IdleSocket> idle_sockets; | 189 std::deque<IdleSocket> idle_sockets; |
178 RequestQueue pending_requests; | 190 RequestQueue pending_requests; |
179 RequestMap connecting_requests; | 191 RequestMap connecting_requests; |
180 int active_socket_count; // number of active sockets | 192 int active_socket_count; // number of active sockets used by clients |
181 int sockets_handed_out_count; // number of sockets given to clients | |
182 }; | 193 }; |
183 | 194 |
184 typedef std::map<std::string, Group> GroupMap; | 195 typedef std::map<std::string, Group> GroupMap; |
185 | 196 |
186 typedef std::map<const ClientSocketHandle*, ConnectJob*> ConnectJobMap; | 197 typedef std::map<const ClientSocketHandle*, ConnectJob*> ConnectJobMap; |
187 | 198 |
188 static void InsertRequestIntoQueue(const Request& r, | 199 static void InsertRequestIntoQueue(const Request& r, |
189 RequestQueue* pending_requests); | 200 RequestQueue* pending_requests); |
190 | 201 |
191 // Closes all idle sockets if |force| is true. Else, only closes idle | 202 // Closes all idle sockets if |force| is true. Else, only closes idle |
(...skipping 10 matching lines...) Expand all Loading... |
202 // Called when timer_ fires. This method scans the idle sockets removing | 213 // Called when timer_ fires. This method scans the idle sockets removing |
203 // sockets that timed out or can't be reused. | 214 // sockets that timed out or can't be reused. |
204 void OnCleanupTimerFired() { | 215 void OnCleanupTimerFired() { |
205 CleanupIdleSockets(false); | 216 CleanupIdleSockets(false); |
206 } | 217 } |
207 | 218 |
208 // Removes the ConnectJob corresponding to |handle| from the | 219 // Removes the ConnectJob corresponding to |handle| from the |
209 // |connect_job_map_|. | 220 // |connect_job_map_|. |
210 void RemoveConnectJob(const ClientSocketHandle* handle); | 221 void RemoveConnectJob(const ClientSocketHandle* handle); |
211 | 222 |
212 static void CheckSocketCounts(const Group& group); | 223 // Same as OnAvailableSocketSlot except it looks up the Group first to see if |
| 224 // it's there. |
| 225 void MaybeOnAvailableSocketSlot(const std::string& group_name); |
213 | 226 |
214 // Remove an active socket. | 227 // Might delete the Group from |group_map_|. |
215 void RemoveActiveSocket(const std::string& group_name, Group* group); | 228 void OnAvailableSocketSlot(const std::string& group_name, Group* group); |
216 | 229 |
217 // Process a request from a group's pending_requests queue. | 230 // Process a request from a group's pending_requests queue. |
218 void ProcessPendingRequest(const std::string& group_name, Group* group); | 231 void ProcessPendingRequest(const std::string& group_name, Group* group); |
219 | 232 |
| 233 // Assigns |socket| to |handle| and updates |group|'s counters appropriately. |
| 234 void HandOutSocket(ClientSocket* socket, |
| 235 bool reused, |
| 236 ClientSocketHandle* handle, |
| 237 Group* group); |
| 238 |
220 GroupMap group_map_; | 239 GroupMap group_map_; |
221 | 240 |
222 ConnectJobMap connect_job_map_; | 241 ConnectJobMap connect_job_map_; |
223 | 242 |
224 // Timer used to periodically prune idle sockets that timed out or can't be | 243 // Timer used to periodically prune idle sockets that timed out or can't be |
225 // reused. | 244 // reused. |
226 base::RepeatingTimer<ClientSocketPoolBase> timer_; | 245 base::RepeatingTimer<ClientSocketPoolBase> timer_; |
227 | 246 |
228 // The total number of idle sockets in the system. | 247 // The total number of idle sockets in the system. |
229 int idle_socket_count_; | 248 int idle_socket_count_; |
230 | 249 |
231 // The maximum number of sockets kept per group. | 250 // The maximum number of sockets kept per group. |
232 const int max_sockets_per_group_; | 251 const int max_sockets_per_group_; |
233 | 252 |
234 const scoped_ptr<ConnectJobFactory> connect_job_factory_; | 253 const scoped_ptr<ConnectJobFactory> connect_job_factory_; |
235 | 254 |
236 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); | 255 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); |
237 }; | 256 }; |
238 | 257 |
239 } // namespace net | 258 } // namespace net |
240 | 259 |
241 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 260 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
OLD | NEW |