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