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