client_socket_pool.h revision 5821806d5e7f356e8fa4b058a389a808ea183019
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/time.h"
14#include "base/template_util.h"
15#include "net/base/completion_callback.h"
16#include "net/base/host_resolver.h"
17#include "net/base/load_states.h"
18#include "net/base/net_export.h"
19#include "net/base/request_priority.h"
20
21namespace base {
22class DictionaryValue;
23}
24
25namespace net {
26
27class ClientSocketHandle;
28class ClientSocketPoolHistograms;
29class StreamSocket;
30
31// ClientSocketPools are layered. This defines an interface for lower level
32// socket pools to communicate with higher layer pools.
33class 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//
45class 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.  Active sockets being
119  // held by ClientSocketPool clients will be discarded when released back to
120  // the pool.  Does not flush any pools wrapped by |this|.
121  virtual void Flush() = 0;
122
123  // Returns true if a there is currently a request blocked on the
124  // per-pool (not per-host) max socket limit.
125  virtual bool IsStalled() const = 0;
126
127  // Called to close any idle connections held by the connection manager.
128  virtual void CloseIdleSockets() = 0;
129
130  // The total number of idle sockets in the pool.
131  virtual int IdleSocketCount() const = 0;
132
133  // The total number of idle sockets in a connection group.
134  virtual int IdleSocketCountInGroup(const std::string& group_name) const = 0;
135
136  // Determine the LoadState of a connecting ClientSocketHandle.
137  virtual LoadState GetLoadState(const std::string& group_name,
138                                 const ClientSocketHandle* handle) const = 0;
139
140  // Adds a LayeredPool on top of |this|.
141  virtual void AddLayeredPool(LayeredPool* layered_pool) = 0;
142
143  // Removes a LayeredPool from |this|.
144  virtual void RemoveLayeredPool(LayeredPool* layered_pool) = 0;
145
146  // Retrieves information on the current state of the pool as a
147  // DictionaryValue.  Caller takes possession of the returned value.
148  // If |include_nested_pools| is true, the states of any nested
149  // ClientSocketPools will be included.
150  virtual base::DictionaryValue* GetInfoAsValue(
151      const std::string& name,
152      const std::string& type,
153      bool include_nested_pools) const = 0;
154
155  // Returns the maximum amount of time to wait before retrying a connect.
156  static const int kMaxConnectRetryIntervalMs = 250;
157
158  // The set of histograms specific to this pool.  We can't use the standard
159  // UMA_HISTOGRAM_* macros because they are callsite static.
160  virtual ClientSocketPoolHistograms* histograms() const = 0;
161
162  static base::TimeDelta unused_idle_socket_timeout();
163  static void set_unused_idle_socket_timeout(base::TimeDelta timeout);
164
165  static base::TimeDelta used_idle_socket_timeout();
166  static void set_used_idle_socket_timeout(base::TimeDelta timeout);
167
168 protected:
169  ClientSocketPool();
170  virtual ~ClientSocketPool();
171
172  // Return the connection timeout for this pool.
173  virtual base::TimeDelta ConnectionTimeout() const = 0;
174
175 private:
176  DISALLOW_COPY_AND_ASSIGN(ClientSocketPool);
177};
178
179// ClientSocketPool subclasses should indicate valid SocketParams via the
180// REGISTER_SOCKET_PARAMS_FOR_POOL macro below.  By default, any given
181// <PoolType,SocketParams> pair will have its SocketParamsTrait inherit from
182// base::false_type, but REGISTER_SOCKET_PARAMS_FOR_POOL will specialize that
183// pairing to inherit from base::true_type.  This provides compile time
184// verification that the correct SocketParams type is used with the appropriate
185// PoolType.
186template <typename PoolType, typename SocketParams>
187struct SocketParamTraits : public base::false_type {
188};
189
190template <typename PoolType, typename SocketParams>
191void CheckIsValidSocketParamsForPool() {
192  COMPILE_ASSERT(!base::is_pointer<scoped_refptr<SocketParams> >::value,
193                 socket_params_cannot_be_pointer);
194  COMPILE_ASSERT((SocketParamTraits<PoolType,
195                                    scoped_refptr<SocketParams> >::value),
196                 invalid_socket_params_for_pool);
197}
198
199// Provides an empty definition for CheckIsValidSocketParamsForPool() which
200// should be optimized out by the compiler.
201#define REGISTER_SOCKET_PARAMS_FOR_POOL(pool_type, socket_params)             \
202template<>                                                                    \
203struct SocketParamTraits<pool_type, scoped_refptr<socket_params> >            \
204    : public base::true_type {                                                \
205}
206
207template <typename PoolType, typename SocketParams>
208void RequestSocketsForPool(PoolType* pool,
209                           const std::string& group_name,
210                           const scoped_refptr<SocketParams>& params,
211                           int num_sockets,
212                           const BoundNetLog& net_log) {
213  CheckIsValidSocketParamsForPool<PoolType, SocketParams>();
214  pool->RequestSockets(group_name, &params, num_sockets, net_log);
215}
216
217}  // namespace net
218
219#endif  // NET_SOCKET_CLIENT_SOCKET_POOL_H_
220