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 #ifndef NET_SOCKET_CLIENT_SOCKET_POOL_H_
      6 #define NET_SOCKET_CLIENT_SOCKET_POOL_H_
      7 
      8 #include <deque>
      9 #include <string>
     10 
     11 #include "base/basictypes.h"
     12 #include "base/memory/ref_counted.h"
     13 #include "base/template_util.h"
     14 #include "base/time/time.h"
     15 #include "net/base/completion_callback.h"
     16 #include "net/base/load_states.h"
     17 #include "net/base/net_export.h"
     18 #include "net/base/request_priority.h"
     19 #include "net/dns/host_resolver.h"
     20 
     21 namespace base {
     22 class DictionaryValue;
     23 }
     24 
     25 namespace net {
     26 
     27 class ClientSocketHandle;
     28 class ClientSocketPoolHistograms;
     29 class StreamSocket;
     30 
     31 // ClientSocketPools are layered. This defines an interface for lower level
     32 // socket pools to communicate with higher layer pools.
     33 class NET_EXPORT LayeredPool {
     34  public:
     35   virtual ~LayeredPool() {};
     36 
     37   // Instructs the LayeredPool to close an idle connection. Return true if one
     38   // was closed.
     39   virtual bool CloseOneIdleConnection() = 0;
     40 };
     41 
     42 // A ClientSocketPool is used to restrict the number of sockets open at a time.
     43 // It also maintains a list of idle persistent sockets.
     44 //
     45 class NET_EXPORT ClientSocketPool {
     46  public:
     47   // Requests a connected socket for a group_name.
     48   //
     49   // There are five possible results from calling this function:
     50   // 1) RequestSocket returns OK and initializes |handle| with a reused socket.
     51   // 2) RequestSocket returns OK with a newly connected socket.
     52   // 3) RequestSocket returns ERR_IO_PENDING.  The handle will be added to a
     53   // wait list until a socket is available to reuse or a new socket finishes
     54   // connecting.  |priority| will determine the placement into the wait list.
     55   // 4) An error occurred early on, so RequestSocket returns an error code.
     56   // 5) A recoverable error occurred while setting up the socket.  An error
     57   // code is returned, but the |handle| is initialized with the new socket.
     58   // The caller must recover from the error before using the connection, or
     59   // Disconnect the socket before releasing or resetting the |handle|.
     60   // The current recoverable errors are: the errors accepted by
     61   // IsCertificateError(err) and PROXY_AUTH_REQUESTED, or
     62   // HTTPS_PROXY_TUNNEL_RESPONSE when reported by HttpProxyClientSocketPool.
     63   //
     64   // If this function returns OK, then |handle| is initialized upon return.
     65   // The |handle|'s is_initialized method will return true in this case.  If a
     66   // StreamSocket was reused, then ClientSocketPool will call
     67   // |handle|->set_reused(true).  In either case, the socket will have been
     68   // allocated and will be connected.  A client might want to know whether or
     69   // not the socket is reused in order to request a new socket if he encounters
     70   // an error with the reused socket.
     71   //
     72   // If ERR_IO_PENDING is returned, then the callback will be used to notify the
     73   // client of completion.
     74   //
     75   // Profiling information for the request is saved to |net_log| if non-NULL.
     76   virtual int RequestSocket(const std::string& group_name,
     77                             const void* params,
     78                             RequestPriority priority,
     79                             ClientSocketHandle* handle,
     80                             const CompletionCallback& callback,
     81                             const BoundNetLog& net_log) = 0;
     82 
     83   // RequestSockets is used to request that |num_sockets| be connected in the
     84   // connection group for |group_name|.  If the connection group already has
     85   // |num_sockets| idle sockets / active sockets / currently connecting sockets,
     86   // then this function doesn't do anything.  Otherwise, it will start up as
     87   // many connections as necessary to reach |num_sockets| total sockets for the
     88   // group.  It uses |params| to control how to connect the sockets.   The
     89   // ClientSocketPool will assign a priority to the new connections, if any.
     90   // This priority will probably be lower than all others, since this method
     91   // is intended to make sure ahead of time that |num_sockets| sockets are
     92   // available to talk to a host.
     93   virtual void RequestSockets(const std::string& group_name,
     94                               const void* params,
     95                               int num_sockets,
     96                               const BoundNetLog& net_log) = 0;
     97 
     98   // Called to cancel a RequestSocket call that returned ERR_IO_PENDING.  The
     99   // same handle parameter must be passed to this method as was passed to the
    100   // RequestSocket call being cancelled.  The associated CompletionCallback is
    101   // not run.  However, for performance, we will let one ConnectJob complete
    102   // and go idle.
    103   virtual void CancelRequest(const std::string& group_name,
    104                              ClientSocketHandle* handle) = 0;
    105 
    106   // Called to release a socket once the socket is no longer needed.  If the
    107   // socket still has an established connection, then it will be added to the
    108   // set of idle sockets to be used to satisfy future RequestSocket calls.
    109   // Otherwise, the StreamSocket is destroyed.  |id| is used to differentiate
    110   // between updated versions of the same pool instance.  The pool's id will
    111   // change when it flushes, so it can use this |id| to discard sockets with
    112   // mismatched ids.
    113   virtual void ReleaseSocket(const std::string& group_name,
    114                              StreamSocket* socket,
    115                              int id) = 0;
    116 
    117   // This flushes all state from the ClientSocketPool.  This means that all
    118   // idle and connecting sockets are discarded with the given |error|.
    119   // Active sockets being held by ClientSocketPool clients will be discarded
    120   // when released back to the pool.
    121   // Does not flush any pools wrapped by |this|.
    122   virtual void FlushWithError(int error) = 0;
    123 
    124   // Returns true if a there is currently a request blocked on the
    125   // per-pool (not per-host) max socket limit.
    126   virtual bool IsStalled() const = 0;
    127 
    128   // Called to close any idle connections held by the connection manager.
    129   virtual void CloseIdleSockets() = 0;
    130 
    131   // The total number of idle sockets in the pool.
    132   virtual int IdleSocketCount() const = 0;
    133 
    134   // The total number of idle sockets in a connection group.
    135   virtual int IdleSocketCountInGroup(const std::string& group_name) const = 0;
    136 
    137   // Determine the LoadState of a connecting ClientSocketHandle.
    138   virtual LoadState GetLoadState(const std::string& group_name,
    139                                  const ClientSocketHandle* handle) const = 0;
    140 
    141   // Adds a LayeredPool on top of |this|.
    142   virtual void AddLayeredPool(LayeredPool* layered_pool) = 0;
    143 
    144   // Removes a LayeredPool from |this|.
    145   virtual void RemoveLayeredPool(LayeredPool* layered_pool) = 0;
    146 
    147   // Retrieves information on the current state of the pool as a
    148   // DictionaryValue.  Caller takes possession of the returned value.
    149   // If |include_nested_pools| is true, the states of any nested
    150   // ClientSocketPools will be included.
    151   virtual base::DictionaryValue* GetInfoAsValue(
    152       const std::string& name,
    153       const std::string& type,
    154       bool include_nested_pools) const = 0;
    155 
    156   // Returns the maximum amount of time to wait before retrying a connect.
    157   static const int kMaxConnectRetryIntervalMs = 250;
    158 
    159   // The set of histograms specific to this pool.  We can't use the standard
    160   // UMA_HISTOGRAM_* macros because they are callsite static.
    161   virtual ClientSocketPoolHistograms* histograms() const = 0;
    162 
    163   static base::TimeDelta unused_idle_socket_timeout();
    164   static void set_unused_idle_socket_timeout(base::TimeDelta timeout);
    165 
    166   static base::TimeDelta used_idle_socket_timeout();
    167   static void set_used_idle_socket_timeout(base::TimeDelta timeout);
    168 
    169  protected:
    170   ClientSocketPool();
    171   virtual ~ClientSocketPool();
    172 
    173   // Return the connection timeout for this pool.
    174   virtual base::TimeDelta ConnectionTimeout() const = 0;
    175 
    176  private:
    177   DISALLOW_COPY_AND_ASSIGN(ClientSocketPool);
    178 };
    179 
    180 // ClientSocketPool subclasses should indicate valid SocketParams via the
    181 // REGISTER_SOCKET_PARAMS_FOR_POOL macro below.  By default, any given
    182 // <PoolType,SocketParams> pair will have its SocketParamsTrait inherit from
    183 // base::false_type, but REGISTER_SOCKET_PARAMS_FOR_POOL will specialize that
    184 // pairing to inherit from base::true_type.  This provides compile time
    185 // verification that the correct SocketParams type is used with the appropriate
    186 // PoolType.
    187 template <typename PoolType, typename SocketParams>
    188 struct SocketParamTraits : public base::false_type {
    189 };
    190 
    191 template <typename PoolType, typename SocketParams>
    192 void CheckIsValidSocketParamsForPool() {
    193   COMPILE_ASSERT(!base::is_pointer<scoped_refptr<SocketParams> >::value,
    194                  socket_params_cannot_be_pointer);
    195   COMPILE_ASSERT((SocketParamTraits<PoolType,
    196                                     scoped_refptr<SocketParams> >::value),
    197                  invalid_socket_params_for_pool);
    198 }
    199 
    200 // Provides an empty definition for CheckIsValidSocketParamsForPool() which
    201 // should be optimized out by the compiler.
    202 #define REGISTER_SOCKET_PARAMS_FOR_POOL(pool_type, socket_params)             \
    203 template<>                                                                    \
    204 struct SocketParamTraits<pool_type, scoped_refptr<socket_params> >            \
    205     : public base::true_type {                                                \
    206 }
    207 
    208 template <typename PoolType, typename SocketParams>
    209 void RequestSocketsForPool(PoolType* pool,
    210                            const std::string& group_name,
    211                            const scoped_refptr<SocketParams>& params,
    212                            int num_sockets,
    213                            const BoundNetLog& net_log) {
    214   CheckIsValidSocketParamsForPool<PoolType, SocketParams>();
    215   pool->RequestSockets(group_name, &params, num_sockets, net_log);
    216 }
    217 
    218 }  // namespace net
    219 
    220 #endif  // NET_SOCKET_CLIENT_SOCKET_POOL_H_
    221