• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
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 //
22 #ifndef NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_
23 #define NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_
24 #pragma once
25 
26 #include <deque>
27 #include <list>
28 #include <map>
29 #include <set>
30 #include <string>
31 
32 #include "base/basictypes.h"
33 #include "base/memory/ref_counted.h"
34 #include "base/memory/scoped_ptr.h"
35 #include "base/task.h"
36 #include "base/time.h"
37 #include "base/timer.h"
38 #include "net/base/address_list.h"
39 #include "net/base/completion_callback.h"
40 #include "net/base/load_states.h"
41 #include "net/base/net_errors.h"
42 #include "net/base/net_log.h"
43 #include "net/base/network_change_notifier.h"
44 #include "net/base/request_priority.h"
45 #include "net/socket/client_socket.h"
46 #include "net/socket/client_socket_pool.h"
47 
48 namespace net {
49 
50 class ClientSocketHandle;
51 
52 // ConnectJob provides an abstract interface for "connecting" a socket.
53 // The connection may involve host resolution, tcp connection, ssl connection,
54 // etc.
55 class ConnectJob {
56  public:
57   class Delegate {
58    public:
Delegate()59     Delegate() {}
~Delegate()60     virtual ~Delegate() {}
61 
62     // Alerts the delegate that the connection completed.
63     virtual void OnConnectJobComplete(int result, ConnectJob* job) = 0;
64 
65    private:
66     DISALLOW_COPY_AND_ASSIGN(Delegate);
67   };
68 
69   // A |timeout_duration| of 0 corresponds to no timeout.
70   ConnectJob(const std::string& group_name,
71              base::TimeDelta timeout_duration,
72              Delegate* delegate,
73              const BoundNetLog& net_log);
74   virtual ~ConnectJob();
75 
76   // Accessors
group_name()77   const std::string& group_name() const { return group_name_; }
net_log()78   const BoundNetLog& net_log() { return net_log_; }
is_preconnect()79   bool is_preconnect() const { return preconnect_state_ != NOT_PRECONNECT; }
is_unused_preconnect()80   bool is_unused_preconnect() const {
81     return preconnect_state_ == UNUSED_PRECONNECT;
82   }
83 
84   // Initialized by the ClientSocketPoolBaseHelper.
85   // TODO(willchan): Move most of the constructor arguments over here.  We
86   // shouldn't give the ConnectJobFactory (subclasses) the ability to screw up
87   // the initialization.
88   void Initialize(bool is_preconnect);
89 
90   // Releases |socket_| to the client.  On connection error, this should return
91   // NULL.
ReleaseSocket()92   ClientSocket* ReleaseSocket() { return socket_.release(); }
93 
94   // Begins connecting the socket.  Returns OK on success, ERR_IO_PENDING if it
95   // cannot complete synchronously without blocking, or another net error code
96   // on error.  In asynchronous completion, the ConnectJob will notify
97   // |delegate_| via OnConnectJobComplete.  In both asynchronous and synchronous
98   // completion, ReleaseSocket() can be called to acquire the connected socket
99   // if it succeeded.
100   int Connect();
101 
102   // Precondition: is_unused_preconnect() must be true.  Marks the job as a
103   // used preconnect job.
104   void UseForNormalRequest();
105 
106   virtual LoadState GetLoadState() const = 0;
107 
108   // If Connect returns an error (or OnConnectJobComplete reports an error
109   // result) this method will be called, allowing the pool to add
110   // additional error state to the ClientSocketHandle (post late-binding).
GetAdditionalErrorState(ClientSocketHandle * handle)111   virtual void GetAdditionalErrorState(ClientSocketHandle* handle) {}
112 
net_log()113   const BoundNetLog& net_log() const { return net_log_; }
114 
115  protected:
116   void set_socket(ClientSocket* socket);
socket()117   ClientSocket* socket() { return socket_.get(); }
118   void NotifyDelegateOfCompletion(int rv);
119   void ResetTimer(base::TimeDelta remainingTime);
120 
121  private:
122   enum PreconnectState {
123     NOT_PRECONNECT,
124     UNUSED_PRECONNECT,
125     USED_PRECONNECT,
126   };
127 
128   virtual int ConnectInternal() = 0;
129 
130   void LogConnectStart();
131   void LogConnectCompletion(int net_error);
132 
133   // Alerts the delegate that the ConnectJob has timed out.
134   void OnTimeout();
135 
136   const std::string group_name_;
137   const base::TimeDelta timeout_duration_;
138   // Timer to abort jobs that take too long.
139   base::OneShotTimer<ConnectJob> timer_;
140   Delegate* delegate_;
141   scoped_ptr<ClientSocket> socket_;
142   BoundNetLog net_log_;
143   // A ConnectJob is idle until Connect() has been called.
144   bool idle_;
145   PreconnectState preconnect_state_;
146 
147   DISALLOW_COPY_AND_ASSIGN(ConnectJob);
148 };
149 
150 namespace internal {
151 
152 // ClientSocketPoolBaseHelper is an internal class that implements almost all
153 // the functionality from ClientSocketPoolBase without using templates.
154 // ClientSocketPoolBase adds templated definitions built on top of
155 // ClientSocketPoolBaseHelper.  This class is not for external use, please use
156 // ClientSocketPoolBase instead.
157 class ClientSocketPoolBaseHelper
158     : public ConnectJob::Delegate,
159       public NetworkChangeNotifier::IPAddressObserver {
160  public:
161   typedef uint32 Flags;
162 
163   // Used to specify specific behavior for the ClientSocketPool.
164   enum Flag {
165     NORMAL = 0,  // Normal behavior.
166     NO_IDLE_SOCKETS = 0x1,  // Do not return an idle socket. Create a new one.
167   };
168 
169   class Request {
170    public:
171     Request(ClientSocketHandle* handle,
172             CompletionCallback* callback,
173             RequestPriority priority,
174             bool ignore_limits,
175             Flags flags,
176             const BoundNetLog& net_log
177 #ifdef ANDROID
178             , bool valid_uid, uid_t calling_uid
179 #endif
180             );
181 
182     virtual ~Request();
183 
handle()184     ClientSocketHandle* handle() const { return handle_; }
callback()185     CompletionCallback* callback() const { return callback_; }
priority()186     RequestPriority priority() const { return priority_; }
ignore_limits()187     bool ignore_limits() const { return ignore_limits_; }
flags()188     Flags flags() const { return flags_; }
net_log()189     const BoundNetLog& net_log() const { return net_log_; }
190 
191    private:
192     ClientSocketHandle* const handle_;
193     CompletionCallback* const callback_;
194     const RequestPriority priority_;
195     bool ignore_limits_;
196     const Flags flags_;
197     BoundNetLog net_log_;
198 #ifdef ANDROID
199     bool valid_uid_;
200     uid_t calling_uid_;
201 #endif
202 
203     DISALLOW_COPY_AND_ASSIGN(Request);
204   };
205 
206   class ConnectJobFactory {
207    public:
ConnectJobFactory()208     ConnectJobFactory() {}
~ConnectJobFactory()209     virtual ~ConnectJobFactory() {}
210 
211     virtual ConnectJob* NewConnectJob(
212         const std::string& group_name,
213         const Request& request,
214         ConnectJob::Delegate* delegate) const = 0;
215 
216     virtual base::TimeDelta ConnectionTimeout() const = 0;
217 
218    private:
219     DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory);
220   };
221 
222   ClientSocketPoolBaseHelper(
223       int max_sockets,
224       int max_sockets_per_group,
225       base::TimeDelta unused_idle_socket_timeout,
226       base::TimeDelta used_idle_socket_timeout,
227       ConnectJobFactory* connect_job_factory);
228 
229   ~ClientSocketPoolBaseHelper();
230 
231   // See ClientSocketPool::RequestSocket for documentation on this function.
232   // ClientSocketPoolBaseHelper takes ownership of |request|, which must be
233   // heap allocated.
234   int RequestSocket(const std::string& group_name, const Request* request);
235 
236   // See ClientSocketPool::RequestSocket for documentation on this function.
237   void RequestSockets(const std::string& group_name,
238                       const Request& request,
239                       int num_sockets);
240 
241   // See ClientSocketPool::CancelRequest for documentation on this function.
242   void CancelRequest(const std::string& group_name,
243                      ClientSocketHandle* handle);
244 
245   // See ClientSocketPool::ReleaseSocket for documentation on this function.
246   void ReleaseSocket(const std::string& group_name,
247                      ClientSocket* socket,
248                      int id);
249 
250   // See ClientSocketPool::Flush for documentation on this function.
251   void Flush();
252 
253   // See ClientSocketPool::CloseIdleSockets for documentation on this function.
254   void CloseIdleSockets();
255 
256   // See ClientSocketPool::IdleSocketCount() for documentation on this function.
idle_socket_count()257   int idle_socket_count() const {
258     return idle_socket_count_;
259   }
260 
261   // See ClientSocketPool::IdleSocketCountInGroup() for documentation on this
262   // function.
263   int IdleSocketCountInGroup(const std::string& group_name) const;
264 
265   // See ClientSocketPool::GetLoadState() for documentation on this function.
266   LoadState GetLoadState(const std::string& group_name,
267                          const ClientSocketHandle* handle) const;
268 
ConnectRetryIntervalMs()269   int ConnectRetryIntervalMs() const {
270     // TODO(mbelshe): Make this tuned dynamically based on measured RTT.
271     //                For now, just use the max retry interval.
272     return ClientSocketPool::kMaxConnectRetryIntervalMs;
273   }
274 
NumConnectJobsInGroup(const std::string & group_name)275   int NumConnectJobsInGroup(const std::string& group_name) const {
276     return group_map_.find(group_name)->second->jobs().size();
277   }
278 
NumActiveSocketsInGroup(const std::string & group_name)279   int NumActiveSocketsInGroup(const std::string& group_name) const {
280     return group_map_.find(group_name)->second->active_socket_count();
281   }
282 
283   bool HasGroup(const std::string& group_name) const;
284 
285   // Called to enable/disable cleaning up idle sockets. When enabled,
286   // idle sockets that have been around for longer than a period defined
287   // by kCleanupInterval are cleaned up using a timer. Otherwise they are
288   // closed next time client makes a request. This may reduce network
289   // activity and power consumption.
290   static bool cleanup_timer_enabled();
291   static bool set_cleanup_timer_enabled(bool enabled);
292 
293   // Closes all idle sockets if |force| is true.  Else, only closes idle
294   // sockets that timed out or can't be reused.  Made public for testing.
295   void CleanupIdleSockets(bool force);
296 
297   // See ClientSocketPool::GetInfoAsValue for documentation on this function.
298   DictionaryValue* GetInfoAsValue(const std::string& name,
299                                   const std::string& type) const;
300 
ConnectionTimeout()301   base::TimeDelta ConnectionTimeout() const {
302     return connect_job_factory_->ConnectionTimeout();
303   }
304 
305   static bool connect_backup_jobs_enabled();
306   static bool set_connect_backup_jobs_enabled(bool enabled);
307 
308   void EnableConnectBackupJobs();
309 
310   // ConnectJob::Delegate methods:
311   virtual void OnConnectJobComplete(int result, ConnectJob* job);
312 
313   // NetworkChangeNotifier::IPAddressObserver methods:
314   virtual void OnIPAddressChanged();
315 
316  private:
317   friend class base::RefCounted<ClientSocketPoolBaseHelper>;
318 
319   // Entry for a persistent socket which became idle at time |start_time|.
320   struct IdleSocket {
IdleSocketIdleSocket321     IdleSocket() : socket(NULL) {}
322 
323     // An idle socket should be removed if it can't be reused, or has been idle
324     // for too long. |now| is the current time value (TimeTicks::Now()).
325     // |timeout| is the length of time to wait before timing out an idle socket.
326     //
327     // An idle socket can't be reused if it is disconnected or has received
328     // data unexpectedly (hence no longer idle).  The unread data would be
329     // mistaken for the beginning of the next response if we were to reuse the
330     // socket for a new request.
331     bool ShouldCleanup(base::TimeTicks now, base::TimeDelta timeout) const;
332 
333     ClientSocket* socket;
334     base::TimeTicks start_time;
335   };
336 
337   typedef std::deque<const Request* > RequestQueue;
338   typedef std::map<const ClientSocketHandle*, const Request*> RequestMap;
339 
340   // A Group is allocated per group_name when there are idle sockets or pending
341   // requests.  Otherwise, the Group object is removed from the map.
342   // |active_socket_count| tracks the number of sockets held by clients.
343   class Group {
344    public:
345     Group();
346     ~Group();
347 
IsEmpty()348     bool IsEmpty() const {
349       return active_socket_count_ == 0 && idle_sockets_.empty() &&
350           jobs_.empty() && pending_requests_.empty();
351     }
352 
HasAvailableSocketSlot(int max_sockets_per_group)353     bool HasAvailableSocketSlot(int max_sockets_per_group) const {
354       return NumActiveSocketSlots() < max_sockets_per_group;
355     }
356 
NumActiveSocketSlots()357     int NumActiveSocketSlots() const {
358       return active_socket_count_ + static_cast<int>(jobs_.size()) +
359           static_cast<int>(idle_sockets_.size());
360     }
361 
IsStalled(int max_sockets_per_group)362     bool IsStalled(int max_sockets_per_group) const {
363       return HasAvailableSocketSlot(max_sockets_per_group) &&
364           pending_requests_.size() > jobs_.size();
365     }
366 
TopPendingPriority()367     RequestPriority TopPendingPriority() const {
368       return pending_requests_.front()->priority();
369     }
370 
HasBackupJob()371     bool HasBackupJob() const { return !method_factory_.empty(); }
372 
CleanupBackupJob()373     void CleanupBackupJob() {
374       method_factory_.RevokeAll();
375     }
376 
377     // Set a timer to create a backup socket if it takes too long to create one.
378     void StartBackupSocketTimer(const std::string& group_name,
379                                 ClientSocketPoolBaseHelper* pool);
380 
381     // Searches |jobs_| to see if there's a preconnect ConnectJob, and if so,
382     // uses it.  Returns true on success.  Otherwise, returns false.
383     bool TryToUsePreconnectConnectJob();
384 
AddJob(ConnectJob * job)385     void AddJob(ConnectJob* job) { jobs_.insert(job); }
RemoveJob(ConnectJob * job)386     void RemoveJob(ConnectJob* job) { jobs_.erase(job); }
387     void RemoveAllJobs();
388 
IncrementActiveSocketCount()389     void IncrementActiveSocketCount() { active_socket_count_++; }
DecrementActiveSocketCount()390     void DecrementActiveSocketCount() { active_socket_count_--; }
391 
jobs()392     const std::set<ConnectJob*>& jobs() const { return jobs_; }
idle_sockets()393     const std::list<IdleSocket>& idle_sockets() const { return idle_sockets_; }
pending_requests()394     const RequestQueue& pending_requests() const { return pending_requests_; }
active_socket_count()395     int active_socket_count() const { return active_socket_count_; }
mutable_pending_requests()396     RequestQueue* mutable_pending_requests() { return &pending_requests_; }
mutable_idle_sockets()397     std::list<IdleSocket>* mutable_idle_sockets() { return &idle_sockets_; }
398 
399    private:
400     // Called when the backup socket timer fires.
401     void OnBackupSocketTimerFired(
402         std::string group_name,
403         ClientSocketPoolBaseHelper* pool);
404 
405     std::list<IdleSocket> idle_sockets_;
406     std::set<ConnectJob*> jobs_;
407     RequestQueue pending_requests_;
408     int active_socket_count_;  // number of active sockets used by clients
409     // A factory to pin the backup_job tasks.
410     ScopedRunnableMethodFactory<Group> method_factory_;
411   };
412 
413   typedef std::map<std::string, Group*> GroupMap;
414 
415   typedef std::set<ConnectJob*> ConnectJobSet;
416 
417   struct CallbackResultPair {
CallbackResultPairCallbackResultPair418     CallbackResultPair() : callback(NULL), result(OK) {}
CallbackResultPairCallbackResultPair419     CallbackResultPair(CompletionCallback* callback_in, int result_in)
420         : callback(callback_in), result(result_in) {}
421 
422     CompletionCallback* callback;
423     int result;
424   };
425 
426   typedef std::map<const ClientSocketHandle*, CallbackResultPair>
427       PendingCallbackMap;
428 
429   static void InsertRequestIntoQueue(const Request* r,
430                                      RequestQueue* pending_requests);
431   static const Request* RemoveRequestFromQueue(const RequestQueue::iterator& it,
432                                                Group* group);
433 
434   Group* GetOrCreateGroup(const std::string& group_name);
435   void RemoveGroup(const std::string& group_name);
436   void RemoveGroup(GroupMap::iterator it);
437 
438   // Called when the number of idle sockets changes.
439   void IncrementIdleCount();
440   void DecrementIdleCount();
441 
442   // Start cleanup timer for idle sockets.
443   void StartIdleSocketTimer();
444 
445   // Scans the group map for groups which have an available socket slot and
446   // at least one pending request. Returns true if any groups are stalled, and
447   // if so, fills |group| and |group_name| with data of the stalled group
448   // having highest priority.
449   bool FindTopStalledGroup(Group** group, std::string* group_name);
450 
451   // Called when timer_ fires.  This method scans the idle sockets removing
452   // sockets that timed out or can't be reused.
OnCleanupTimerFired()453   void OnCleanupTimerFired() {
454     CleanupIdleSockets(false);
455   }
456 
457   // Removes |job| from |connect_job_set_|.  Also updates |group| if non-NULL.
458   void RemoveConnectJob(ConnectJob* job, Group* group);
459 
460   // Tries to see if we can handle any more requests for |group|.
461   void OnAvailableSocketSlot(const std::string& group_name, Group* group);
462 
463   // Process a pending socket request for a group.
464   void ProcessPendingRequest(const std::string& group_name, Group* group);
465 
466   // Assigns |socket| to |handle| and updates |group|'s counters appropriately.
467   void HandOutSocket(ClientSocket* socket,
468                      bool reused,
469                      ClientSocketHandle* handle,
470                      base::TimeDelta time_idle,
471                      Group* group,
472                      const BoundNetLog& net_log);
473 
474   // Adds |socket| to the list of idle sockets for |group|.
475   void AddIdleSocket(ClientSocket* socket, Group* group);
476 
477   // Iterates through |group_map_|, canceling all ConnectJobs and deleting
478   // groups if they are no longer needed.
479   void CancelAllConnectJobs();
480 
481   // Iterates through |group_map_|, posting ERR_ABORTED callbacks for all
482   // requests, and then deleting groups if they are no longer needed.
483   void AbortAllRequests();
484 
485   // Returns true if we can't create any more sockets due to the total limit.
486   bool ReachedMaxSocketsLimit() const;
487 
488   // This is the internal implementation of RequestSocket().  It differs in that
489   // it does not handle logging into NetLog of the queueing status of
490   // |request|.
491   int RequestSocketInternal(const std::string& group_name,
492                             const Request* request);
493 
494   // Assigns an idle socket for the group to the request.
495   // Returns |true| if an idle socket is available, false otherwise.
496   bool AssignIdleSocketToGroup(const Request* request, Group* group);
497 
498   static void LogBoundConnectJobToRequest(
499       const NetLog::Source& connect_job_source, const Request* request);
500 
501   // Closes one idle socket.  Picks the first one encountered.
502   // TODO(willchan): Consider a better algorithm for doing this.  Perhaps we
503   // should keep an ordered list of idle sockets, and close them in order.
504   // Requires maintaining more state.  It's not clear if it's worth it since
505   // I'm not sure if we hit this situation often.
506   void CloseOneIdleSocket();
507 
508   // Same as CloseOneIdleSocket() except it won't close an idle socket in
509   // |group|.  If |group| is NULL, it is ignored.  Returns true if it closed a
510   // socket.
511   bool CloseOneIdleSocketExceptInGroup(const Group* group);
512 
513   // Checks if there are stalled socket groups that should be notified
514   // for possible wakeup.
515   void CheckForStalledSocketGroups();
516 
517   // Posts a task to call InvokeUserCallback() on the next iteration through the
518   // current message loop.  Inserts |callback| into |pending_callback_map_|,
519   // keyed by |handle|.
520   void InvokeUserCallbackLater(
521       ClientSocketHandle* handle, CompletionCallback* callback, int rv);
522 
523   // Invokes the user callback for |handle|.  By the time this task has run,
524   // it's possible that the request has been cancelled, so |handle| may not
525   // exist in |pending_callback_map_|.  We look up the callback and result code
526   // in |pending_callback_map_|.
527   void InvokeUserCallback(ClientSocketHandle* handle);
528 
529   GroupMap group_map_;
530 
531   // Map of the ClientSocketHandles for which we have a pending Task to invoke a
532   // callback.  This is necessary since, before we invoke said callback, it's
533   // possible that the request is cancelled.
534   PendingCallbackMap pending_callback_map_;
535 
536   // Timer used to periodically prune idle sockets that timed out or can't be
537   // reused.
538   base::RepeatingTimer<ClientSocketPoolBaseHelper> timer_;
539 
540   // The total number of idle sockets in the system.
541   int idle_socket_count_;
542 
543   // Number of connecting sockets across all groups.
544   int connecting_socket_count_;
545 
546   // Number of connected sockets we handed out across all groups.
547   int handed_out_socket_count_;
548 
549   // The maximum total number of sockets. See ReachedMaxSocketsLimit.
550   const int max_sockets_;
551 
552   // The maximum number of sockets kept per group.
553   const int max_sockets_per_group_;
554 
555   // Whether to use timer to cleanup idle sockets.
556   bool use_cleanup_timer_;
557 
558   // The time to wait until closing idle sockets.
559   const base::TimeDelta unused_idle_socket_timeout_;
560   const base::TimeDelta used_idle_socket_timeout_;
561 
562   const scoped_ptr<ConnectJobFactory> connect_job_factory_;
563 
564   // TODO(vandebo) Remove when backup jobs move to TransportClientSocketPool
565   bool connect_backup_jobs_enabled_;
566 
567   // A unique id for the pool.  It gets incremented every time we Flush() the
568   // pool.  This is so that when sockets get released back to the pool, we can
569   // make sure that they are discarded rather than reused.
570   int pool_generation_number_;
571 
572   ScopedRunnableMethodFactory<ClientSocketPoolBaseHelper> method_factory_;
573 
574   DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBaseHelper);
575 };
576 
577 }  // namespace internal
578 
579 // The maximum duration, in seconds, to keep used idle persistent sockets alive.
580 static const int kUsedIdleSocketTimeout = 300;  // 5 minutes
581 
582 template <typename SocketParams>
583 class ClientSocketPoolBase {
584  public:
585   class Request : public internal::ClientSocketPoolBaseHelper::Request {
586    public:
Request(ClientSocketHandle * handle,CompletionCallback * callback,RequestPriority priority,internal::ClientSocketPoolBaseHelper::Flags flags,bool ignore_limits,const scoped_refptr<SocketParams> & params,const BoundNetLog & net_log,bool valid_uid,int calling_uid)587     Request(ClientSocketHandle* handle,
588             CompletionCallback* callback,
589             RequestPriority priority,
590             internal::ClientSocketPoolBaseHelper::Flags flags,
591             bool ignore_limits,
592             const scoped_refptr<SocketParams>& params,
593             const BoundNetLog& net_log
594 #ifdef ANDROID
595             , bool valid_uid, int calling_uid
596 #endif
597            )
598         : internal::ClientSocketPoolBaseHelper::Request(
599               handle, callback, priority, ignore_limits,
600               flags, net_log
601 #ifdef ANDROID
602               , valid_uid, calling_uid
603 #endif
604               ),
605           params_(params) {}
606 
params()607     const scoped_refptr<SocketParams>& params() const { return params_; }
608 
609    private:
610     const scoped_refptr<SocketParams> params_;
611   };
612 
613   class ConnectJobFactory {
614    public:
ConnectJobFactory()615     ConnectJobFactory() {}
~ConnectJobFactory()616     virtual ~ConnectJobFactory() {}
617 
618     virtual ConnectJob* NewConnectJob(
619         const std::string& group_name,
620         const Request& request,
621         ConnectJob::Delegate* delegate) const = 0;
622 
623     virtual base::TimeDelta ConnectionTimeout() const = 0;
624 
625    private:
626     DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory);
627   };
628 
629   // |max_sockets| is the maximum number of sockets to be maintained by this
630   // ClientSocketPool.  |max_sockets_per_group| specifies the maximum number of
631   // sockets a "group" can have.  |unused_idle_socket_timeout| specifies how
632   // long to leave an unused idle socket open before closing it.
633   // |used_idle_socket_timeout| specifies how long to leave a previously used
634   // idle socket open before closing it.
ClientSocketPoolBase(int max_sockets,int max_sockets_per_group,ClientSocketPoolHistograms * histograms,base::TimeDelta unused_idle_socket_timeout,base::TimeDelta used_idle_socket_timeout,ConnectJobFactory * connect_job_factory)635   ClientSocketPoolBase(
636       int max_sockets,
637       int max_sockets_per_group,
638       ClientSocketPoolHistograms* histograms,
639       base::TimeDelta unused_idle_socket_timeout,
640       base::TimeDelta used_idle_socket_timeout,
641       ConnectJobFactory* connect_job_factory)
642       : histograms_(histograms),
643         helper_(max_sockets, max_sockets_per_group,
644                 unused_idle_socket_timeout, used_idle_socket_timeout,
645                 new ConnectJobFactoryAdaptor(connect_job_factory)) {}
646 
~ClientSocketPoolBase()647   virtual ~ClientSocketPoolBase() {}
648 
649   // These member functions simply forward to ClientSocketPoolBaseHelper.
650 
651   // RequestSocket bundles up the parameters into a Request and then forwards to
652   // ClientSocketPoolBaseHelper::RequestSocket().
RequestSocket(const std::string & group_name,const scoped_refptr<SocketParams> & params,RequestPriority priority,ClientSocketHandle * handle,CompletionCallback * callback,const BoundNetLog & net_log)653   int RequestSocket(const std::string& group_name,
654                     const scoped_refptr<SocketParams>& params,
655                     RequestPriority priority,
656                     ClientSocketHandle* handle,
657                     CompletionCallback* callback,
658                     const BoundNetLog& net_log) {
659 #ifdef ANDROID
660     uid_t calling_uid = 0;
661     bool valid_uid = params->getUID(&calling_uid);
662 #endif
663     Request* request =
664         new Request(handle, callback, priority,
665                     internal::ClientSocketPoolBaseHelper::NORMAL,
666                     params->ignore_limits(),
667                     params, net_log
668 #ifdef ANDROID
669                     , valid_uid, calling_uid
670 #endif
671                     );
672     return helper_.RequestSocket(group_name, request);
673   }
674 
675   // RequestSockets bundles up the parameters into a Request and then forwards
676   // to ClientSocketPoolBaseHelper::RequestSockets().  Note that it assigns the
677   // priority to LOWEST and specifies the NO_IDLE_SOCKETS flag.
RequestSockets(const std::string & group_name,const scoped_refptr<SocketParams> & params,int num_sockets,const BoundNetLog & net_log)678   void RequestSockets(const std::string& group_name,
679                       const scoped_refptr<SocketParams>& params,
680                       int num_sockets,
681                       const BoundNetLog& net_log) {
682 #ifdef ANDROID
683     uid_t calling_uid = 0;
684     bool valid_uid = params->getUID(&calling_uid);
685 #endif
686     const Request request(NULL /* no handle */,
687                           NULL /* no callback */,
688                           LOWEST,
689                           internal::ClientSocketPoolBaseHelper::NO_IDLE_SOCKETS,
690                           params->ignore_limits(),
691                           params,
692                           net_log
693 #ifdef ANDROID
694                           , valid_uid, calling_uid
695 #endif
696                           );
697     helper_.RequestSockets(group_name, request, num_sockets);
698   }
699 
CancelRequest(const std::string & group_name,ClientSocketHandle * handle)700   void CancelRequest(const std::string& group_name,
701                      ClientSocketHandle* handle) {
702     return helper_.CancelRequest(group_name, handle);
703   }
704 
ReleaseSocket(const std::string & group_name,ClientSocket * socket,int id)705   void ReleaseSocket(const std::string& group_name, ClientSocket* socket,
706                      int id) {
707     return helper_.ReleaseSocket(group_name, socket, id);
708   }
709 
CloseIdleSockets()710   void CloseIdleSockets() { return helper_.CloseIdleSockets(); }
711 
idle_socket_count()712   int idle_socket_count() const { return helper_.idle_socket_count(); }
713 
IdleSocketCountInGroup(const std::string & group_name)714   int IdleSocketCountInGroup(const std::string& group_name) const {
715     return helper_.IdleSocketCountInGroup(group_name);
716   }
717 
GetLoadState(const std::string & group_name,const ClientSocketHandle * handle)718   LoadState GetLoadState(const std::string& group_name,
719                          const ClientSocketHandle* handle) const {
720     return helper_.GetLoadState(group_name, handle);
721   }
722 
OnConnectJobComplete(int result,ConnectJob * job)723   virtual void OnConnectJobComplete(int result, ConnectJob* job) {
724     return helper_.OnConnectJobComplete(result, job);
725   }
726 
NumConnectJobsInGroup(const std::string & group_name)727   int NumConnectJobsInGroup(const std::string& group_name) const {
728     return helper_.NumConnectJobsInGroup(group_name);
729   }
730 
NumActiveSocketsInGroup(const std::string & group_name)731   int NumActiveSocketsInGroup(const std::string& group_name) const {
732     return helper_.NumActiveSocketsInGroup(group_name);
733   }
734 
HasGroup(const std::string & group_name)735   bool HasGroup(const std::string& group_name) const {
736     return helper_.HasGroup(group_name);
737   }
738 
CleanupIdleSockets(bool force)739   void CleanupIdleSockets(bool force) {
740     return helper_.CleanupIdleSockets(force);
741   }
742 
GetInfoAsValue(const std::string & name,const std::string & type)743   DictionaryValue* GetInfoAsValue(const std::string& name,
744                                   const std::string& type) const {
745     return helper_.GetInfoAsValue(name, type);
746   }
747 
ConnectionTimeout()748   base::TimeDelta ConnectionTimeout() const {
749     return helper_.ConnectionTimeout();
750   }
751 
histograms()752   ClientSocketPoolHistograms* histograms() const {
753     return histograms_;
754   }
755 
EnableConnectBackupJobs()756   void EnableConnectBackupJobs() { helper_.EnableConnectBackupJobs(); }
757 
Flush()758   void Flush() { helper_.Flush(); }
759 
760  private:
761   // This adaptor class exists to bridge the
762   // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and
763   // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the
764   // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to
765   // static_cast themselves.
766   class ConnectJobFactoryAdaptor
767       : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory {
768    public:
769     typedef typename ClientSocketPoolBase<SocketParams>::ConnectJobFactory
770         ConnectJobFactory;
771 
ConnectJobFactoryAdaptor(ConnectJobFactory * connect_job_factory)772     explicit ConnectJobFactoryAdaptor(ConnectJobFactory* connect_job_factory)
773         : connect_job_factory_(connect_job_factory) {}
~ConnectJobFactoryAdaptor()774     virtual ~ConnectJobFactoryAdaptor() {}
775 
NewConnectJob(const std::string & group_name,const internal::ClientSocketPoolBaseHelper::Request & request,ConnectJob::Delegate * delegate)776     virtual ConnectJob* NewConnectJob(
777         const std::string& group_name,
778         const internal::ClientSocketPoolBaseHelper::Request& request,
779         ConnectJob::Delegate* delegate) const {
780       const Request* casted_request = static_cast<const Request*>(&request);
781       return connect_job_factory_->NewConnectJob(
782           group_name, *casted_request, delegate);
783     }
784 
ConnectionTimeout()785     virtual base::TimeDelta ConnectionTimeout() const {
786       return connect_job_factory_->ConnectionTimeout();
787     }
788 
789     const scoped_ptr<ConnectJobFactory> connect_job_factory_;
790   };
791 
792   // Histograms for the pool
793   ClientSocketPoolHistograms* const histograms_;
794   internal::ClientSocketPoolBaseHelper helper_;
795 
796   DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase);
797 };
798 
799 }  // namespace net
800 
801 #endif  // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_
802