prune resources in MemoryCache
[chromium-blink-merge.git] / net / socket / transport_client_socket_pool.h
blob2deb94740655ce12c60960d12d25b8ee5c15f00f
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.
5 #ifndef NET_SOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_
6 #define NET_SOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_
8 #include <string>
10 #include "base/basictypes.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/profiler/scoped_tracker.h"
14 #include "base/time/time.h"
15 #include "base/timer/timer.h"
16 #include "net/base/host_port_pair.h"
17 #include "net/dns/host_resolver.h"
18 #include "net/dns/single_request_host_resolver.h"
19 #include "net/socket/client_socket_pool.h"
20 #include "net/socket/client_socket_pool_base.h"
21 #include "net/socket/client_socket_pool_histograms.h"
23 namespace net {
25 class ClientSocketFactory;
27 typedef base::Callback<int(const AddressList&, const BoundNetLog& net_log)>
28 OnHostResolutionCallback;
30 class NET_EXPORT_PRIVATE TransportSocketParams
31 : public base::RefCounted<TransportSocketParams> {
32 public:
33 // CombineConnectAndWrite currently translates to using TCP FastOpen.
34 // TCP FastOpen should not be used if the first write to the socket may
35 // be non-idempotent, as the underlying socket could retransmit the data
36 // on failure of the first transmission.
37 // NOTE: Currently, COMBINE_CONNECT_AND_WRITE_DESIRED is used if the data in
38 // the write is known to be idempotent, and COMBINE_CONNECT_AND_WRITE_DEFAULT
39 // is used as a default for other cases (including non-idempotent writes).
40 enum CombineConnectAndWritePolicy {
41 COMBINE_CONNECT_AND_WRITE_DEFAULT, // Default policy, implemented in
42 // TransportSocketParams constructor.
43 COMBINE_CONNECT_AND_WRITE_DESIRED, // Combine if supported by socket.
44 COMBINE_CONNECT_AND_WRITE_PROHIBITED // Do not combine.
47 // |host_resolution_callback| will be invoked after the the hostname is
48 // resolved. If |host_resolution_callback| does not return OK, then the
49 // connection will be aborted with that value. |combine_connect_and_write|
50 // defines the policy for use of TCP FastOpen on this socket.
51 TransportSocketParams(
52 const HostPortPair& host_port_pair,
53 bool disable_resolver_cache,
54 bool ignore_limits,
55 const OnHostResolutionCallback& host_resolution_callback,
56 CombineConnectAndWritePolicy combine_connect_and_write);
58 const HostResolver::RequestInfo& destination() const { return destination_; }
59 bool ignore_limits() const { return ignore_limits_; }
60 const OnHostResolutionCallback& host_resolution_callback() const {
61 return host_resolution_callback_;
64 CombineConnectAndWritePolicy combine_connect_and_write() const {
65 return combine_connect_and_write_;
68 private:
69 friend class base::RefCounted<TransportSocketParams>;
70 ~TransportSocketParams();
72 HostResolver::RequestInfo destination_;
73 bool ignore_limits_;
74 const OnHostResolutionCallback host_resolution_callback_;
75 CombineConnectAndWritePolicy combine_connect_and_write_;
77 DISALLOW_COPY_AND_ASSIGN(TransportSocketParams);
80 // Common data and logic shared between TransportConnectJob and
81 // WebSocketTransportConnectJob.
82 class NET_EXPORT_PRIVATE TransportConnectJobHelper {
83 public:
84 enum State {
85 STATE_RESOLVE_HOST,
86 STATE_RESOLVE_HOST_COMPLETE,
87 STATE_TRANSPORT_CONNECT,
88 STATE_TRANSPORT_CONNECT_COMPLETE,
89 STATE_NONE,
92 // For recording the connection time in the appropriate bucket.
93 enum ConnectionLatencyHistogram {
94 CONNECTION_LATENCY_UNKNOWN,
95 CONNECTION_LATENCY_IPV4_WINS_RACE,
96 CONNECTION_LATENCY_IPV4_NO_RACE,
97 CONNECTION_LATENCY_IPV6_RACEABLE,
98 CONNECTION_LATENCY_IPV6_SOLO,
101 TransportConnectJobHelper(const scoped_refptr<TransportSocketParams>& params,
102 ClientSocketFactory* client_socket_factory,
103 HostResolver* host_resolver,
104 LoadTimingInfo::ConnectTiming* connect_timing);
105 ~TransportConnectJobHelper();
107 ClientSocketFactory* client_socket_factory() {
108 return client_socket_factory_;
111 const AddressList& addresses() const { return addresses_; }
112 State next_state() const { return next_state_; }
113 void set_next_state(State next_state) { next_state_ = next_state; }
114 CompletionCallback on_io_complete() const { return on_io_complete_; }
115 const TransportSocketParams* params() { return params_.get(); }
117 int DoResolveHost(RequestPriority priority, const BoundNetLog& net_log);
118 int DoResolveHostComplete(int result, const BoundNetLog& net_log);
120 template <class T>
121 int DoConnectInternal(T* job);
123 template <class T>
124 void SetOnIOComplete(T* job);
126 template <class T>
127 void OnIOComplete(T* job, int result);
129 // Record the histograms Net.DNS_Resolution_And_TCP_Connection_Latency2 and
130 // Net.TCP_Connection_Latency and return the connect duration.
131 base::TimeDelta HistogramDuration(ConnectionLatencyHistogram race_result);
133 static const int kIPv6FallbackTimerInMs;
135 private:
136 template <class T>
137 int DoLoop(T* job, int result);
139 scoped_refptr<TransportSocketParams> params_;
140 ClientSocketFactory* const client_socket_factory_;
141 SingleRequestHostResolver resolver_;
142 AddressList addresses_;
143 State next_state_;
144 CompletionCallback on_io_complete_;
145 LoadTimingInfo::ConnectTiming* connect_timing_;
147 DISALLOW_COPY_AND_ASSIGN(TransportConnectJobHelper);
150 // TransportConnectJob handles the host resolution necessary for socket creation
151 // and the transport (likely TCP) connect. TransportConnectJob also has fallback
152 // logic for IPv6 connect() timeouts (which may happen due to networks / routers
153 // with broken IPv6 support). Those timeouts take 20s, so rather than make the
154 // user wait 20s for the timeout to fire, we use a fallback timer
155 // (kIPv6FallbackTimerInMs) and start a connect() to a IPv4 address if the timer
156 // fires. Then we race the IPv4 connect() against the IPv6 connect() (which has
157 // a headstart) and return the one that completes first to the socket pool.
158 class NET_EXPORT_PRIVATE TransportConnectJob : public ConnectJob {
159 public:
160 TransportConnectJob(const std::string& group_name,
161 RequestPriority priority,
162 const scoped_refptr<TransportSocketParams>& params,
163 base::TimeDelta timeout_duration,
164 ClientSocketFactory* client_socket_factory,
165 HostResolver* host_resolver,
166 Delegate* delegate,
167 NetLog* net_log);
168 ~TransportConnectJob() override;
170 // ConnectJob methods.
171 LoadState GetLoadState() const override;
173 // Rolls |addrlist| forward until the first IPv4 address, if any.
174 // WARNING: this method should only be used to implement the prefer-IPv4 hack.
175 static void MakeAddressListStartWithIPv4(AddressList* addrlist);
177 private:
178 enum ConnectInterval {
179 CONNECT_INTERVAL_LE_10MS,
180 CONNECT_INTERVAL_LE_20MS,
181 CONNECT_INTERVAL_GT_20MS,
184 friend class TransportConnectJobHelper;
186 int DoResolveHost();
187 int DoResolveHostComplete(int result);
188 int DoTransportConnect();
189 int DoTransportConnectComplete(int result);
191 // Not part of the state machine.
192 void DoIPv6FallbackTransportConnect();
193 void DoIPv6FallbackTransportConnectComplete(int result);
195 // Begins the host resolution and the TCP connect. Returns OK on success
196 // and ERR_IO_PENDING if it cannot immediately service the request.
197 // Otherwise, it returns a net error code.
198 int ConnectInternal() override;
200 TransportConnectJobHelper helper_;
202 scoped_ptr<StreamSocket> transport_socket_;
204 scoped_ptr<StreamSocket> fallback_transport_socket_;
205 scoped_ptr<AddressList> fallback_addresses_;
206 base::TimeTicks fallback_connect_start_time_;
207 base::OneShotTimer<TransportConnectJob> fallback_timer_;
209 // Track the interval between this connect and previous connect.
210 ConnectInterval interval_between_connects_;
212 DISALLOW_COPY_AND_ASSIGN(TransportConnectJob);
215 class NET_EXPORT_PRIVATE TransportClientSocketPool : public ClientSocketPool {
216 public:
217 typedef TransportSocketParams SocketParams;
219 TransportClientSocketPool(
220 int max_sockets,
221 int max_sockets_per_group,
222 ClientSocketPoolHistograms* histograms,
223 HostResolver* host_resolver,
224 ClientSocketFactory* client_socket_factory,
225 NetLog* net_log);
227 ~TransportClientSocketPool() override;
229 // ClientSocketPool implementation.
230 int RequestSocket(const std::string& group_name,
231 const void* resolve_info,
232 RequestPriority priority,
233 ClientSocketHandle* handle,
234 const CompletionCallback& callback,
235 const BoundNetLog& net_log) override;
236 void RequestSockets(const std::string& group_name,
237 const void* params,
238 int num_sockets,
239 const BoundNetLog& net_log) override;
240 void CancelRequest(const std::string& group_name,
241 ClientSocketHandle* handle) override;
242 void ReleaseSocket(const std::string& group_name,
243 scoped_ptr<StreamSocket> socket,
244 int id) override;
245 void FlushWithError(int error) override;
246 void CloseIdleSockets() override;
247 int IdleSocketCount() const override;
248 int IdleSocketCountInGroup(const std::string& group_name) const override;
249 LoadState GetLoadState(const std::string& group_name,
250 const ClientSocketHandle* handle) const override;
251 base::DictionaryValue* GetInfoAsValue(
252 const std::string& name,
253 const std::string& type,
254 bool include_nested_pools) const override;
255 base::TimeDelta ConnectionTimeout() const override;
256 ClientSocketPoolHistograms* histograms() const override;
258 // HigherLayeredPool implementation.
259 bool IsStalled() const override;
260 void AddHigherLayeredPool(HigherLayeredPool* higher_pool) override;
261 void RemoveHigherLayeredPool(HigherLayeredPool* higher_pool) override;
263 protected:
264 // Methods shared with WebSocketTransportClientSocketPool
265 void NetLogTcpClientSocketPoolRequestedSocket(
266 const BoundNetLog& net_log,
267 const scoped_refptr<TransportSocketParams>* casted_params);
269 private:
270 typedef ClientSocketPoolBase<TransportSocketParams> PoolBase;
272 class TransportConnectJobFactory
273 : public PoolBase::ConnectJobFactory {
274 public:
275 TransportConnectJobFactory(ClientSocketFactory* client_socket_factory,
276 HostResolver* host_resolver,
277 NetLog* net_log)
278 : client_socket_factory_(client_socket_factory),
279 host_resolver_(host_resolver),
280 net_log_(net_log) {}
282 ~TransportConnectJobFactory() override {}
284 // ClientSocketPoolBase::ConnectJobFactory methods.
286 scoped_ptr<ConnectJob> NewConnectJob(
287 const std::string& group_name,
288 const PoolBase::Request& request,
289 ConnectJob::Delegate* delegate) const override;
291 base::TimeDelta ConnectionTimeout() const override;
293 private:
294 ClientSocketFactory* const client_socket_factory_;
295 HostResolver* const host_resolver_;
296 NetLog* net_log_;
298 DISALLOW_COPY_AND_ASSIGN(TransportConnectJobFactory);
301 PoolBase base_;
303 DISALLOW_COPY_AND_ASSIGN(TransportClientSocketPool);
306 template <class T>
307 int TransportConnectJobHelper::DoConnectInternal(T* job) {
308 next_state_ = STATE_RESOLVE_HOST;
309 return this->DoLoop(job, OK);
312 template <class T>
313 void TransportConnectJobHelper::SetOnIOComplete(T* job) {
314 // These usages of base::Unretained() are safe because IO callbacks are
315 // guaranteed not to be called after the object is destroyed.
316 on_io_complete_ = base::Bind(&TransportConnectJobHelper::OnIOComplete<T>,
317 base::Unretained(this),
318 base::Unretained(job));
321 template <class T>
322 void TransportConnectJobHelper::OnIOComplete(T* job, int result) {
323 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed.
324 tracked_objects::ScopedTracker tracking_profile(
325 FROM_HERE_WITH_EXPLICIT_FUNCTION(
326 "436634 TransportConnectJobHelper::OnIOComplete"));
328 result = this->DoLoop(job, result);
330 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed.
331 tracked_objects::ScopedTracker tracking_profile1(
332 FROM_HERE_WITH_EXPLICIT_FUNCTION(
333 "436634 TransportConnectJobHelper::OnIOComplete1"));
335 if (result != ERR_IO_PENDING)
336 job->NotifyDelegateOfCompletion(result); // Deletes |job| and |this|
339 template <class T>
340 int TransportConnectJobHelper::DoLoop(T* job, int result) {
341 DCHECK_NE(next_state_, STATE_NONE);
343 int rv = result;
344 do {
345 State state = next_state_;
346 next_state_ = STATE_NONE;
347 switch (state) {
348 case STATE_RESOLVE_HOST:
349 DCHECK_EQ(OK, rv);
350 rv = job->DoResolveHost();
351 break;
352 case STATE_RESOLVE_HOST_COMPLETE:
353 rv = job->DoResolveHostComplete(rv);
354 break;
355 case STATE_TRANSPORT_CONNECT:
356 DCHECK_EQ(OK, rv);
357 rv = job->DoTransportConnect();
358 break;
359 case STATE_TRANSPORT_CONNECT_COMPLETE:
360 rv = job->DoTransportConnectComplete(rv);
361 break;
362 default:
363 NOTREACHED();
364 rv = ERR_FAILED;
365 break;
367 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
369 return rv;
372 } // namespace net
374 #endif // NET_SOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_