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_
10 #include "base/basictypes.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/time/time.h"
14 #include "base/timer/timer.h"
15 #include "net/base/host_port_pair.h"
16 #include "net/dns/host_resolver.h"
17 #include "net/dns/single_request_host_resolver.h"
18 #include "net/socket/client_socket_pool.h"
19 #include "net/socket/client_socket_pool_base.h"
20 #include "net/socket/client_socket_pool_histograms.h"
24 class ClientSocketFactory
;
26 typedef base::Callback
<int(const AddressList
&, const BoundNetLog
& net_log
)>
27 OnHostResolutionCallback
;
29 class NET_EXPORT_PRIVATE TransportSocketParams
30 : public base::RefCounted
<TransportSocketParams
> {
32 // |host_resolution_callback| will be invoked after the the hostname is
33 // resolved. If |host_resolution_callback| does not return OK, then the
34 // connection will be aborted with that value.
35 TransportSocketParams(
36 const HostPortPair
& host_port_pair
,
37 bool disable_resolver_cache
,
39 const OnHostResolutionCallback
& host_resolution_callback
);
41 const HostResolver::RequestInfo
& destination() const { return destination_
; }
42 bool ignore_limits() const { return ignore_limits_
; }
43 const OnHostResolutionCallback
& host_resolution_callback() const {
44 return host_resolution_callback_
;
48 friend class base::RefCounted
<TransportSocketParams
>;
49 ~TransportSocketParams();
51 HostResolver::RequestInfo destination_
;
53 const OnHostResolutionCallback host_resolution_callback_
;
55 DISALLOW_COPY_AND_ASSIGN(TransportSocketParams
);
58 // Common data and logic shared between TransportConnectJob and
59 // WebSocketTransportConnectJob.
60 class NET_EXPORT_PRIVATE TransportConnectJobHelper
{
64 STATE_RESOLVE_HOST_COMPLETE
,
65 STATE_TRANSPORT_CONNECT
,
66 STATE_TRANSPORT_CONNECT_COMPLETE
,
70 // For recording the connection time in the appropriate bucket.
71 enum ConnectionLatencyHistogram
{
72 CONNECTION_LATENCY_UNKNOWN
,
73 CONNECTION_LATENCY_IPV4_WINS_RACE
,
74 CONNECTION_LATENCY_IPV4_NO_RACE
,
75 CONNECTION_LATENCY_IPV6_RACEABLE
,
76 CONNECTION_LATENCY_IPV6_SOLO
,
79 TransportConnectJobHelper(const scoped_refptr
<TransportSocketParams
>& params
,
80 ClientSocketFactory
* client_socket_factory
,
81 HostResolver
* host_resolver
,
82 LoadTimingInfo::ConnectTiming
* connect_timing
);
83 ~TransportConnectJobHelper();
85 ClientSocketFactory
* client_socket_factory() {
86 return client_socket_factory_
;
89 const AddressList
& addresses() const { return addresses_
; }
90 State
next_state() const { return next_state_
; }
91 void set_next_state(State next_state
) { next_state_
= next_state
; }
92 CompletionCallback
on_io_complete() const { return on_io_complete_
; }
94 int DoResolveHost(RequestPriority priority
, const BoundNetLog
& net_log
);
95 int DoResolveHostComplete(int result
, const BoundNetLog
& net_log
);
98 int DoConnectInternal(T
* job
);
101 void SetOnIOComplete(T
* job
);
104 void OnIOComplete(T
* job
, int result
);
106 // Record the histograms Net.DNS_Resolution_And_TCP_Connection_Latency2 and
107 // Net.TCP_Connection_Latency and return the connect duration.
108 base::TimeDelta
HistogramDuration(ConnectionLatencyHistogram race_result
);
110 static const int kIPv6FallbackTimerInMs
;
114 int DoLoop(T
* job
, int result
);
116 scoped_refptr
<TransportSocketParams
> params_
;
117 ClientSocketFactory
* const client_socket_factory_
;
118 SingleRequestHostResolver resolver_
;
119 AddressList addresses_
;
121 CompletionCallback on_io_complete_
;
122 LoadTimingInfo::ConnectTiming
* connect_timing_
;
124 DISALLOW_COPY_AND_ASSIGN(TransportConnectJobHelper
);
127 // TransportConnectJob handles the host resolution necessary for socket creation
128 // and the transport (likely TCP) connect. TransportConnectJob also has fallback
129 // logic for IPv6 connect() timeouts (which may happen due to networks / routers
130 // with broken IPv6 support). Those timeouts take 20s, so rather than make the
131 // user wait 20s for the timeout to fire, we use a fallback timer
132 // (kIPv6FallbackTimerInMs) and start a connect() to a IPv4 address if the timer
133 // fires. Then we race the IPv4 connect() against the IPv6 connect() (which has
134 // a headstart) and return the one that completes first to the socket pool.
135 class NET_EXPORT_PRIVATE TransportConnectJob
: public ConnectJob
{
137 TransportConnectJob(const std::string
& group_name
,
138 RequestPriority priority
,
139 const scoped_refptr
<TransportSocketParams
>& params
,
140 base::TimeDelta timeout_duration
,
141 ClientSocketFactory
* client_socket_factory
,
142 HostResolver
* host_resolver
,
145 virtual ~TransportConnectJob();
147 // ConnectJob methods.
148 virtual LoadState
GetLoadState() const OVERRIDE
;
150 // Rolls |addrlist| forward until the first IPv4 address, if any.
151 // WARNING: this method should only be used to implement the prefer-IPv4 hack.
152 static void MakeAddressListStartWithIPv4(AddressList
* addrlist
);
155 enum ConnectInterval
{
156 CONNECT_INTERVAL_LE_10MS
,
157 CONNECT_INTERVAL_LE_20MS
,
158 CONNECT_INTERVAL_GT_20MS
,
161 friend class TransportConnectJobHelper
;
164 int DoResolveHostComplete(int result
);
165 int DoTransportConnect();
166 int DoTransportConnectComplete(int result
);
168 // Not part of the state machine.
169 void DoIPv6FallbackTransportConnect();
170 void DoIPv6FallbackTransportConnectComplete(int result
);
172 // Begins the host resolution and the TCP connect. Returns OK on success
173 // and ERR_IO_PENDING if it cannot immediately service the request.
174 // Otherwise, it returns a net error code.
175 virtual int ConnectInternal() OVERRIDE
;
177 TransportConnectJobHelper helper_
;
179 scoped_ptr
<StreamSocket
> transport_socket_
;
181 scoped_ptr
<StreamSocket
> fallback_transport_socket_
;
182 scoped_ptr
<AddressList
> fallback_addresses_
;
183 base::TimeTicks fallback_connect_start_time_
;
184 base::OneShotTimer
<TransportConnectJob
> fallback_timer_
;
186 // Track the interval between this connect and previous connect.
187 ConnectInterval interval_between_connects_
;
189 DISALLOW_COPY_AND_ASSIGN(TransportConnectJob
);
192 class NET_EXPORT_PRIVATE TransportClientSocketPool
: public ClientSocketPool
{
194 typedef TransportSocketParams SocketParams
;
196 TransportClientSocketPool(
198 int max_sockets_per_group
,
199 ClientSocketPoolHistograms
* histograms
,
200 HostResolver
* host_resolver
,
201 ClientSocketFactory
* client_socket_factory
,
204 virtual ~TransportClientSocketPool();
206 // ClientSocketPool implementation.
207 virtual int RequestSocket(const std::string
& group_name
,
208 const void* resolve_info
,
209 RequestPriority priority
,
210 ClientSocketHandle
* handle
,
211 const CompletionCallback
& callback
,
212 const BoundNetLog
& net_log
) OVERRIDE
;
213 virtual void RequestSockets(const std::string
& group_name
,
216 const BoundNetLog
& net_log
) OVERRIDE
;
217 virtual void CancelRequest(const std::string
& group_name
,
218 ClientSocketHandle
* handle
) OVERRIDE
;
219 virtual void ReleaseSocket(const std::string
& group_name
,
220 scoped_ptr
<StreamSocket
> socket
,
222 virtual void FlushWithError(int error
) OVERRIDE
;
223 virtual void CloseIdleSockets() OVERRIDE
;
224 virtual int IdleSocketCount() const OVERRIDE
;
225 virtual int IdleSocketCountInGroup(
226 const std::string
& group_name
) const OVERRIDE
;
227 virtual LoadState
GetLoadState(
228 const std::string
& group_name
,
229 const ClientSocketHandle
* handle
) const OVERRIDE
;
230 virtual base::DictionaryValue
* GetInfoAsValue(
231 const std::string
& name
,
232 const std::string
& type
,
233 bool include_nested_pools
) const OVERRIDE
;
234 virtual base::TimeDelta
ConnectionTimeout() const OVERRIDE
;
235 virtual ClientSocketPoolHistograms
* histograms() const OVERRIDE
;
237 // HigherLayeredPool implementation.
238 virtual bool IsStalled() const OVERRIDE
;
239 virtual void AddHigherLayeredPool(HigherLayeredPool
* higher_pool
) OVERRIDE
;
240 virtual void RemoveHigherLayeredPool(HigherLayeredPool
* higher_pool
) OVERRIDE
;
243 // Methods shared with WebSocketTransportClientSocketPool
244 void NetLogTcpClientSocketPoolRequestedSocket(
245 const BoundNetLog
& net_log
,
246 const scoped_refptr
<TransportSocketParams
>* casted_params
);
249 typedef ClientSocketPoolBase
<TransportSocketParams
> PoolBase
;
251 class TransportConnectJobFactory
252 : public PoolBase::ConnectJobFactory
{
254 TransportConnectJobFactory(ClientSocketFactory
* client_socket_factory
,
255 HostResolver
* host_resolver
,
257 : client_socket_factory_(client_socket_factory
),
258 host_resolver_(host_resolver
),
261 virtual ~TransportConnectJobFactory() {}
263 // ClientSocketPoolBase::ConnectJobFactory methods.
265 virtual scoped_ptr
<ConnectJob
> NewConnectJob(
266 const std::string
& group_name
,
267 const PoolBase::Request
& request
,
268 ConnectJob::Delegate
* delegate
) const OVERRIDE
;
270 virtual base::TimeDelta
ConnectionTimeout() const OVERRIDE
;
273 ClientSocketFactory
* const client_socket_factory_
;
274 HostResolver
* const host_resolver_
;
277 DISALLOW_COPY_AND_ASSIGN(TransportConnectJobFactory
);
282 DISALLOW_COPY_AND_ASSIGN(TransportClientSocketPool
);
286 int TransportConnectJobHelper::DoConnectInternal(T
* job
) {
287 next_state_
= STATE_RESOLVE_HOST
;
288 return this->DoLoop(job
, OK
);
292 void TransportConnectJobHelper::SetOnIOComplete(T
* job
) {
293 // These usages of base::Unretained() are safe because IO callbacks are
294 // guaranteed not to be called after the object is destroyed.
295 on_io_complete_
= base::Bind(&TransportConnectJobHelper::OnIOComplete
<T
>,
296 base::Unretained(this),
297 base::Unretained(job
));
301 void TransportConnectJobHelper::OnIOComplete(T
* job
, int result
) {
302 result
= this->DoLoop(job
, result
);
303 if (result
!= ERR_IO_PENDING
)
304 job
->NotifyDelegateOfCompletion(result
); // Deletes |job| and |this|
308 int TransportConnectJobHelper::DoLoop(T
* job
, int result
) {
309 DCHECK_NE(next_state_
, STATE_NONE
);
313 State state
= next_state_
;
314 next_state_
= STATE_NONE
;
316 case STATE_RESOLVE_HOST
:
318 rv
= job
->DoResolveHost();
320 case STATE_RESOLVE_HOST_COMPLETE
:
321 rv
= job
->DoResolveHostComplete(rv
);
323 case STATE_TRANSPORT_CONNECT
:
325 rv
= job
->DoTransportConnect();
327 case STATE_TRANSPORT_CONNECT_COMPLETE
:
328 rv
= job
->DoTransportConnectComplete(rv
);
335 } while (rv
!= ERR_IO_PENDING
&& next_state_
!= STATE_NONE
);
342 #endif // NET_SOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_