blob: 77698ce715df8ed3fe4baf9f3c22521b1116676b [file] [log] [blame]
[email protected]a796bcec2010-03-22 17:17:261// Copyright (c) 2010 The Chromium Authors. All rights reserved.
[email protected]ff579d42009-06-24 15:47:022// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
[email protected]d80a4322009-08-14 07:07:494//
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.
7// Subclasses of ClientSocketPool should compose ClientSocketPoolBase to handle
8// the core logic of (1) restricting the number of active (connected or
9// connecting) sockets per "group" (generally speaking, the hostname), (2)
10// maintaining a per-group list of idle, persistent sockets for reuse, and (3)
11// limiting the total number of active sockets in the system.
12//
13// ClientSocketPoolBase abstracts socket connection details behind ConnectJob,
14// ConnectJobFactory, and SocketParams. When a socket "slot" becomes available,
15// the ClientSocketPoolBase will ask the ConnectJobFactory to create a
16// ConnectJob with a SocketParams. Subclasses of ClientSocketPool should
17// implement their socket specific connection by subclassing ConnectJob and
18// implementing ConnectJob::ConnectInternal(). They can control the parameters
19// passed to each new ConnectJob instance via their ConnectJobFactory subclass
20// and templated SocketParams parameter.
21//
[email protected]ff579d42009-06-24 15:47:0222#ifndef NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_
23#define NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_
24
25#include <deque>
26#include <map>
[email protected]5fc08e32009-07-15 17:09:5727#include <set>
[email protected]ff579d42009-06-24 15:47:0228#include <string>
29
30#include "base/basictypes.h"
[email protected]6b624c62010-03-14 08:37:3231#include "base/compiler_specific.h"
[email protected]100d5fb92009-12-21 21:08:3532#include "base/ref_counted.h"
[email protected]ff579d42009-06-24 15:47:0233#include "base/scoped_ptr.h"
[email protected]6b624c62010-03-14 08:37:3234#include "base/task.h"
[email protected]ff579d42009-06-24 15:47:0235#include "base/time.h"
36#include "base/timer.h"
37#include "net/base/address_list.h"
38#include "net/base/completion_callback.h"
[email protected]ff579d42009-06-24 15:47:0239#include "net/base/load_states.h"
[email protected]d80a4322009-08-14 07:07:4940#include "net/base/net_errors.h"
[email protected]9e743cd2010-03-16 07:03:5341#include "net/base/net_log.h"
[email protected]a554a8262010-05-20 00:13:5242#include "net/base/network_change_notifier.h"
[email protected]ac790b42009-12-02 04:31:3143#include "net/base/request_priority.h"
[email protected]2ab05b52009-07-01 23:57:5844#include "net/socket/client_socket.h"
[email protected]ff579d42009-06-24 15:47:0245#include "net/socket/client_socket_pool.h"
46
47namespace net {
48
[email protected]ff579d42009-06-24 15:47:0249class ClientSocketHandle;
[email protected]ff579d42009-06-24 15:47:0250
51// ConnectJob provides an abstract interface for "connecting" a socket.
52// The connection may involve host resolution, tcp connection, ssl connection,
53// etc.
54class ConnectJob {
55 public:
[email protected]ab838892009-06-30 18:49:0556 class Delegate {
57 public:
58 Delegate() {}
59 virtual ~Delegate() {}
60
[email protected]2ab05b52009-07-01 23:57:5861 // Alerts the delegate that the connection completed.
62 virtual void OnConnectJobComplete(int result, ConnectJob* job) = 0;
[email protected]ab838892009-06-30 18:49:0563
64 private:
65 DISALLOW_COPY_AND_ASSIGN(Delegate);
66 };
67
[email protected]974ebd62009-08-03 23:14:3468 // A |timeout_duration| of 0 corresponds to no timeout.
[email protected]2ab05b52009-07-01 23:57:5869 ConnectJob(const std::string& group_name,
[email protected]974ebd62009-08-03 23:14:3470 base::TimeDelta timeout_duration,
[email protected]fd7b7c92009-08-20 19:38:3071 Delegate* delegate,
[email protected]9e743cd2010-03-16 07:03:5372 const BoundNetLog& net_log);
[email protected]2ab05b52009-07-01 23:57:5873 virtual ~ConnectJob();
[email protected]ff579d42009-06-24 15:47:0274
[email protected]2ab05b52009-07-01 23:57:5875 // Accessors
76 const std::string& group_name() const { return group_name_; }
[email protected]9e743cd2010-03-16 07:03:5377 const BoundNetLog& net_log() { return net_log_; }
[email protected]2ab05b52009-07-01 23:57:5878
[email protected]8e12ae02009-07-02 16:15:0479 // Releases |socket_| to the client. On connection error, this should return
80 // NULL.
[email protected]2ab05b52009-07-01 23:57:5881 ClientSocket* ReleaseSocket() { return socket_.release(); }
[email protected]ab838892009-06-30 18:49:0582
[email protected]ff579d42009-06-24 15:47:0283 // Begins connecting the socket. Returns OK on success, ERR_IO_PENDING if it
84 // cannot complete synchronously without blocking, or another net error code
[email protected]2ab05b52009-07-01 23:57:5885 // on error. In asynchronous completion, the ConnectJob will notify
86 // |delegate_| via OnConnectJobComplete. In both asynchronous and synchronous
87 // completion, ReleaseSocket() can be called to acquire the connected socket
88 // if it succeeded.
[email protected]974ebd62009-08-03 23:14:3489 int Connect();
[email protected]ff579d42009-06-24 15:47:0290
[email protected]46451352009-09-01 14:54:2191 virtual LoadState GetLoadState() const = 0;
[email protected]fd7b7c92009-08-20 19:38:3092
[email protected]e60e47a2010-07-14 03:37:1893 // If Connect returns an error (or OnConnectJobComplete reports an error
94 // result) this method will be called, allowing the pool to add
95 // additional error state to the ClientSocketHandle (post late-binding).
96 virtual void GetAdditionalErrorState(ClientSocketHandle* handle) {}
97
[email protected]ab838892009-06-30 18:49:0598 protected:
[email protected]06650c52010-06-03 00:49:1799 void set_socket(ClientSocket* socket);
[email protected]2ab05b52009-07-01 23:57:58100 ClientSocket* socket() { return socket_.get(); }
[email protected]fd7b7c92009-08-20 19:38:30101 void NotifyDelegateOfCompletion(int rv);
[email protected]a796bcec2010-03-22 17:17:26102 void ResetTimer(base::TimeDelta remainingTime);
[email protected]ab838892009-06-30 18:49:05103
[email protected]ff579d42009-06-24 15:47:02104 private:
[email protected]974ebd62009-08-03 23:14:34105 virtual int ConnectInternal() = 0;
106
[email protected]06650c52010-06-03 00:49:17107 void LogConnectStart();
108 void LogConnectCompletion(int net_error);
109
[email protected]974ebd62009-08-03 23:14:34110 // Alerts the delegate that the ConnectJob has timed out.
111 void OnTimeout();
112
[email protected]2ab05b52009-07-01 23:57:58113 const std::string group_name_;
[email protected]974ebd62009-08-03 23:14:34114 const base::TimeDelta timeout_duration_;
115 // Timer to abort jobs that take too long.
116 base::OneShotTimer<ConnectJob> timer_;
117 Delegate* delegate_;
[email protected]2ab05b52009-07-01 23:57:58118 scoped_ptr<ClientSocket> socket_;
[email protected]9e743cd2010-03-16 07:03:53119 BoundNetLog net_log_;
[email protected]a2006ece2010-04-23 16:44:02120 // A ConnectJob is idle until Connect() has been called.
121 bool idle_;
[email protected]ab838892009-06-30 18:49:05122
[email protected]ff579d42009-06-24 15:47:02123 DISALLOW_COPY_AND_ASSIGN(ConnectJob);
124};
125
[email protected]d80a4322009-08-14 07:07:49126namespace internal {
127
128// ClientSocketPoolBaseHelper is an internal class that implements almost all
129// the functionality from ClientSocketPoolBase without using templates.
130// ClientSocketPoolBase adds templated definitions built on top of
131// ClientSocketPoolBaseHelper. This class is not for external use, please use
132// ClientSocketPoolBase instead.
133class ClientSocketPoolBaseHelper
134 : public base::RefCounted<ClientSocketPoolBaseHelper>,
[email protected]a554a8262010-05-20 00:13:52135 public ConnectJob::Delegate,
136 public NetworkChangeNotifier::Observer {
[email protected]ff579d42009-06-24 15:47:02137 public:
[email protected]d80a4322009-08-14 07:07:49138 class Request {
139 public:
[email protected]684970b2009-08-14 04:54:46140 Request(ClientSocketHandle* handle,
[email protected]ff579d42009-06-24 15:47:02141 CompletionCallback* callback,
[email protected]ac790b42009-12-02 04:31:31142 RequestPriority priority,
[email protected]9e743cd2010-03-16 07:03:53143 const BoundNetLog& net_log);
[email protected]ff579d42009-06-24 15:47:02144
[email protected]fd4fe0b2010-02-08 23:02:15145 virtual ~Request();
[email protected]d80a4322009-08-14 07:07:49146
147 ClientSocketHandle* handle() const { return handle_; }
148 CompletionCallback* callback() const { return callback_; }
[email protected]ac790b42009-12-02 04:31:31149 RequestPriority priority() const { return priority_; }
[email protected]9e743cd2010-03-16 07:03:53150 const BoundNetLog& net_log() const { return net_log_; }
[email protected]d80a4322009-08-14 07:07:49151
152 private:
153 ClientSocketHandle* const handle_;
154 CompletionCallback* const callback_;
[email protected]ac790b42009-12-02 04:31:31155 const RequestPriority priority_;
[email protected]9e743cd2010-03-16 07:03:53156 BoundNetLog net_log_;
[email protected]d80a4322009-08-14 07:07:49157
158 DISALLOW_COPY_AND_ASSIGN(Request);
[email protected]ff579d42009-06-24 15:47:02159 };
160
161 class ConnectJobFactory {
162 public:
163 ConnectJobFactory() {}
164 virtual ~ConnectJobFactory() {}
165
166 virtual ConnectJob* NewConnectJob(
167 const std::string& group_name,
168 const Request& request,
[email protected]06650c52010-06-03 00:49:17169 ConnectJob::Delegate* delegate) const = 0;
[email protected]ff579d42009-06-24 15:47:02170
[email protected]a796bcec2010-03-22 17:17:26171 virtual base::TimeDelta ConnectionTimeout() const = 0;
172
[email protected]ff579d42009-06-24 15:47:02173 private:
174 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory);
175 };
176
[email protected]100d5fb92009-12-21 21:08:35177 ClientSocketPoolBaseHelper(
178 int max_sockets,
179 int max_sockets_per_group,
180 base::TimeDelta unused_idle_socket_timeout,
181 base::TimeDelta used_idle_socket_timeout,
[email protected]66761b952010-06-25 21:30:38182 ConnectJobFactory* connect_job_factory);
[email protected]ff579d42009-06-24 15:47:02183
[email protected]d80a4322009-08-14 07:07:49184 // See ClientSocketPool::RequestSocket for documentation on this function.
[email protected]e7e99322010-05-04 23:30:17185 // ClientSocketPoolBaseHelper takes ownership of |request|, which must be
186 // heap allocated.
[email protected]d80a4322009-08-14 07:07:49187 int RequestSocket(const std::string& group_name, const Request* request);
[email protected]ff579d42009-06-24 15:47:02188
[email protected]d80a4322009-08-14 07:07:49189 // See ClientSocketPool::CancelRequest for documentation on this function.
[email protected]ff579d42009-06-24 15:47:02190 void CancelRequest(const std::string& group_name,
191 const ClientSocketHandle* handle);
192
[email protected]d80a4322009-08-14 07:07:49193 // See ClientSocketPool::ReleaseSocket for documentation on this function.
[email protected]ff579d42009-06-24 15:47:02194 void ReleaseSocket(const std::string& group_name,
[email protected]a7e38572010-06-07 18:22:24195 ClientSocket* socket,
196 int id);
[email protected]ff579d42009-06-24 15:47:02197
[email protected]a7e38572010-06-07 18:22:24198 // See ClientSocketPool::Flush for documentation on this function.
199 void Flush();
[email protected]241c5c2c2010-06-21 18:46:00200
[email protected]d80a4322009-08-14 07:07:49201 // See ClientSocketPool::CloseIdleSockets for documentation on this function.
[email protected]ff579d42009-06-24 15:47:02202 void CloseIdleSockets();
203
[email protected]d80a4322009-08-14 07:07:49204 // See ClientSocketPool::IdleSocketCount() for documentation on this function.
[email protected]ff579d42009-06-24 15:47:02205 int idle_socket_count() const {
206 return idle_socket_count_;
207 }
208
[email protected]d80a4322009-08-14 07:07:49209 // See ClientSocketPool::IdleSocketCountInGroup() for documentation on this
210 // function.
[email protected]ff579d42009-06-24 15:47:02211 int IdleSocketCountInGroup(const std::string& group_name) const;
212
[email protected]d80a4322009-08-14 07:07:49213 // See ClientSocketPool::GetLoadState() for documentation on this function.
[email protected]ff579d42009-06-24 15:47:02214 LoadState GetLoadState(const std::string& group_name,
215 const ClientSocketHandle* handle) const;
216
[email protected]6b624c62010-03-14 08:37:32217 int ConnectRetryIntervalMs() const {
218 // TODO(mbelshe): Make this tuned dynamically based on measured RTT.
219 // For now, just use the max retry interval.
220 return ClientSocketPool::kMaxConnectRetryIntervalMs;
221 }
222
[email protected]d80a4322009-08-14 07:07:49223 // ConnectJob::Delegate methods:
[email protected]2ab05b52009-07-01 23:57:58224 virtual void OnConnectJobComplete(int result, ConnectJob* job);
[email protected]ff579d42009-06-24 15:47:02225
[email protected]a554a8262010-05-20 00:13:52226 // NetworkChangeNotifier::Observer methods:
[email protected]66761b952010-06-25 21:30:38227 virtual void OnIPAddressChanged();
[email protected]a554a8262010-05-20 00:13:52228
[email protected]974ebd62009-08-03 23:14:34229 int NumConnectJobsInGroup(const std::string& group_name) const {
230 return group_map_.find(group_name)->second.jobs.size();
231 }
[email protected]211d2172009-07-22 15:48:53232
[email protected]9bf28db2009-08-29 01:35:16233 // Closes all idle sockets if |force| is true. Else, only closes idle
234 // sockets that timed out or can't be reused. Made public for testing.
235 void CleanupIdleSockets(bool force);
236
[email protected]a796bcec2010-03-22 17:17:26237 base::TimeDelta ConnectionTimeout() const {
238 return connect_job_factory_->ConnectionTimeout();
239 }
240
[email protected]43a21b82010-06-10 21:30:54241 void EnableBackupJobs() { backup_jobs_enabled_ = true; }
[email protected]7c28e9a2010-03-20 01:16:13242
[email protected]ff579d42009-06-24 15:47:02243 private:
[email protected]5389bc72009-11-05 23:34:24244 friend class base::RefCounted<ClientSocketPoolBaseHelper>;
245
246 ~ClientSocketPoolBaseHelper();
247
[email protected]ff579d42009-06-24 15:47:02248 // Entry for a persistent socket which became idle at time |start_time|.
249 struct IdleSocket {
[email protected]5fc08e32009-07-15 17:09:57250 IdleSocket() : socket(NULL), used(false) {}
[email protected]ff579d42009-06-24 15:47:02251 ClientSocket* socket;
252 base::TimeTicks start_time;
[email protected]5fc08e32009-07-15 17:09:57253 bool used; // Indicates whether or not the socket has been used yet.
[email protected]ff579d42009-06-24 15:47:02254
255 // An idle socket should be removed if it can't be reused, or has been idle
256 // for too long. |now| is the current time value (TimeTicks::Now()).
[email protected]9bf28db2009-08-29 01:35:16257 // |timeout| is the length of time to wait before timing out an idle socket.
[email protected]ff579d42009-06-24 15:47:02258 //
259 // An idle socket can't be reused if it is disconnected or has received
260 // data unexpectedly (hence no longer idle). The unread data would be
261 // mistaken for the beginning of the next response if we were to reuse the
262 // socket for a new request.
[email protected]9bf28db2009-08-29 01:35:16263 bool ShouldCleanup(base::TimeTicks now, base::TimeDelta timeout) const;
[email protected]ff579d42009-06-24 15:47:02264 };
265
[email protected]d80a4322009-08-14 07:07:49266 typedef std::deque<const Request*> RequestQueue;
267 typedef std::map<const ClientSocketHandle*, const Request*> RequestMap;
[email protected]ff579d42009-06-24 15:47:02268
269 // A Group is allocated per group_name when there are idle sockets or pending
270 // requests. Otherwise, the Group object is removed from the map.
[email protected]eb5a99382010-07-11 03:18:26271 // |active_socket_count| tracks the number of sockets held by clients.
[email protected]ff579d42009-06-24 15:47:02272 struct Group {
[email protected]6b624c62010-03-14 08:37:32273 Group()
274 : active_socket_count(0),
[email protected]6b624c62010-03-14 08:37:32275 backup_job(NULL),
276 backup_task(NULL) {
277 }
278
279 ~Group() {
280 CleanupBackupJob();
281 }
[email protected]2ab05b52009-07-01 23:57:58282
283 bool IsEmpty() const {
[email protected]2b7523d2009-07-29 20:29:23284 return active_socket_count == 0 && idle_sockets.empty() && jobs.empty() &&
[email protected]4d3b05d2010-01-27 21:27:29285 pending_requests.empty();
[email protected]2ab05b52009-07-01 23:57:58286 }
287
288 bool HasAvailableSocketSlot(int max_sockets_per_group) const {
[email protected]5fc08e32009-07-15 17:09:57289 return active_socket_count + static_cast<int>(jobs.size()) <
[email protected]2ab05b52009-07-01 23:57:58290 max_sockets_per_group;
291 }
292
[email protected]ac790b42009-12-02 04:31:31293 RequestPriority TopPendingPriority() const {
[email protected]d80a4322009-08-14 07:07:49294 return pending_requests.front()->priority();
[email protected]211d2172009-07-22 15:48:53295 }
296
[email protected]6b624c62010-03-14 08:37:32297 void CleanupBackupJob() {
298 if (backup_job) {
299 delete backup_job;
300 backup_job = NULL;
301 }
302 if (backup_task) {
303 backup_task->Cancel();
304 backup_task = NULL;
305 }
306 }
307
[email protected]ff579d42009-06-24 15:47:02308 std::deque<IdleSocket> idle_sockets;
[email protected]5fc08e32009-07-15 17:09:57309 std::set<const ConnectJob*> jobs;
[email protected]ff579d42009-06-24 15:47:02310 RequestQueue pending_requests;
[email protected]2ab05b52009-07-01 23:57:58311 int active_socket_count; // number of active sockets used by clients
[email protected]6b624c62010-03-14 08:37:32312 // A backup job in case the connect for this group takes too long.
313 ConnectJob* backup_job;
314 CancelableTask* backup_task;
[email protected]ff579d42009-06-24 15:47:02315 };
316
317 typedef std::map<std::string, Group> GroupMap;
318
[email protected]5fc08e32009-07-15 17:09:57319 typedef std::set<const ConnectJob*> ConnectJobSet;
[email protected]ff579d42009-06-24 15:47:02320
[email protected]d80a4322009-08-14 07:07:49321 static void InsertRequestIntoQueue(const Request* r,
[email protected]ff579d42009-06-24 15:47:02322 RequestQueue* pending_requests);
[email protected]fd7b7c92009-08-20 19:38:30323 static const Request* RemoveRequestFromQueue(RequestQueue::iterator it,
324 RequestQueue* pending_requests);
[email protected]ff579d42009-06-24 15:47:02325
[email protected]ff579d42009-06-24 15:47:02326 // Called when the number of idle sockets changes.
327 void IncrementIdleCount();
328 void DecrementIdleCount();
329
[email protected]211d2172009-07-22 15:48:53330 // Scans the group map for groups which have an available socket slot and
331 // at least one pending request. Returns number of groups found, and if found
332 // at least one, fills |group| and |group_name| with data of the stalled group
333 // having highest priority.
334 int FindTopStalledGroup(Group** group, std::string* group_name);
335
[email protected]ff579d42009-06-24 15:47:02336 // Called when timer_ fires. This method scans the idle sockets removing
337 // sockets that timed out or can't be reused.
338 void OnCleanupTimerFired() {
339 CleanupIdleSockets(false);
340 }
341
[email protected]4d3b05d2010-01-27 21:27:29342 // Removes |job| from |connect_job_set_|. Also updates |group| if non-NULL.
343 void RemoveConnectJob(const ConnectJob* job, Group* group);
[email protected]ff579d42009-06-24 15:47:02344
[email protected]8ae03f42010-07-07 19:08:10345 // Might delete the Group from |group_map_|.
[email protected]eb5a99382010-07-11 03:18:26346 // If |was_at_socket_limit|, will also check for idle sockets to assign
347 // to any stalled groups.
348 void OnAvailableSocketSlot(const std::string& group_name,
349 bool was_at_socket_limit);
[email protected]8ae03f42010-07-07 19:08:10350
[email protected]eb5a99382010-07-11 03:18:26351 // Process a pending socket request for a group.
352 // If |was_at_socket_limit|, will also check for idle sockets to assign
353 // to any stalled groups.
354 void ProcessPendingRequest(const std::string& group_name,
355 bool was_at_socket_limit);
[email protected]ff579d42009-06-24 15:47:02356
[email protected]2ab05b52009-07-01 23:57:58357 // Assigns |socket| to |handle| and updates |group|'s counters appropriately.
358 void HandOutSocket(ClientSocket* socket,
359 bool reused,
360 ClientSocketHandle* handle,
[email protected]f9d285c2009-08-17 19:54:29361 base::TimeDelta time_idle,
[email protected]fd4fe0b2010-02-08 23:02:15362 Group* group,
[email protected]9e743cd2010-03-16 07:03:53363 const BoundNetLog& net_log);
[email protected]2ab05b52009-07-01 23:57:58364
[email protected]5fc08e32009-07-15 17:09:57365 // Adds |socket| to the list of idle sockets for |group|. |used| indicates
366 // whether or not the socket has previously been used.
367 void AddIdleSocket(ClientSocket* socket, bool used, Group* group);
368
369 // Iterates through |connect_job_map_|, canceling all ConnectJobs.
370 // Afterwards, it iterates through all groups and deletes them if they are no
371 // longer needed.
372 void CancelAllConnectJobs();
373
[email protected]211d2172009-07-22 15:48:53374 // Returns true if we can't create any more sockets due to the total limit.
[email protected]211d2172009-07-22 15:48:53375 bool ReachedMaxSocketsLimit() const;
376
[email protected]fd4fe0b2010-02-08 23:02:15377 // This is the internal implementation of RequestSocket(). It differs in that
[email protected]9e743cd2010-03-16 07:03:53378 // it does not handle logging into NetLog of the queueing status of
[email protected]fd4fe0b2010-02-08 23:02:15379 // |request|.
380 int RequestSocketInternal(const std::string& group_name,
381 const Request* request);
382
[email protected]eb5a99382010-07-11 03:18:26383 // Assigns an idle socket for the group to the request.
384 // Returns |true| if an idle socket is available, false otherwise.
385 bool AssignIdleSocketToGroup(Group* group, const Request* request);
386
[email protected]06650c52010-06-03 00:49:17387 static void LogBoundConnectJobToRequest(
388 const NetLog::Source& connect_job_source, const Request* request);
389
[email protected]6b624c62010-03-14 08:37:32390 // Set a timer to create a backup socket if it takes too long to create one.
391 void StartBackupSocketTimer(const std::string& group_name);
392
393 // Called when the backup socket timer fires.
394 void OnBackupSocketTimerFired(const std::string& group_name);
395
[email protected]43a21b82010-06-10 21:30:54396 // Closes one idle socket. Picks the first one encountered.
397 // TODO(willchan): Consider a better algorithm for doing this. Perhaps we
398 // should keep an ordered list of idle sockets, and close them in order.
399 // Requires maintaining more state. It's not clear if it's worth it since
400 // I'm not sure if we hit this situation often.
401 void CloseOneIdleSocket();
402
[email protected]eb5a99382010-07-11 03:18:26403 // Checks if there are stalled socket groups that should be notified
404 // for possible wakeup.
405 void CheckForStalledSocketGroups();
406
407 // Returns true if we might have a stalled group.
408 bool MayHaveStalledGroups();
409
[email protected]ff579d42009-06-24 15:47:02410 GroupMap group_map_;
411
[email protected]ff579d42009-06-24 15:47:02412 // Timer used to periodically prune idle sockets that timed out or can't be
413 // reused.
[email protected]d80a4322009-08-14 07:07:49414 base::RepeatingTimer<ClientSocketPoolBaseHelper> timer_;
[email protected]ff579d42009-06-24 15:47:02415
416 // The total number of idle sockets in the system.
417 int idle_socket_count_;
418
[email protected]211d2172009-07-22 15:48:53419 // Number of connecting sockets across all groups.
420 int connecting_socket_count_;
421
422 // Number of connected sockets we handed out across all groups.
423 int handed_out_socket_count_;
424
425 // The maximum total number of sockets. See ReachedMaxSocketsLimit.
426 const int max_sockets_;
427
[email protected]ff579d42009-06-24 15:47:02428 // The maximum number of sockets kept per group.
429 const int max_sockets_per_group_;
430
[email protected]9bf28db2009-08-29 01:35:16431 // The time to wait until closing idle sockets.
432 const base::TimeDelta unused_idle_socket_timeout_;
433 const base::TimeDelta used_idle_socket_timeout_;
434
[email protected]ab838892009-06-30 18:49:05435 const scoped_ptr<ConnectJobFactory> connect_job_factory_;
[email protected]ff579d42009-06-24 15:47:02436
[email protected]7c28e9a2010-03-20 01:16:13437 // TODO(vandebo) Remove when backup jobs move to TCPClientSocketPool
438 bool backup_jobs_enabled_;
439
[email protected]6b624c62010-03-14 08:37:32440 // A factory to pin the backup_job tasks.
441 ScopedRunnableMethodFactory<ClientSocketPoolBaseHelper> method_factory_;
[email protected]a7e38572010-06-07 18:22:24442
443 // A unique id for the pool. It gets incremented every time we Flush() the
444 // pool. This is so that when sockets get released back to the pool, we can
445 // make sure that they are discarded rather than reused.
446 int pool_generation_number_;
[email protected]eb5a99382010-07-11 03:18:26447
448 // The count of stalled groups the last time we checked.
449 int last_stalled_group_count_;
[email protected]d80a4322009-08-14 07:07:49450};
451
452} // namespace internal
453
[email protected]9bf28db2009-08-29 01:35:16454// The maximum duration, in seconds, to keep used idle persistent sockets alive.
455static const int kUsedIdleSocketTimeout = 300; // 5 minutes
456
[email protected]d80a4322009-08-14 07:07:49457template <typename SocketParams>
458class ClientSocketPoolBase {
459 public:
460 class Request : public internal::ClientSocketPoolBaseHelper::Request {
461 public:
462 Request(ClientSocketHandle* handle,
463 CompletionCallback* callback,
[email protected]ac790b42009-12-02 04:31:31464 RequestPriority priority,
[email protected]df4b4ef2010-07-12 18:25:21465 const scoped_refptr<SocketParams>& params,
[email protected]9e743cd2010-03-16 07:03:53466 const BoundNetLog& net_log)
[email protected]d80a4322009-08-14 07:07:49467 : internal::ClientSocketPoolBaseHelper::Request(
[email protected]9e743cd2010-03-16 07:03:53468 handle, callback, priority, net_log),
[email protected]d80a4322009-08-14 07:07:49469 params_(params) {}
470
[email protected]df4b4ef2010-07-12 18:25:21471 const scoped_refptr<SocketParams>& params() const { return params_; }
[email protected]d80a4322009-08-14 07:07:49472
473 private:
[email protected]df4b4ef2010-07-12 18:25:21474 scoped_refptr<SocketParams> params_;
[email protected]d80a4322009-08-14 07:07:49475 };
476
477 class ConnectJobFactory {
478 public:
479 ConnectJobFactory() {}
480 virtual ~ConnectJobFactory() {}
481
482 virtual ConnectJob* NewConnectJob(
483 const std::string& group_name,
484 const Request& request,
[email protected]06650c52010-06-03 00:49:17485 ConnectJob::Delegate* delegate) const = 0;
[email protected]d80a4322009-08-14 07:07:49486
[email protected]a796bcec2010-03-22 17:17:26487 virtual base::TimeDelta ConnectionTimeout() const = 0;
488
[email protected]d80a4322009-08-14 07:07:49489 private:
490 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory);
491 };
492
[email protected]9bf28db2009-08-29 01:35:16493 // |max_sockets| is the maximum number of sockets to be maintained by this
494 // ClientSocketPool. |max_sockets_per_group| specifies the maximum number of
495 // sockets a "group" can have. |unused_idle_socket_timeout| specifies how
496 // long to leave an unused idle socket open before closing it.
497 // |used_idle_socket_timeout| specifies how long to leave a previously used
498 // idle socket open before closing it.
[email protected]100d5fb92009-12-21 21:08:35499 ClientSocketPoolBase(
500 int max_sockets,
501 int max_sockets_per_group,
[email protected]b89f7e42010-05-20 20:37:00502 const scoped_refptr<ClientSocketPoolHistograms>& histograms,
[email protected]100d5fb92009-12-21 21:08:35503 base::TimeDelta unused_idle_socket_timeout,
504 base::TimeDelta used_idle_socket_timeout,
[email protected]66761b952010-06-25 21:30:38505 ConnectJobFactory* connect_job_factory)
[email protected]b89f7e42010-05-20 20:37:00506 : histograms_(histograms),
[email protected]a796bcec2010-03-22 17:17:26507 helper_(new internal::ClientSocketPoolBaseHelper(
[email protected]d80a4322009-08-14 07:07:49508 max_sockets, max_sockets_per_group,
[email protected]9bf28db2009-08-29 01:35:16509 unused_idle_socket_timeout, used_idle_socket_timeout,
[email protected]66761b952010-06-25 21:30:38510 new ConnectJobFactoryAdaptor(connect_job_factory))) {}
[email protected]d80a4322009-08-14 07:07:49511
[email protected]20cb5f482009-12-16 01:01:25512 virtual ~ClientSocketPoolBase() {}
[email protected]d80a4322009-08-14 07:07:49513
514 // These member functions simply forward to ClientSocketPoolBaseHelper.
515
516 // RequestSocket bundles up the parameters into a Request and then forwards to
517 // ClientSocketPoolBaseHelper::RequestSocket(). Note that the memory
518 // ownership is transferred in the asynchronous (ERR_IO_PENDING) case.
519 int RequestSocket(const std::string& group_name,
[email protected]df4b4ef2010-07-12 18:25:21520 const scoped_refptr<SocketParams>& params,
[email protected]ac790b42009-12-02 04:31:31521 RequestPriority priority,
[email protected]d80a4322009-08-14 07:07:49522 ClientSocketHandle* handle,
523 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53524 const BoundNetLog& net_log) {
[email protected]e7e99322010-05-04 23:30:17525 Request* request = new Request(handle, callback, priority, params, net_log);
526 return helper_->RequestSocket(group_name, request);
[email protected]d80a4322009-08-14 07:07:49527 }
528
529 void CancelRequest(const std::string& group_name,
530 const ClientSocketHandle* handle) {
531 return helper_->CancelRequest(group_name, handle);
532 }
533
[email protected]241c5c2c2010-06-21 18:46:00534 void ReleaseSocket(const std::string& group_name, ClientSocket* socket,
535 int id) {
[email protected]a7e38572010-06-07 18:22:24536 return helper_->ReleaseSocket(group_name, socket, id);
[email protected]d80a4322009-08-14 07:07:49537 }
538
539 void CloseIdleSockets() { return helper_->CloseIdleSockets(); }
540
541 int idle_socket_count() const { return helper_->idle_socket_count(); }
542
543 int IdleSocketCountInGroup(const std::string& group_name) const {
544 return helper_->IdleSocketCountInGroup(group_name);
545 }
546
547 LoadState GetLoadState(const std::string& group_name,
548 const ClientSocketHandle* handle) const {
549 return helper_->GetLoadState(group_name, handle);
550 }
551
552 virtual void OnConnectJobComplete(int result, ConnectJob* job) {
553 return helper_->OnConnectJobComplete(result, job);
554 }
555
[email protected]d80a4322009-08-14 07:07:49556 int NumConnectJobsInGroup(const std::string& group_name) const {
557 return helper_->NumConnectJobsInGroup(group_name);
558 }
559
[email protected]9bf28db2009-08-29 01:35:16560 void CleanupIdleSockets(bool force) {
561 return helper_->CleanupIdleSockets(force);
562 }
563
[email protected]a796bcec2010-03-22 17:17:26564 base::TimeDelta ConnectionTimeout() const {
565 return helper_->ConnectionTimeout();
566 }
567
[email protected]b89f7e42010-05-20 20:37:00568 scoped_refptr<ClientSocketPoolHistograms> histograms() const {
569 return histograms_;
570 }
[email protected]a796bcec2010-03-22 17:17:26571
[email protected]43a21b82010-06-10 21:30:54572 void EnableBackupJobs() { helper_->EnableBackupJobs(); }
[email protected]7c28e9a2010-03-20 01:16:13573
[email protected]a7e38572010-06-07 18:22:24574 void Flush() { helper_->Flush(); }
575
[email protected]d80a4322009-08-14 07:07:49576 private:
577 // This adaptor class exists to bridge the
578 // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and
579 // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the
580 // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to
581 // static_cast themselves.
582 class ConnectJobFactoryAdaptor
583 : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory {
584 public:
585 typedef typename ClientSocketPoolBase<SocketParams>::ConnectJobFactory
586 ConnectJobFactory;
587
588 explicit ConnectJobFactoryAdaptor(
589 ConnectJobFactory* connect_job_factory)
590 : connect_job_factory_(connect_job_factory) {}
591 virtual ~ConnectJobFactoryAdaptor() {}
592
593 virtual ConnectJob* NewConnectJob(
594 const std::string& group_name,
595 const internal::ClientSocketPoolBaseHelper::Request& request,
[email protected]06650c52010-06-03 00:49:17596 ConnectJob::Delegate* delegate) const {
[email protected]d80a4322009-08-14 07:07:49597 const Request* casted_request = static_cast<const Request*>(&request);
598 return connect_job_factory_->NewConnectJob(
[email protected]06650c52010-06-03 00:49:17599 group_name, *casted_request, delegate);
[email protected]d80a4322009-08-14 07:07:49600 }
601
[email protected]a796bcec2010-03-22 17:17:26602 virtual base::TimeDelta ConnectionTimeout() const {
603 return connect_job_factory_->ConnectionTimeout();
604 }
605
[email protected]d80a4322009-08-14 07:07:49606 const scoped_ptr<ConnectJobFactory> connect_job_factory_;
607 };
608
[email protected]b89f7e42010-05-20 20:37:00609 // Histograms for the pool
610 const scoped_refptr<ClientSocketPoolHistograms> histograms_;
[email protected]a796bcec2010-03-22 17:17:26611
[email protected]eb5a99382010-07-11 03:18:26612 // The reason for reference counting here is because the operations on
613 // the ClientSocketPoolBaseHelper which release sockets can cause the
614 // ClientSocketPoolBase<T> reference to drop to zero. While we're deep
615 // in cleanup code, we'll often hold a reference to |self|.
[email protected]d80a4322009-08-14 07:07:49616 scoped_refptr<internal::ClientSocketPoolBaseHelper> helper_;
617
[email protected]ff579d42009-06-24 15:47:02618 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase);
619};
620
[email protected]ff579d42009-06-24 15:47:02621} // namespace net
622
623#endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_