summaryrefslogtreecommitdiff
path: root/chromium/net/socket/client_socket_pool.h
blob: 7cb9a7ebc2eb2209b9f0caf261fef4b4bb97dd77 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_SOCKET_CLIENT_SOCKET_POOL_H_
#define NET_SOCKET_CLIENT_SOCKET_POOL_H_

#include <deque>
#include <string>

#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/template_util.h"
#include "base/time/time.h"
#include "net/base/completion_callback.h"
#include "net/base/load_states.h"
#include "net/base/net_export.h"
#include "net/base/request_priority.h"
#include "net/dns/host_resolver.h"

namespace base {
class DictionaryValue;
}

namespace net {

class ClientSocketHandle;
class ClientSocketPoolHistograms;
class StreamSocket;

// ClientSocketPools are layered. This defines an interface for lower level
// socket pools to communicate with higher layer pools.
class NET_EXPORT LayeredPool {
 public:
  virtual ~LayeredPool() {};

  // Instructs the LayeredPool to close an idle connection. Return true if one
  // was closed.
  virtual bool CloseOneIdleConnection() = 0;
};

// A ClientSocketPool is used to restrict the number of sockets open at a time.
// It also maintains a list of idle persistent sockets.
//
class NET_EXPORT ClientSocketPool {
 public:
  // Requests a connected socket for a group_name.
  //
  // There are five possible results from calling this function:
  // 1) RequestSocket returns OK and initializes |handle| with a reused socket.
  // 2) RequestSocket returns OK with a newly connected socket.
  // 3) RequestSocket returns ERR_IO_PENDING.  The handle will be added to a
  // wait list until a socket is available to reuse or a new socket finishes
  // connecting.  |priority| will determine the placement into the wait list.
  // 4) An error occurred early on, so RequestSocket returns an error code.
  // 5) A recoverable error occurred while setting up the socket.  An error
  // code is returned, but the |handle| is initialized with the new socket.
  // The caller must recover from the error before using the connection, or
  // Disconnect the socket before releasing or resetting the |handle|.
  // The current recoverable errors are: the errors accepted by
  // IsCertificateError(err) and PROXY_AUTH_REQUESTED, or
  // HTTPS_PROXY_TUNNEL_RESPONSE when reported by HttpProxyClientSocketPool.
  //
  // If this function returns OK, then |handle| is initialized upon return.
  // The |handle|'s is_initialized method will return true in this case.  If a
  // StreamSocket was reused, then ClientSocketPool will call
  // |handle|->set_reused(true).  In either case, the socket will have been
  // allocated and will be connected.  A client might want to know whether or
  // not the socket is reused in order to request a new socket if he encounters
  // an error with the reused socket.
  //
  // If ERR_IO_PENDING is returned, then the callback will be used to notify the
  // client of completion.
  //
  // Profiling information for the request is saved to |net_log| if non-NULL.
  virtual int RequestSocket(const std::string& group_name,
                            const void* params,
                            RequestPriority priority,
                            ClientSocketHandle* handle,
                            const CompletionCallback& callback,
                            const BoundNetLog& net_log) = 0;

  // RequestSockets is used to request that |num_sockets| be connected in the
  // connection group for |group_name|.  If the connection group already has
  // |num_sockets| idle sockets / active sockets / currently connecting sockets,
  // then this function doesn't do anything.  Otherwise, it will start up as
  // many connections as necessary to reach |num_sockets| total sockets for the
  // group.  It uses |params| to control how to connect the sockets.   The
  // ClientSocketPool will assign a priority to the new connections, if any.
  // This priority will probably be lower than all others, since this method
  // is intended to make sure ahead of time that |num_sockets| sockets are
  // available to talk to a host.
  virtual void RequestSockets(const std::string& group_name,
                              const void* params,
                              int num_sockets,
                              const BoundNetLog& net_log) = 0;

  // Called to cancel a RequestSocket call that returned ERR_IO_PENDING.  The
  // same handle parameter must be passed to this method as was passed to the
  // RequestSocket call being cancelled.  The associated CompletionCallback is
  // not run.  However, for performance, we will let one ConnectJob complete
  // and go idle.
  virtual void CancelRequest(const std::string& group_name,
                             ClientSocketHandle* handle) = 0;

  // Called to release a socket once the socket is no longer needed.  If the
  // socket still has an established connection, then it will be added to the
  // set of idle sockets to be used to satisfy future RequestSocket calls.
  // Otherwise, the StreamSocket is destroyed.  |id| is used to differentiate
  // between updated versions of the same pool instance.  The pool's id will
  // change when it flushes, so it can use this |id| to discard sockets with
  // mismatched ids.
  virtual void ReleaseSocket(const std::string& group_name,
                             StreamSocket* socket,
                             int id) = 0;

  // This flushes all state from the ClientSocketPool.  This means that all
  // idle and connecting sockets are discarded with the given |error|.
  // Active sockets being held by ClientSocketPool clients will be discarded
  // when released back to the pool.
  // Does not flush any pools wrapped by |this|.
  virtual void FlushWithError(int error) = 0;

  // Returns true if a there is currently a request blocked on the
  // per-pool (not per-host) max socket limit.
  virtual bool IsStalled() const = 0;

  // Called to close any idle connections held by the connection manager.
  virtual void CloseIdleSockets() = 0;

  // The total number of idle sockets in the pool.
  virtual int IdleSocketCount() const = 0;

  // The total number of idle sockets in a connection group.
  virtual int IdleSocketCountInGroup(const std::string& group_name) const = 0;

  // Determine the LoadState of a connecting ClientSocketHandle.
  virtual LoadState GetLoadState(const std::string& group_name,
                                 const ClientSocketHandle* handle) const = 0;

  // Adds a LayeredPool on top of |this|.
  virtual void AddLayeredPool(LayeredPool* layered_pool) = 0;

  // Removes a LayeredPool from |this|.
  virtual void RemoveLayeredPool(LayeredPool* layered_pool) = 0;

  // Retrieves information on the current state of the pool as a
  // DictionaryValue.  Caller takes possession of the returned value.
  // If |include_nested_pools| is true, the states of any nested
  // ClientSocketPools will be included.
  virtual base::DictionaryValue* GetInfoAsValue(
      const std::string& name,
      const std::string& type,
      bool include_nested_pools) const = 0;

  // Returns the maximum amount of time to wait before retrying a connect.
  static const int kMaxConnectRetryIntervalMs = 250;

  // The set of histograms specific to this pool.  We can't use the standard
  // UMA_HISTOGRAM_* macros because they are callsite static.
  virtual ClientSocketPoolHistograms* histograms() const = 0;

  static base::TimeDelta unused_idle_socket_timeout();
  static void set_unused_idle_socket_timeout(base::TimeDelta timeout);

  static base::TimeDelta used_idle_socket_timeout();
  static void set_used_idle_socket_timeout(base::TimeDelta timeout);

 protected:
  ClientSocketPool();
  virtual ~ClientSocketPool();

  // Return the connection timeout for this pool.
  virtual base::TimeDelta ConnectionTimeout() const = 0;

 private:
  DISALLOW_COPY_AND_ASSIGN(ClientSocketPool);
};

// ClientSocketPool subclasses should indicate valid SocketParams via the
// REGISTER_SOCKET_PARAMS_FOR_POOL macro below.  By default, any given
// <PoolType,SocketParams> pair will have its SocketParamsTrait inherit from
// base::false_type, but REGISTER_SOCKET_PARAMS_FOR_POOL will specialize that
// pairing to inherit from base::true_type.  This provides compile time
// verification that the correct SocketParams type is used with the appropriate
// PoolType.
template <typename PoolType, typename SocketParams>
struct SocketParamTraits : public base::false_type {
};

template <typename PoolType, typename SocketParams>
void CheckIsValidSocketParamsForPool() {
  COMPILE_ASSERT(!base::is_pointer<scoped_refptr<SocketParams> >::value,
                 socket_params_cannot_be_pointer);
  COMPILE_ASSERT((SocketParamTraits<PoolType,
                                    scoped_refptr<SocketParams> >::value),
                 invalid_socket_params_for_pool);
}

// Provides an empty definition for CheckIsValidSocketParamsForPool() which
// should be optimized out by the compiler.
#define REGISTER_SOCKET_PARAMS_FOR_POOL(pool_type, socket_params)             \
template<>                                                                    \
struct SocketParamTraits<pool_type, scoped_refptr<socket_params> >            \
    : public base::true_type {                                                \
}

template <typename PoolType, typename SocketParams>
void RequestSocketsForPool(PoolType* pool,
                           const std::string& group_name,
                           const scoped_refptr<SocketParams>& params,
                           int num_sockets,
                           const BoundNetLog& net_log) {
  CheckIsValidSocketParamsForPool<PoolType, SocketParams>();
  pool->RequestSockets(group_name, &params, num_sockets, net_log);
}

}  // namespace net

#endif  // NET_SOCKET_CLIENT_SOCKET_POOL_H_