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