Home | History | Annotate | Download | only in socket
      1 // Copyright (c) 2012 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 
     25 #include <cstddef>
     26 #include <deque>
     27 #include <list>
     28 #include <map>
     29 #include <set>
     30 #include <string>
     31 #include <vector>
     32 
     33 #include "base/basictypes.h"
     34 #include "base/memory/ref_counted.h"
     35 #include "base/memory/scoped_ptr.h"
     36 #include "base/memory/weak_ptr.h"
     37 #include "base/time/time.h"
     38 #include "base/timer/timer.h"
     39 #include "net/base/address_list.h"
     40 #include "net/base/completion_callback.h"
     41 #include "net/base/load_states.h"
     42 #include "net/base/load_timing_info.h"
     43 #include "net/base/net_errors.h"
     44 #include "net/base/net_export.h"
     45 #include "net/base/net_log.h"
     46 #include "net/base/network_change_notifier.h"
     47 #include "net/base/priority_queue.h"
     48 #include "net/base/request_priority.h"
     49 #include "net/socket/client_socket_handle.h"
     50 #include "net/socket/client_socket_pool.h"
     51 #include "net/socket/stream_socket.h"
     52 
     53 namespace net {
     54 
     55 class ClientSocketHandle;
     56 
     57 // ConnectJob provides an abstract interface for "connecting" a socket.
     58 // The connection may involve host resolution, tcp connection, ssl connection,
     59 // etc.
     60 class NET_EXPORT_PRIVATE ConnectJob {
     61  public:
     62   class NET_EXPORT_PRIVATE Delegate {
     63    public:
     64     Delegate() {}
     65     virtual ~Delegate() {}
     66 
     67     // Alerts the delegate that the connection completed. |job| must
     68     // be destroyed by the delegate. A scoped_ptr<> isn't used because
     69     // the caller of this function doesn't own |job|.
     70     virtual void OnConnectJobComplete(int result,
     71                                       ConnectJob* job) = 0;
     72 
     73    private:
     74     DISALLOW_COPY_AND_ASSIGN(Delegate);
     75   };
     76 
     77   // A |timeout_duration| of 0 corresponds to no timeout.
     78   ConnectJob(const std::string& group_name,
     79              base::TimeDelta timeout_duration,
     80              RequestPriority priority,
     81              Delegate* delegate,
     82              const BoundNetLog& net_log);
     83   virtual ~ConnectJob();
     84 
     85   // Accessors
     86   const std::string& group_name() const { return group_name_; }
     87   const BoundNetLog& net_log() { return net_log_; }
     88 
     89   // Releases ownership of the underlying socket to the caller.
     90   // Returns the released socket, or NULL if there was a connection
     91   // error.
     92   scoped_ptr<StreamSocket> PassSocket();
     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   virtual LoadState GetLoadState() const = 0;
    103 
    104   // If Connect returns an error (or OnConnectJobComplete reports an error
    105   // result) this method will be called, allowing the pool to add
    106   // additional error state to the ClientSocketHandle (post late-binding).
    107   virtual void GetAdditionalErrorState(ClientSocketHandle* handle) {}
    108 
    109   const LoadTimingInfo::ConnectTiming& connect_timing() const {
    110     return connect_timing_;
    111   }
    112 
    113   const BoundNetLog& net_log() const { return net_log_; }
    114 
    115  protected:
    116   RequestPriority priority() const { return priority_; }
    117   void SetSocket(scoped_ptr<StreamSocket> socket);
    118   StreamSocket* socket() { return socket_.get(); }
    119   void NotifyDelegateOfCompletion(int rv);
    120   void ResetTimer(base::TimeDelta remainingTime);
    121 
    122   // Connection establishment timing information.
    123   LoadTimingInfo::ConnectTiming connect_timing_;
    124 
    125  private:
    126   virtual int ConnectInternal() = 0;
    127 
    128   void LogConnectStart();
    129   void LogConnectCompletion(int net_error);
    130 
    131   // Alerts the delegate that the ConnectJob has timed out.
    132   void OnTimeout();
    133 
    134   const std::string group_name_;
    135   const base::TimeDelta timeout_duration_;
    136   // TODO(akalin): Support reprioritization.
    137   const RequestPriority priority_;
    138   // Timer to abort jobs that take too long.
    139   base::OneShotTimer<ConnectJob> timer_;
    140   Delegate* delegate_;
    141   scoped_ptr<StreamSocket> socket_;
    142   BoundNetLog net_log_;
    143   // A ConnectJob is idle until Connect() has been called.
    144   bool idle_;
    145 
    146   DISALLOW_COPY_AND_ASSIGN(ConnectJob);
    147 };
    148 
    149 namespace internal {
    150 
    151 // ClientSocketPoolBaseHelper is an internal class that implements almost all
    152 // the functionality from ClientSocketPoolBase without using templates.
    153 // ClientSocketPoolBase adds templated definitions built on top of
    154 // ClientSocketPoolBaseHelper.  This class is not for external use, please use
    155 // ClientSocketPoolBase instead.
    156 class NET_EXPORT_PRIVATE ClientSocketPoolBaseHelper
    157     : public ConnectJob::Delegate,
    158       public NetworkChangeNotifier::IPAddressObserver {
    159  public:
    160   typedef uint32 Flags;
    161 
    162   // Used to specify specific behavior for the ClientSocketPool.
    163   enum Flag {
    164     NORMAL = 0,  // Normal behavior.
    165     NO_IDLE_SOCKETS = 0x1,  // Do not return an idle socket. Create a new one.
    166   };
    167 
    168   class NET_EXPORT_PRIVATE Request {
    169    public:
    170     Request(ClientSocketHandle* handle,
    171             const CompletionCallback& callback,
    172             RequestPriority priority,
    173             bool ignore_limits,
    174             Flags flags,
    175             const BoundNetLog& net_log);
    176 
    177     virtual ~Request();
    178 
    179     ClientSocketHandle* handle() const { return handle_; }
    180     const CompletionCallback& callback() const { return callback_; }
    181     RequestPriority priority() const { return priority_; }
    182     bool ignore_limits() const { return ignore_limits_; }
    183     Flags flags() const { return flags_; }
    184     const BoundNetLog& net_log() const { return net_log_; }
    185 
    186    private:
    187     ClientSocketHandle* const handle_;
    188     const CompletionCallback callback_;
    189     // TODO(akalin): Support reprioritization.
    190     const RequestPriority priority_;
    191     const bool ignore_limits_;
    192     const Flags flags_;
    193     const BoundNetLog net_log_;
    194 
    195     DISALLOW_COPY_AND_ASSIGN(Request);
    196   };
    197 
    198   class ConnectJobFactory {
    199    public:
    200     ConnectJobFactory() {}
    201     virtual ~ConnectJobFactory() {}
    202 
    203     virtual scoped_ptr<ConnectJob> NewConnectJob(
    204         const std::string& group_name,
    205         const Request& request,
    206         ConnectJob::Delegate* delegate) const = 0;
    207 
    208     virtual base::TimeDelta ConnectionTimeout() const = 0;
    209 
    210    private:
    211     DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory);
    212   };
    213 
    214   ClientSocketPoolBaseHelper(
    215       HigherLayeredPool* pool,
    216       int max_sockets,
    217       int max_sockets_per_group,
    218       base::TimeDelta unused_idle_socket_timeout,
    219       base::TimeDelta used_idle_socket_timeout,
    220       ConnectJobFactory* connect_job_factory);
    221 
    222   virtual ~ClientSocketPoolBaseHelper();
    223 
    224   // Adds a lower layered pool to |this|, and adds |this| as a higher layered
    225   // pool on top of |lower_pool|.
    226   void AddLowerLayeredPool(LowerLayeredPool* lower_pool);
    227 
    228   // See LowerLayeredPool::IsStalled for documentation on this function.
    229   bool IsStalled() const;
    230 
    231   // See LowerLayeredPool for documentation on these functions. It is expected
    232   // in the destructor that no higher layer pools remain.
    233   void AddHigherLayeredPool(HigherLayeredPool* higher_pool);
    234   void RemoveHigherLayeredPool(HigherLayeredPool* higher_pool);
    235 
    236   // See ClientSocketPool::RequestSocket for documentation on this function.
    237   int RequestSocket(const std::string& group_name,
    238                     scoped_ptr<const Request> request);
    239 
    240   // See ClientSocketPool::RequestSocket for documentation on this function.
    241   void RequestSockets(const std::string& group_name,
    242                       const Request& request,
    243                       int num_sockets);
    244 
    245   // See ClientSocketPool::CancelRequest for documentation on this function.
    246   void CancelRequest(const std::string& group_name,
    247                      ClientSocketHandle* handle);
    248 
    249   // See ClientSocketPool::ReleaseSocket for documentation on this function.
    250   void ReleaseSocket(const std::string& group_name,
    251                      scoped_ptr<StreamSocket> socket,
    252                      int id);
    253 
    254   // See ClientSocketPool::FlushWithError for documentation on this function.
    255   void FlushWithError(int error);
    256 
    257   // See ClientSocketPool::CloseIdleSockets for documentation on this function.
    258   void CloseIdleSockets();
    259 
    260   // See ClientSocketPool::IdleSocketCount() for documentation on this function.
    261   int idle_socket_count() const {
    262     return idle_socket_count_;
    263   }
    264 
    265   // See ClientSocketPool::IdleSocketCountInGroup() for documentation on this
    266   // function.
    267   int IdleSocketCountInGroup(const std::string& group_name) const;
    268 
    269   // See ClientSocketPool::GetLoadState() for documentation on this function.
    270   LoadState GetLoadState(const std::string& group_name,
    271                          const ClientSocketHandle* handle) const;
    272 
    273   base::TimeDelta ConnectRetryInterval() const {
    274     // TODO(mbelshe): Make this tuned dynamically based on measured RTT.
    275     //                For now, just use the max retry interval.
    276     return base::TimeDelta::FromMilliseconds(
    277         ClientSocketPool::kMaxConnectRetryIntervalMs);
    278   }
    279 
    280   int NumUnassignedConnectJobsInGroup(const std::string& group_name) const {
    281     return group_map_.find(group_name)->second->unassigned_job_count();
    282   }
    283 
    284   int NumConnectJobsInGroup(const std::string& group_name) const {
    285     return group_map_.find(group_name)->second->jobs().size();
    286   }
    287 
    288   int NumActiveSocketsInGroup(const std::string& group_name) const {
    289     return group_map_.find(group_name)->second->active_socket_count();
    290   }
    291 
    292   bool HasGroup(const std::string& group_name) const;
    293 
    294   // Called to enable/disable cleaning up idle sockets. When enabled,
    295   // idle sockets that have been around for longer than a period defined
    296   // by kCleanupInterval are cleaned up using a timer. Otherwise they are
    297   // closed next time client makes a request. This may reduce network
    298   // activity and power consumption.
    299   static bool cleanup_timer_enabled();
    300   static bool set_cleanup_timer_enabled(bool enabled);
    301 
    302   // Closes all idle sockets if |force| is true.  Else, only closes idle
    303   // sockets that timed out or can't be reused.  Made public for testing.
    304   void CleanupIdleSockets(bool force);
    305 
    306   // Closes one idle socket.  Picks the first one encountered.
    307   // TODO(willchan): Consider a better algorithm for doing this.  Perhaps we
    308   // should keep an ordered list of idle sockets, and close them in order.
    309   // Requires maintaining more state.  It's not clear if it's worth it since
    310   // I'm not sure if we hit this situation often.
    311   bool CloseOneIdleSocket();
    312 
    313   // Checks higher layered pools to see if they can close an idle connection.
    314   bool CloseOneIdleConnectionInHigherLayeredPool();
    315 
    316   // See ClientSocketPool::GetInfoAsValue for documentation on this function.
    317   base::DictionaryValue* GetInfoAsValue(const std::string& name,
    318                                         const std::string& type) const;
    319 
    320   base::TimeDelta ConnectionTimeout() const {
    321     return connect_job_factory_->ConnectionTimeout();
    322   }
    323 
    324   static bool connect_backup_jobs_enabled();
    325   static bool set_connect_backup_jobs_enabled(bool enabled);
    326 
    327   void EnableConnectBackupJobs();
    328 
    329   // ConnectJob::Delegate methods:
    330   virtual void OnConnectJobComplete(int result, ConnectJob* job) OVERRIDE;
    331 
    332   // NetworkChangeNotifier::IPAddressObserver methods:
    333   virtual void OnIPAddressChanged() OVERRIDE;
    334 
    335  private:
    336   friend class base::RefCounted<ClientSocketPoolBaseHelper>;
    337 
    338   // Entry for a persistent socket which became idle at time |start_time|.
    339   struct IdleSocket {
    340     IdleSocket() : socket(NULL) {}
    341 
    342     // An idle socket can't be used if it is disconnected or has been used
    343     // before and has received data unexpectedly (hence no longer idle).  The
    344     // unread data would be mistaken for the beginning of the next response if
    345     // we were to use the socket for a new request.
    346     //
    347     // Note that a socket that has never been used before (like a preconnected
    348     // socket) may be used even with unread data.  This may be, e.g., a SPDY
    349     // SETTINGS frame.
    350     bool IsUsable() const;
    351 
    352     // An idle socket should be removed if it can't be reused, or has been idle
    353     // for too long. |now| is the current time value (TimeTicks::Now()).
    354     // |timeout| is the length of time to wait before timing out an idle socket.
    355     bool ShouldCleanup(base::TimeTicks now, base::TimeDelta timeout) const;
    356 
    357     StreamSocket* socket;
    358     base::TimeTicks start_time;
    359   };
    360 
    361   typedef PriorityQueue<const Request*> RequestQueue;
    362   typedef std::map<const ClientSocketHandle*, const Request*> RequestMap;
    363 
    364   // A Group is allocated per group_name when there are idle sockets or pending
    365   // requests.  Otherwise, the Group object is removed from the map.
    366   // |active_socket_count| tracks the number of sockets held by clients.
    367   class Group {
    368    public:
    369     Group();
    370     ~Group();
    371 
    372     bool IsEmpty() const {
    373       return active_socket_count_ == 0 && idle_sockets_.empty() &&
    374           jobs_.empty() && pending_requests_.empty();
    375     }
    376 
    377     bool HasAvailableSocketSlot(int max_sockets_per_group) const {
    378       return NumActiveSocketSlots() < max_sockets_per_group;
    379     }
    380 
    381     int NumActiveSocketSlots() const {
    382       return active_socket_count_ + static_cast<int>(jobs_.size()) +
    383           static_cast<int>(idle_sockets_.size());
    384     }
    385 
    386     bool IsStalledOnPoolMaxSockets(int max_sockets_per_group) const {
    387       return HasAvailableSocketSlot(max_sockets_per_group) &&
    388           pending_requests_.size() > jobs_.size();
    389     }
    390 
    391     // Returns the priority of the top of the pending request queue
    392     // (which may be less than the maximum priority over the entire
    393     // queue, due to how we prioritize requests with |ignore_limits|
    394     // set over others).
    395     RequestPriority TopPendingPriority() const {
    396       // NOTE: FirstMax().value()->priority() is not the same as
    397       // FirstMax().priority()!
    398       return pending_requests_.FirstMax().value()->priority();
    399     }
    400 
    401     // Set a timer to create a backup job if it takes too long to
    402     // create one and if a timer isn't already running.
    403     void StartBackupJobTimer(const std::string& group_name,
    404                              ClientSocketPoolBaseHelper* pool);
    405 
    406     bool BackupJobTimerIsRunning() const;
    407 
    408     // If there's a ConnectJob that's never been assigned to Request,
    409     // decrements |unassigned_job_count_| and returns true.
    410     // Otherwise, returns false.
    411     bool TryToUseUnassignedConnectJob();
    412 
    413     void AddJob(scoped_ptr<ConnectJob> job, bool is_preconnect);
    414     // Remove |job| from this group, which must already own |job|.
    415     void RemoveJob(ConnectJob* job);
    416     void RemoveAllJobs();
    417 
    418     bool has_pending_requests() const {
    419       return !pending_requests_.empty();
    420     }
    421 
    422     size_t pending_request_count() const {
    423       return pending_requests_.size();
    424     }
    425 
    426     // Gets (but does not remove) the next pending request. Returns
    427     // NULL if there are no pending requests.
    428     const Request* GetNextPendingRequest() const;
    429 
    430     // Returns true if there is a connect job for |handle|.
    431     bool HasConnectJobForHandle(const ClientSocketHandle* handle) const;
    432 
    433     // Inserts the request into the queue based on priority
    434     // order. Older requests are prioritized over requests of equal
    435     // priority.
    436     void InsertPendingRequest(scoped_ptr<const Request> request);
    437 
    438     // Gets and removes the next pending request. Returns NULL if
    439     // there are no pending requests.
    440     scoped_ptr<const Request> PopNextPendingRequest();
    441 
    442     // Finds the pending request for |handle| and removes it. Returns
    443     // the removed pending request, or NULL if there was none.
    444     scoped_ptr<const Request> FindAndRemovePendingRequest(
    445         ClientSocketHandle* handle);
    446 
    447     void IncrementActiveSocketCount() { active_socket_count_++; }
    448     void DecrementActiveSocketCount() { active_socket_count_--; }
    449 
    450     int unassigned_job_count() const { return unassigned_job_count_; }
    451     const std::set<ConnectJob*>& jobs() const { return jobs_; }
    452     const std::list<IdleSocket>& idle_sockets() const { return idle_sockets_; }
    453     int active_socket_count() const { return active_socket_count_; }
    454     std::list<IdleSocket>* mutable_idle_sockets() { return &idle_sockets_; }
    455 
    456    private:
    457     // Returns the iterator's pending request after removing it from
    458     // the queue.
    459     scoped_ptr<const Request> RemovePendingRequest(
    460         const RequestQueue::Pointer& pointer);
    461 
    462     // Called when the backup socket timer fires.
    463     void OnBackupJobTimerFired(
    464         std::string group_name,
    465         ClientSocketPoolBaseHelper* pool);
    466 
    467     // Checks that |unassigned_job_count_| does not execeed the number of
    468     // ConnectJobs.
    469     void SanityCheck();
    470 
    471     // Total number of ConnectJobs that have never been assigned to a Request.
    472     // Since jobs use late binding to requests, which ConnectJobs have or have
    473     // not been assigned to a request are not tracked.  This is incremented on
    474     // preconnect and decremented when a preconnect is assigned, or when there
    475     // are fewer than |unassigned_job_count_| ConnectJobs.  Not incremented
    476     // when a request is cancelled.
    477     size_t unassigned_job_count_;
    478 
    479     std::list<IdleSocket> idle_sockets_;
    480     std::set<ConnectJob*> jobs_;
    481     RequestQueue pending_requests_;
    482     int active_socket_count_;  // number of active sockets used by clients
    483     // A timer for when to start the backup job.
    484     base::OneShotTimer<Group> backup_job_timer_;
    485   };
    486 
    487   typedef std::map<std::string, Group*> GroupMap;
    488 
    489   typedef std::set<ConnectJob*> ConnectJobSet;
    490 
    491   struct CallbackResultPair {
    492     CallbackResultPair();
    493     CallbackResultPair(const CompletionCallback& callback_in, int result_in);
    494     ~CallbackResultPair();
    495 
    496     CompletionCallback callback;
    497     int result;
    498   };
    499 
    500   typedef std::map<const ClientSocketHandle*, CallbackResultPair>
    501       PendingCallbackMap;
    502 
    503   Group* GetOrCreateGroup(const std::string& group_name);
    504   void RemoveGroup(const std::string& group_name);
    505   void RemoveGroup(GroupMap::iterator it);
    506 
    507   // Called when the number of idle sockets changes.
    508   void IncrementIdleCount();
    509   void DecrementIdleCount();
    510 
    511   // Start cleanup timer for idle sockets.
    512   void StartIdleSocketTimer();
    513 
    514   // Scans the group map for groups which have an available socket slot and
    515   // at least one pending request. Returns true if any groups are stalled, and
    516   // if so (and if both |group| and |group_name| are not NULL), fills |group|
    517   // and |group_name| with data of the stalled group having highest priority.
    518   bool FindTopStalledGroup(Group** group, std::string* group_name) const;
    519 
    520   // Called when timer_ fires.  This method scans the idle sockets removing
    521   // sockets that timed out or can't be reused.
    522   void OnCleanupTimerFired() {
    523     CleanupIdleSockets(false);
    524   }
    525 
    526   // Removes |job| from |group|, which must already own |job|.
    527   void RemoveConnectJob(ConnectJob* job, Group* group);
    528 
    529   // Tries to see if we can handle any more requests for |group|.
    530   void OnAvailableSocketSlot(const std::string& group_name, Group* group);
    531 
    532   // Process a pending socket request for a group.
    533   void ProcessPendingRequest(const std::string& group_name, Group* group);
    534 
    535   // Assigns |socket| to |handle| and updates |group|'s counters appropriately.
    536   void HandOutSocket(scoped_ptr<StreamSocket> socket,
    537                      ClientSocketHandle::SocketReuseType reuse_type,
    538                      const LoadTimingInfo::ConnectTiming& connect_timing,
    539                      ClientSocketHandle* handle,
    540                      base::TimeDelta time_idle,
    541                      Group* group,
    542                      const BoundNetLog& net_log);
    543 
    544   // Adds |socket| to the list of idle sockets for |group|.
    545   void AddIdleSocket(scoped_ptr<StreamSocket> socket, Group* group);
    546 
    547   // Iterates through |group_map_|, canceling all ConnectJobs and deleting
    548   // groups if they are no longer needed.
    549   void CancelAllConnectJobs();
    550 
    551   // Iterates through |group_map_|, posting |error| callbacks for all
    552   // requests, and then deleting groups if they are no longer needed.
    553   void CancelAllRequestsWithError(int error);
    554 
    555   // Returns true if we can't create any more sockets due to the total limit.
    556   bool ReachedMaxSocketsLimit() const;
    557 
    558   // This is the internal implementation of RequestSocket().  It differs in that
    559   // it does not handle logging into NetLog of the queueing status of
    560   // |request|.
    561   int RequestSocketInternal(const std::string& group_name,
    562                             const Request& request);
    563 
    564   // Assigns an idle socket for the group to the request.
    565   // Returns |true| if an idle socket is available, false otherwise.
    566   bool AssignIdleSocketToRequest(const Request& request, Group* group);
    567 
    568   static void LogBoundConnectJobToRequest(
    569       const NetLog::Source& connect_job_source, const Request& request);
    570 
    571   // Same as CloseOneIdleSocket() except it won't close an idle socket in
    572   // |group|.  If |group| is NULL, it is ignored.  Returns true if it closed a
    573   // socket.
    574   bool CloseOneIdleSocketExceptInGroup(const Group* group);
    575 
    576   // Checks if there are stalled socket groups that should be notified
    577   // for possible wakeup.
    578   void CheckForStalledSocketGroups();
    579 
    580   // Posts a task to call InvokeUserCallback() on the next iteration through the
    581   // current message loop.  Inserts |callback| into |pending_callback_map_|,
    582   // keyed by |handle|.
    583   void InvokeUserCallbackLater(
    584       ClientSocketHandle* handle, const CompletionCallback& callback, int rv);
    585 
    586   // Invokes the user callback for |handle|.  By the time this task has run,
    587   // it's possible that the request has been cancelled, so |handle| may not
    588   // exist in |pending_callback_map_|.  We look up the callback and result code
    589   // in |pending_callback_map_|.
    590   void InvokeUserCallback(ClientSocketHandle* handle);
    591 
    592   // Tries to close idle sockets in a higher level socket pool as long as this
    593   // this pool is stalled.
    594   void TryToCloseSocketsInLayeredPools();
    595 
    596   GroupMap group_map_;
    597 
    598   // Map of the ClientSocketHandles for which we have a pending Task to invoke a
    599   // callback.  This is necessary since, before we invoke said callback, it's
    600   // possible that the request is cancelled.
    601   PendingCallbackMap pending_callback_map_;
    602 
    603   // Timer used to periodically prune idle sockets that timed out or can't be
    604   // reused.
    605   base::RepeatingTimer<ClientSocketPoolBaseHelper> timer_;
    606 
    607   // The total number of idle sockets in the system.
    608   int idle_socket_count_;
    609 
    610   // Number of connecting sockets across all groups.
    611   int connecting_socket_count_;
    612 
    613   // Number of connected sockets we handed out across all groups.
    614   int handed_out_socket_count_;
    615 
    616   // The maximum total number of sockets. See ReachedMaxSocketsLimit.
    617   const int max_sockets_;
    618 
    619   // The maximum number of sockets kept per group.
    620   const int max_sockets_per_group_;
    621 
    622   // Whether to use timer to cleanup idle sockets.
    623   bool use_cleanup_timer_;
    624 
    625   // The time to wait until closing idle sockets.
    626   const base::TimeDelta unused_idle_socket_timeout_;
    627   const base::TimeDelta used_idle_socket_timeout_;
    628 
    629   const scoped_ptr<ConnectJobFactory> connect_job_factory_;
    630 
    631   // TODO(vandebo) Remove when backup jobs move to TransportClientSocketPool
    632   bool connect_backup_jobs_enabled_;
    633 
    634   // A unique id for the pool.  It gets incremented every time we
    635   // FlushWithError() the pool.  This is so that when sockets get released back
    636   // to the pool, we can make sure that they are discarded rather than reused.
    637   int pool_generation_number_;
    638 
    639   // Used to add |this| as a higher layer pool on top of lower layer pools.  May
    640   // be NULL if no lower layer pools will be added.
    641   HigherLayeredPool* pool_;
    642 
    643   // Pools that create connections through |this|.  |this| will try to close
    644   // their idle sockets when it stalls.  Must be empty on destruction.
    645   std::set<HigherLayeredPool*> higher_pools_;
    646 
    647   // Pools that this goes through.  Typically there's only one, but not always.
    648   // |this| will check if they're stalled when it has a new idle socket.  |this|
    649   // will remove itself from all lower layered pools on destruction.
    650   std::set<LowerLayeredPool*> lower_pools_;
    651 
    652   base::WeakPtrFactory<ClientSocketPoolBaseHelper> weak_factory_;
    653 
    654   DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBaseHelper);
    655 };
    656 
    657 }  // namespace internal
    658 
    659 template <typename SocketParams>
    660 class ClientSocketPoolBase {
    661  public:
    662   class Request : public internal::ClientSocketPoolBaseHelper::Request {
    663    public:
    664     Request(ClientSocketHandle* handle,
    665             const CompletionCallback& callback,
    666             RequestPriority priority,
    667             internal::ClientSocketPoolBaseHelper::Flags flags,
    668             bool ignore_limits,
    669             const scoped_refptr<SocketParams>& params,
    670             const BoundNetLog& net_log)
    671         : internal::ClientSocketPoolBaseHelper::Request(
    672               handle, callback, priority, ignore_limits, flags, net_log),
    673           params_(params) {}
    674 
    675     const scoped_refptr<SocketParams>& params() const { return params_; }
    676 
    677    private:
    678     const scoped_refptr<SocketParams> params_;
    679   };
    680 
    681   class ConnectJobFactory {
    682    public:
    683     ConnectJobFactory() {}
    684     virtual ~ConnectJobFactory() {}
    685 
    686     virtual scoped_ptr<ConnectJob> NewConnectJob(
    687         const std::string& group_name,
    688         const Request& request,
    689         ConnectJob::Delegate* delegate) const = 0;
    690 
    691     virtual base::TimeDelta ConnectionTimeout() const = 0;
    692 
    693    private:
    694     DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory);
    695   };
    696 
    697   // |max_sockets| is the maximum number of sockets to be maintained by this
    698   // ClientSocketPool.  |max_sockets_per_group| specifies the maximum number of
    699   // sockets a "group" can have.  |unused_idle_socket_timeout| specifies how
    700   // long to leave an unused idle socket open before closing it.
    701   // |used_idle_socket_timeout| specifies how long to leave a previously used
    702   // idle socket open before closing it.
    703   ClientSocketPoolBase(
    704       HigherLayeredPool* self,
    705       int max_sockets,
    706       int max_sockets_per_group,
    707       ClientSocketPoolHistograms* histograms,
    708       base::TimeDelta unused_idle_socket_timeout,
    709       base::TimeDelta used_idle_socket_timeout,
    710       ConnectJobFactory* connect_job_factory)
    711       : histograms_(histograms),
    712         helper_(self, max_sockets, max_sockets_per_group,
    713                 unused_idle_socket_timeout, used_idle_socket_timeout,
    714                 new ConnectJobFactoryAdaptor(connect_job_factory)) {}
    715 
    716   virtual ~ClientSocketPoolBase() {}
    717 
    718   // These member functions simply forward to ClientSocketPoolBaseHelper.
    719   void AddLowerLayeredPool(LowerLayeredPool* lower_pool) {
    720     helper_.AddLowerLayeredPool(lower_pool);
    721   }
    722 
    723   void AddHigherLayeredPool(HigherLayeredPool* higher_pool) {
    724     helper_.AddHigherLayeredPool(higher_pool);
    725   }
    726 
    727   void RemoveHigherLayeredPool(HigherLayeredPool* higher_pool) {
    728     helper_.RemoveHigherLayeredPool(higher_pool);
    729   }
    730 
    731   // RequestSocket bundles up the parameters into a Request and then forwards to
    732   // ClientSocketPoolBaseHelper::RequestSocket().
    733   int RequestSocket(const std::string& group_name,
    734                     const scoped_refptr<SocketParams>& params,
    735                     RequestPriority priority,
    736                     ClientSocketHandle* handle,
    737                     const CompletionCallback& callback,
    738                     const BoundNetLog& net_log) {
    739     scoped_ptr<const Request> request(
    740         new Request(handle, callback, priority,
    741                     internal::ClientSocketPoolBaseHelper::NORMAL,
    742                     params->ignore_limits(),
    743                     params, net_log));
    744     return helper_.RequestSocket(
    745         group_name,
    746         request.template PassAs<
    747             const internal::ClientSocketPoolBaseHelper::Request>());
    748   }
    749 
    750   // RequestSockets bundles up the parameters into a Request and then forwards
    751   // to ClientSocketPoolBaseHelper::RequestSockets().  Note that it assigns the
    752   // priority to DEFAULT_PRIORITY and specifies the NO_IDLE_SOCKETS flag.
    753   void RequestSockets(const std::string& group_name,
    754                       const scoped_refptr<SocketParams>& params,
    755                       int num_sockets,
    756                       const BoundNetLog& net_log) {
    757     const Request request(NULL /* no handle */,
    758                           CompletionCallback(),
    759                           DEFAULT_PRIORITY,
    760                           internal::ClientSocketPoolBaseHelper::NO_IDLE_SOCKETS,
    761                           params->ignore_limits(),
    762                           params,
    763                           net_log);
    764     helper_.RequestSockets(group_name, request, num_sockets);
    765   }
    766 
    767   void CancelRequest(const std::string& group_name,
    768                      ClientSocketHandle* handle) {
    769     return helper_.CancelRequest(group_name, handle);
    770   }
    771 
    772   void ReleaseSocket(const std::string& group_name,
    773                      scoped_ptr<StreamSocket> socket,
    774                      int id) {
    775     return helper_.ReleaseSocket(group_name, socket.Pass(), id);
    776   }
    777 
    778   void FlushWithError(int error) { helper_.FlushWithError(error); }
    779 
    780   bool IsStalled() const { return helper_.IsStalled(); }
    781 
    782   void CloseIdleSockets() { return helper_.CloseIdleSockets(); }
    783 
    784   int idle_socket_count() const { return helper_.idle_socket_count(); }
    785 
    786   int IdleSocketCountInGroup(const std::string& group_name) const {
    787     return helper_.IdleSocketCountInGroup(group_name);
    788   }
    789 
    790   LoadState GetLoadState(const std::string& group_name,
    791                          const ClientSocketHandle* handle) const {
    792     return helper_.GetLoadState(group_name, handle);
    793   }
    794 
    795   virtual void OnConnectJobComplete(int result, ConnectJob* job) {
    796     return helper_.OnConnectJobComplete(result, job);
    797   }
    798 
    799   int NumUnassignedConnectJobsInGroup(const std::string& group_name) const {
    800     return helper_.NumUnassignedConnectJobsInGroup(group_name);
    801   }
    802 
    803   int NumConnectJobsInGroup(const std::string& group_name) const {
    804     return helper_.NumConnectJobsInGroup(group_name);
    805   }
    806 
    807   int NumActiveSocketsInGroup(const std::string& group_name) const {
    808     return helper_.NumActiveSocketsInGroup(group_name);
    809   }
    810 
    811   bool HasGroup(const std::string& group_name) const {
    812     return helper_.HasGroup(group_name);
    813   }
    814 
    815   void CleanupIdleSockets(bool force) {
    816     return helper_.CleanupIdleSockets(force);
    817   }
    818 
    819   base::DictionaryValue* GetInfoAsValue(const std::string& name,
    820                                         const std::string& type) const {
    821     return helper_.GetInfoAsValue(name, type);
    822   }
    823 
    824   base::TimeDelta ConnectionTimeout() const {
    825     return helper_.ConnectionTimeout();
    826   }
    827 
    828   ClientSocketPoolHistograms* histograms() const {
    829     return histograms_;
    830   }
    831 
    832   void EnableConnectBackupJobs() { helper_.EnableConnectBackupJobs(); }
    833 
    834   bool CloseOneIdleSocket() { return helper_.CloseOneIdleSocket(); }
    835 
    836   bool CloseOneIdleConnectionInHigherLayeredPool() {
    837     return helper_.CloseOneIdleConnectionInHigherLayeredPool();
    838   }
    839 
    840  private:
    841   // This adaptor class exists to bridge the
    842   // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and
    843   // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the
    844   // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to
    845   // static_cast themselves.
    846   class ConnectJobFactoryAdaptor
    847       : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory {
    848    public:
    849     typedef typename ClientSocketPoolBase<SocketParams>::ConnectJobFactory
    850         ConnectJobFactory;
    851 
    852     explicit ConnectJobFactoryAdaptor(ConnectJobFactory* connect_job_factory)
    853         : connect_job_factory_(connect_job_factory) {}
    854     virtual ~ConnectJobFactoryAdaptor() {}
    855 
    856     virtual scoped_ptr<ConnectJob> NewConnectJob(
    857         const std::string& group_name,
    858         const internal::ClientSocketPoolBaseHelper::Request& request,
    859         ConnectJob::Delegate* delegate) const OVERRIDE {
    860       const Request& casted_request = static_cast<const Request&>(request);
    861       return connect_job_factory_->NewConnectJob(
    862           group_name, casted_request, delegate);
    863     }
    864 
    865     virtual base::TimeDelta ConnectionTimeout() const {
    866       return connect_job_factory_->ConnectionTimeout();
    867     }
    868 
    869     const scoped_ptr<ConnectJobFactory> connect_job_factory_;
    870   };
    871 
    872   // Histograms for the pool
    873   ClientSocketPoolHistograms* const histograms_;
    874   internal::ClientSocketPoolBaseHelper helper_;
    875 
    876   DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase);
    877 };
    878 
    879 }  // namespace net
    880 
    881 #endif  // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_
    882