Home | History | Annotate | Download | only in socket
      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:
     59     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
     77   const std::string& group_name() const { return group_name_; }
     78   const BoundNetLog& net_log() { return net_log_; }
     79   bool is_preconnect() const { return preconnect_state_ != NOT_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.
     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).
    111   virtual void GetAdditionalErrorState(ClientSocketHandle* handle) {}
    112 
    113   const BoundNetLog& net_log() const { return net_log_; }
    114 
    115  protected:
    116   void set_socket(ClientSocket* 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 
    184     ClientSocketHandle* handle() const { return handle_; }
    185     CompletionCallback* callback() const { return callback_; }
    186     RequestPriority priority() const { return priority_; }
    187     bool ignore_limits() const { return ignore_limits_; }
    188     Flags flags() const { return flags_; }
    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:
    208     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.
    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 
    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 
    275   int NumConnectJobsInGroup(const std::string& group_name) const {
    276     return group_map_.find(group_name)->second->jobs().size();
    277   }
    278 
    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   // Closes all idle sockets if |force| is true.  Else, only closes idle
    286   // sockets that timed out or can't be reused.  Made public for testing.
    287   void CleanupIdleSockets(bool force);
    288 
    289   // See ClientSocketPool::GetInfoAsValue for documentation on this function.
    290   DictionaryValue* GetInfoAsValue(const std::string& name,
    291                                   const std::string& type) const;
    292 
    293   base::TimeDelta ConnectionTimeout() const {
    294     return connect_job_factory_->ConnectionTimeout();
    295   }
    296 
    297   static bool connect_backup_jobs_enabled();
    298   static bool set_connect_backup_jobs_enabled(bool enabled);
    299 
    300   void EnableConnectBackupJobs();
    301 
    302   // ConnectJob::Delegate methods:
    303   virtual void OnConnectJobComplete(int result, ConnectJob* job);
    304 
    305   // NetworkChangeNotifier::IPAddressObserver methods:
    306   virtual void OnIPAddressChanged();
    307 
    308  private:
    309   friend class base::RefCounted<ClientSocketPoolBaseHelper>;
    310 
    311   // Entry for a persistent socket which became idle at time |start_time|.
    312   struct IdleSocket {
    313     IdleSocket() : socket(NULL) {}
    314 
    315     // An idle socket should be removed if it can't be reused, or has been idle
    316     // for too long. |now| is the current time value (TimeTicks::Now()).
    317     // |timeout| is the length of time to wait before timing out an idle socket.
    318     //
    319     // An idle socket can't be reused if it is disconnected or has received
    320     // data unexpectedly (hence no longer idle).  The unread data would be
    321     // mistaken for the beginning of the next response if we were to reuse the
    322     // socket for a new request.
    323     bool ShouldCleanup(base::TimeTicks now, base::TimeDelta timeout) const;
    324 
    325     ClientSocket* socket;
    326     base::TimeTicks start_time;
    327   };
    328 
    329   typedef std::deque<const Request* > RequestQueue;
    330   typedef std::map<const ClientSocketHandle*, const Request*> RequestMap;
    331 
    332   // A Group is allocated per group_name when there are idle sockets or pending
    333   // requests.  Otherwise, the Group object is removed from the map.
    334   // |active_socket_count| tracks the number of sockets held by clients.
    335   class Group {
    336    public:
    337     Group();
    338     ~Group();
    339 
    340     bool IsEmpty() const {
    341       return active_socket_count_ == 0 && idle_sockets_.empty() &&
    342           jobs_.empty() && pending_requests_.empty();
    343     }
    344 
    345     bool HasAvailableSocketSlot(int max_sockets_per_group) const {
    346       return NumActiveSocketSlots() < max_sockets_per_group;
    347     }
    348 
    349     int NumActiveSocketSlots() const {
    350       return active_socket_count_ + static_cast<int>(jobs_.size()) +
    351           static_cast<int>(idle_sockets_.size());
    352     }
    353 
    354     bool IsStalled(int max_sockets_per_group) const {
    355       return HasAvailableSocketSlot(max_sockets_per_group) &&
    356           pending_requests_.size() > jobs_.size();
    357     }
    358 
    359     RequestPriority TopPendingPriority() const {
    360       return pending_requests_.front()->priority();
    361     }
    362 
    363     bool HasBackupJob() const { return !method_factory_.empty(); }
    364 
    365     void CleanupBackupJob() {
    366       method_factory_.RevokeAll();
    367     }
    368 
    369     // Set a timer to create a backup socket if it takes too long to create one.
    370     void StartBackupSocketTimer(const std::string& group_name,
    371                                 ClientSocketPoolBaseHelper* pool);
    372 
    373     // Searches |jobs_| to see if there's a preconnect ConnectJob, and if so,
    374     // uses it.  Returns true on success.  Otherwise, returns false.
    375     bool TryToUsePreconnectConnectJob();
    376 
    377     void AddJob(ConnectJob* job) { jobs_.insert(job); }
    378     void RemoveJob(ConnectJob* job) { jobs_.erase(job); }
    379     void RemoveAllJobs();
    380 
    381     void IncrementActiveSocketCount() { active_socket_count_++; }
    382     void DecrementActiveSocketCount() { active_socket_count_--; }
    383 
    384     const std::set<ConnectJob*>& jobs() const { return jobs_; }
    385     const std::list<IdleSocket>& idle_sockets() const { return idle_sockets_; }
    386     const RequestQueue& pending_requests() const { return pending_requests_; }
    387     int active_socket_count() const { return active_socket_count_; }
    388     RequestQueue* mutable_pending_requests() { return &pending_requests_; }
    389     std::list<IdleSocket>* mutable_idle_sockets() { return &idle_sockets_; }
    390 
    391    private:
    392     // Called when the backup socket timer fires.
    393     void OnBackupSocketTimerFired(
    394         std::string group_name,
    395         ClientSocketPoolBaseHelper* pool);
    396 
    397     std::list<IdleSocket> idle_sockets_;
    398     std::set<ConnectJob*> jobs_;
    399     RequestQueue pending_requests_;
    400     int active_socket_count_;  // number of active sockets used by clients
    401     // A factory to pin the backup_job tasks.
    402     ScopedRunnableMethodFactory<Group> method_factory_;
    403   };
    404 
    405   typedef std::map<std::string, Group*> GroupMap;
    406 
    407   typedef std::set<ConnectJob*> ConnectJobSet;
    408 
    409   struct CallbackResultPair {
    410     CallbackResultPair() : callback(NULL), result(OK) {}
    411     CallbackResultPair(CompletionCallback* callback_in, int result_in)
    412         : callback(callback_in), result(result_in) {}
    413 
    414     CompletionCallback* callback;
    415     int result;
    416   };
    417 
    418   typedef std::map<const ClientSocketHandle*, CallbackResultPair>
    419       PendingCallbackMap;
    420 
    421   static void InsertRequestIntoQueue(const Request* r,
    422                                      RequestQueue* pending_requests);
    423   static const Request* RemoveRequestFromQueue(const RequestQueue::iterator& it,
    424                                                Group* group);
    425 
    426   Group* GetOrCreateGroup(const std::string& group_name);
    427   void RemoveGroup(const std::string& group_name);
    428   void RemoveGroup(GroupMap::iterator it);
    429 
    430   // Called when the number of idle sockets changes.
    431   void IncrementIdleCount();
    432   void DecrementIdleCount();
    433 
    434   // Scans the group map for groups which have an available socket slot and
    435   // at least one pending request. Returns true if any groups are stalled, and
    436   // if so, fills |group| and |group_name| with data of the stalled group
    437   // having highest priority.
    438   bool FindTopStalledGroup(Group** group, std::string* group_name);
    439 
    440   // Called when timer_ fires.  This method scans the idle sockets removing
    441   // sockets that timed out or can't be reused.
    442   void OnCleanupTimerFired() {
    443     CleanupIdleSockets(false);
    444   }
    445 
    446   // Removes |job| from |connect_job_set_|.  Also updates |group| if non-NULL.
    447   void RemoveConnectJob(ConnectJob* job, Group* group);
    448 
    449   // Tries to see if we can handle any more requests for |group|.
    450   void OnAvailableSocketSlot(const std::string& group_name, Group* group);
    451 
    452   // Process a pending socket request for a group.
    453   void ProcessPendingRequest(const std::string& group_name, Group* group);
    454 
    455   // Assigns |socket| to |handle| and updates |group|'s counters appropriately.
    456   void HandOutSocket(ClientSocket* socket,
    457                      bool reused,
    458                      ClientSocketHandle* handle,
    459                      base::TimeDelta time_idle,
    460                      Group* group,
    461                      const BoundNetLog& net_log);
    462 
    463   // Adds |socket| to the list of idle sockets for |group|.
    464   void AddIdleSocket(ClientSocket* socket, Group* group);
    465 
    466   // Iterates through |group_map_|, canceling all ConnectJobs and deleting
    467   // groups if they are no longer needed.
    468   void CancelAllConnectJobs();
    469 
    470   // Iterates through |group_map_|, posting ERR_ABORTED callbacks for all
    471   // requests, and then deleting groups if they are no longer needed.
    472   void AbortAllRequests();
    473 
    474   // Returns true if we can't create any more sockets due to the total limit.
    475   bool ReachedMaxSocketsLimit() const;
    476 
    477   // This is the internal implementation of RequestSocket().  It differs in that
    478   // it does not handle logging into NetLog of the queueing status of
    479   // |request|.
    480   int RequestSocketInternal(const std::string& group_name,
    481                             const Request* request);
    482 
    483   // Assigns an idle socket for the group to the request.
    484   // Returns |true| if an idle socket is available, false otherwise.
    485   bool AssignIdleSocketToGroup(const Request* request, Group* group);
    486 
    487   static void LogBoundConnectJobToRequest(
    488       const NetLog::Source& connect_job_source, const Request* request);
    489 
    490   // Closes one idle socket.  Picks the first one encountered.
    491   // TODO(willchan): Consider a better algorithm for doing this.  Perhaps we
    492   // should keep an ordered list of idle sockets, and close them in order.
    493   // Requires maintaining more state.  It's not clear if it's worth it since
    494   // I'm not sure if we hit this situation often.
    495   void CloseOneIdleSocket();
    496 
    497   // Same as CloseOneIdleSocket() except it won't close an idle socket in
    498   // |group|.  If |group| is NULL, it is ignored.  Returns true if it closed a
    499   // socket.
    500   bool CloseOneIdleSocketExceptInGroup(const Group* group);
    501 
    502   // Checks if there are stalled socket groups that should be notified
    503   // for possible wakeup.
    504   void CheckForStalledSocketGroups();
    505 
    506   // Posts a task to call InvokeUserCallback() on the next iteration through the
    507   // current message loop.  Inserts |callback| into |pending_callback_map_|,
    508   // keyed by |handle|.
    509   void InvokeUserCallbackLater(
    510       ClientSocketHandle* handle, CompletionCallback* callback, int rv);
    511 
    512   // Invokes the user callback for |handle|.  By the time this task has run,
    513   // it's possible that the request has been cancelled, so |handle| may not
    514   // exist in |pending_callback_map_|.  We look up the callback and result code
    515   // in |pending_callback_map_|.
    516   void InvokeUserCallback(ClientSocketHandle* handle);
    517 
    518   GroupMap group_map_;
    519 
    520   // Map of the ClientSocketHandles for which we have a pending Task to invoke a
    521   // callback.  This is necessary since, before we invoke said callback, it's
    522   // possible that the request is cancelled.
    523   PendingCallbackMap pending_callback_map_;
    524 
    525   // Timer used to periodically prune idle sockets that timed out or can't be
    526   // reused.
    527   base::RepeatingTimer<ClientSocketPoolBaseHelper> timer_;
    528 
    529   // The total number of idle sockets in the system.
    530   int idle_socket_count_;
    531 
    532   // Number of connecting sockets across all groups.
    533   int connecting_socket_count_;
    534 
    535   // Number of connected sockets we handed out across all groups.
    536   int handed_out_socket_count_;
    537 
    538   // The maximum total number of sockets. See ReachedMaxSocketsLimit.
    539   const int max_sockets_;
    540 
    541   // The maximum number of sockets kept per group.
    542   const int max_sockets_per_group_;
    543 
    544   // The time to wait until closing idle sockets.
    545   const base::TimeDelta unused_idle_socket_timeout_;
    546   const base::TimeDelta used_idle_socket_timeout_;
    547 
    548   const scoped_ptr<ConnectJobFactory> connect_job_factory_;
    549 
    550   // TODO(vandebo) Remove when backup jobs move to TransportClientSocketPool
    551   bool connect_backup_jobs_enabled_;
    552 
    553   // A unique id for the pool.  It gets incremented every time we Flush() the
    554   // pool.  This is so that when sockets get released back to the pool, we can
    555   // make sure that they are discarded rather than reused.
    556   int pool_generation_number_;
    557 
    558   ScopedRunnableMethodFactory<ClientSocketPoolBaseHelper> method_factory_;
    559 
    560   DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBaseHelper);
    561 };
    562 
    563 }  // namespace internal
    564 
    565 // The maximum duration, in seconds, to keep used idle persistent sockets alive.
    566 static const int kUsedIdleSocketTimeout = 300;  // 5 minutes
    567 
    568 template <typename SocketParams>
    569 class ClientSocketPoolBase {
    570  public:
    571   class Request : public internal::ClientSocketPoolBaseHelper::Request {
    572    public:
    573     Request(ClientSocketHandle* handle,
    574             CompletionCallback* callback,
    575             RequestPriority priority,
    576             internal::ClientSocketPoolBaseHelper::Flags flags,
    577             bool ignore_limits,
    578             const scoped_refptr<SocketParams>& params,
    579             const BoundNetLog& net_log
    580 #ifdef ANDROID
    581             , bool valid_uid, int calling_uid
    582 #endif
    583            )
    584         : internal::ClientSocketPoolBaseHelper::Request(
    585               handle, callback, priority, ignore_limits,
    586               flags, net_log
    587 #ifdef ANDROID
    588               , valid_uid, calling_uid
    589 #endif
    590               ),
    591           params_(params) {}
    592 
    593     const scoped_refptr<SocketParams>& params() const { return params_; }
    594 
    595    private:
    596     const scoped_refptr<SocketParams> params_;
    597   };
    598 
    599   class ConnectJobFactory {
    600    public:
    601     ConnectJobFactory() {}
    602     virtual ~ConnectJobFactory() {}
    603 
    604     virtual ConnectJob* NewConnectJob(
    605         const std::string& group_name,
    606         const Request& request,
    607         ConnectJob::Delegate* delegate) const = 0;
    608 
    609     virtual base::TimeDelta ConnectionTimeout() const = 0;
    610 
    611    private:
    612     DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory);
    613   };
    614 
    615   // |max_sockets| is the maximum number of sockets to be maintained by this
    616   // ClientSocketPool.  |max_sockets_per_group| specifies the maximum number of
    617   // sockets a "group" can have.  |unused_idle_socket_timeout| specifies how
    618   // long to leave an unused idle socket open before closing it.
    619   // |used_idle_socket_timeout| specifies how long to leave a previously used
    620   // idle socket open before closing it.
    621   ClientSocketPoolBase(
    622       int max_sockets,
    623       int max_sockets_per_group,
    624       ClientSocketPoolHistograms* histograms,
    625       base::TimeDelta unused_idle_socket_timeout,
    626       base::TimeDelta used_idle_socket_timeout,
    627       ConnectJobFactory* connect_job_factory)
    628       : histograms_(histograms),
    629         helper_(max_sockets, max_sockets_per_group,
    630                 unused_idle_socket_timeout, used_idle_socket_timeout,
    631                 new ConnectJobFactoryAdaptor(connect_job_factory)) {}
    632 
    633   virtual ~ClientSocketPoolBase() {}
    634 
    635   // These member functions simply forward to ClientSocketPoolBaseHelper.
    636 
    637   // RequestSocket bundles up the parameters into a Request and then forwards to
    638   // ClientSocketPoolBaseHelper::RequestSocket().
    639   int RequestSocket(const std::string& group_name,
    640                     const scoped_refptr<SocketParams>& params,
    641                     RequestPriority priority,
    642                     ClientSocketHandle* handle,
    643                     CompletionCallback* callback,
    644                     const BoundNetLog& net_log) {
    645 #ifdef ANDROID
    646     uid_t calling_uid = 0;
    647     bool valid_uid = params->getUID(&calling_uid);
    648 #endif
    649     Request* request =
    650         new Request(handle, callback, priority,
    651                     internal::ClientSocketPoolBaseHelper::NORMAL,
    652                     params->ignore_limits(),
    653                     params, net_log
    654 #ifdef ANDROID
    655                     , valid_uid, calling_uid
    656 #endif
    657                     );
    658     return helper_.RequestSocket(group_name, request);
    659   }
    660 
    661   // RequestSockets bundles up the parameters into a Request and then forwards
    662   // to ClientSocketPoolBaseHelper::RequestSockets().  Note that it assigns the
    663   // priority to LOWEST and specifies the NO_IDLE_SOCKETS flag.
    664   void RequestSockets(const std::string& group_name,
    665                       const scoped_refptr<SocketParams>& params,
    666                       int num_sockets,
    667                       const BoundNetLog& net_log) {
    668 #ifdef ANDROID
    669     uid_t calling_uid = 0;
    670     bool valid_uid = params->getUID(&calling_uid);
    671 #endif
    672     const Request request(NULL /* no handle */,
    673                           NULL /* no callback */,
    674                           LOWEST,
    675                           internal::ClientSocketPoolBaseHelper::NO_IDLE_SOCKETS,
    676                           params->ignore_limits(),
    677                           params,
    678                           net_log
    679 #ifdef ANDROID
    680                           , valid_uid, calling_uid
    681 #endif
    682                           );
    683     helper_.RequestSockets(group_name, request, num_sockets);
    684   }
    685 
    686   void CancelRequest(const std::string& group_name,
    687                      ClientSocketHandle* handle) {
    688     return helper_.CancelRequest(group_name, handle);
    689   }
    690 
    691   void ReleaseSocket(const std::string& group_name, ClientSocket* socket,
    692                      int id) {
    693     return helper_.ReleaseSocket(group_name, socket, id);
    694   }
    695 
    696   void CloseIdleSockets() { return helper_.CloseIdleSockets(); }
    697 
    698   int idle_socket_count() const { return helper_.idle_socket_count(); }
    699 
    700   int IdleSocketCountInGroup(const std::string& group_name) const {
    701     return helper_.IdleSocketCountInGroup(group_name);
    702   }
    703 
    704   LoadState GetLoadState(const std::string& group_name,
    705                          const ClientSocketHandle* handle) const {
    706     return helper_.GetLoadState(group_name, handle);
    707   }
    708 
    709   virtual void OnConnectJobComplete(int result, ConnectJob* job) {
    710     return helper_.OnConnectJobComplete(result, job);
    711   }
    712 
    713   int NumConnectJobsInGroup(const std::string& group_name) const {
    714     return helper_.NumConnectJobsInGroup(group_name);
    715   }
    716 
    717   int NumActiveSocketsInGroup(const std::string& group_name) const {
    718     return helper_.NumActiveSocketsInGroup(group_name);
    719   }
    720 
    721   bool HasGroup(const std::string& group_name) const {
    722     return helper_.HasGroup(group_name);
    723   }
    724 
    725   void CleanupIdleSockets(bool force) {
    726     return helper_.CleanupIdleSockets(force);
    727   }
    728 
    729   DictionaryValue* GetInfoAsValue(const std::string& name,
    730                                   const std::string& type) const {
    731     return helper_.GetInfoAsValue(name, type);
    732   }
    733 
    734   base::TimeDelta ConnectionTimeout() const {
    735     return helper_.ConnectionTimeout();
    736   }
    737 
    738   ClientSocketPoolHistograms* histograms() const {
    739     return histograms_;
    740   }
    741 
    742   void EnableConnectBackupJobs() { helper_.EnableConnectBackupJobs(); }
    743 
    744   void Flush() { helper_.Flush(); }
    745 
    746  private:
    747   // This adaptor class exists to bridge the
    748   // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and
    749   // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the
    750   // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to
    751   // static_cast themselves.
    752   class ConnectJobFactoryAdaptor
    753       : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory {
    754    public:
    755     typedef typename ClientSocketPoolBase<SocketParams>::ConnectJobFactory
    756         ConnectJobFactory;
    757 
    758     explicit ConnectJobFactoryAdaptor(ConnectJobFactory* connect_job_factory)
    759         : connect_job_factory_(connect_job_factory) {}
    760     virtual ~ConnectJobFactoryAdaptor() {}
    761 
    762     virtual ConnectJob* NewConnectJob(
    763         const std::string& group_name,
    764         const internal::ClientSocketPoolBaseHelper::Request& request,
    765         ConnectJob::Delegate* delegate) const {
    766       const Request* casted_request = static_cast<const Request*>(&request);
    767       return connect_job_factory_->NewConnectJob(
    768           group_name, *casted_request, delegate);
    769     }
    770 
    771     virtual base::TimeDelta ConnectionTimeout() const {
    772       return connect_job_factory_->ConnectionTimeout();
    773     }
    774 
    775     const scoped_ptr<ConnectJobFactory> connect_job_factory_;
    776   };
    777 
    778   // Histograms for the pool
    779   ClientSocketPoolHistograms* const histograms_;
    780   internal::ClientSocketPoolBaseHelper helper_;
    781 
    782   DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase);
    783 };
    784 
    785 }  // namespace net
    786 
    787 #endif  // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_
    788