OLD | NEW |
| (Empty) |
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_TRANSPORT_CLIENT_SOCKET_POOL_H_ | |
6 #define NET_SOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_ | |
7 | |
8 #include <string> | |
9 | |
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" | |
22 | |
23 namespace net { | |
24 | |
25 class ClientSocketFactory; | |
26 | |
27 typedef base::Callback<int(const AddressList&, const BoundNetLog& net_log)> | |
28 OnHostResolutionCallback; | |
29 | |
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. | |
45 }; | |
46 | |
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); | |
57 | |
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_; | |
62 } | |
63 | |
64 CombineConnectAndWritePolicy combine_connect_and_write() const { | |
65 return combine_connect_and_write_; | |
66 } | |
67 | |
68 private: | |
69 friend class base::RefCounted<TransportSocketParams>; | |
70 ~TransportSocketParams(); | |
71 | |
72 HostResolver::RequestInfo destination_; | |
73 bool ignore_limits_; | |
74 const OnHostResolutionCallback host_resolution_callback_; | |
75 CombineConnectAndWritePolicy combine_connect_and_write_; | |
76 | |
77 DISALLOW_COPY_AND_ASSIGN(TransportSocketParams); | |
78 }; | |
79 | |
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, | |
90 }; | |
91 | |
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, | |
99 }; | |
100 | |
101 TransportConnectJobHelper(const scoped_refptr<TransportSocketParams>& params, | |
102 ClientSocketFactory* client_socket_factory, | |
103 HostResolver* host_resolver, | |
104 LoadTimingInfo::ConnectTiming* connect_timing); | |
105 ~TransportConnectJobHelper(); | |
106 | |
107 ClientSocketFactory* client_socket_factory() { | |
108 return client_socket_factory_; | |
109 } | |
110 | |
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(); } | |
116 | |
117 int DoResolveHost(RequestPriority priority, const BoundNetLog& net_log); | |
118 int DoResolveHostComplete(int result, const BoundNetLog& net_log); | |
119 | |
120 template <class T> | |
121 int DoConnectInternal(T* job); | |
122 | |
123 template <class T> | |
124 void SetOnIOComplete(T* job); | |
125 | |
126 template <class T> | |
127 void OnIOComplete(T* job, int result); | |
128 | |
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); | |
132 | |
133 static const int kIPv6FallbackTimerInMs; | |
134 | |
135 private: | |
136 template <class T> | |
137 int DoLoop(T* job, int result); | |
138 | |
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_; | |
146 | |
147 DISALLOW_COPY_AND_ASSIGN(TransportConnectJobHelper); | |
148 }; | |
149 | |
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; | |
169 | |
170 // ConnectJob methods. | |
171 LoadState GetLoadState() const override; | |
172 | |
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); | |
176 | |
177 private: | |
178 enum ConnectInterval { | |
179 CONNECT_INTERVAL_LE_10MS, | |
180 CONNECT_INTERVAL_LE_20MS, | |
181 CONNECT_INTERVAL_GT_20MS, | |
182 }; | |
183 | |
184 friend class TransportConnectJobHelper; | |
185 | |
186 int DoResolveHost(); | |
187 int DoResolveHostComplete(int result); | |
188 int DoTransportConnect(); | |
189 int DoTransportConnectComplete(int result); | |
190 | |
191 // Not part of the state machine. | |
192 void DoIPv6FallbackTransportConnect(); | |
193 void DoIPv6FallbackTransportConnectComplete(int result); | |
194 | |
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; | |
199 | |
200 TransportConnectJobHelper helper_; | |
201 | |
202 scoped_ptr<StreamSocket> transport_socket_; | |
203 | |
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_; | |
208 | |
209 // Track the interval between this connect and previous connect. | |
210 ConnectInterval interval_between_connects_; | |
211 | |
212 DISALLOW_COPY_AND_ASSIGN(TransportConnectJob); | |
213 }; | |
214 | |
215 class NET_EXPORT_PRIVATE TransportClientSocketPool : public ClientSocketPool { | |
216 public: | |
217 typedef TransportSocketParams SocketParams; | |
218 | |
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); | |
226 | |
227 ~TransportClientSocketPool() override; | |
228 | |
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; | |
257 | |
258 // HigherLayeredPool implementation. | |
259 bool IsStalled() const override; | |
260 void AddHigherLayeredPool(HigherLayeredPool* higher_pool) override; | |
261 void RemoveHigherLayeredPool(HigherLayeredPool* higher_pool) override; | |
262 | |
263 protected: | |
264 // Methods shared with WebSocketTransportClientSocketPool | |
265 void NetLogTcpClientSocketPoolRequestedSocket( | |
266 const BoundNetLog& net_log, | |
267 const scoped_refptr<TransportSocketParams>* casted_params); | |
268 | |
269 private: | |
270 typedef ClientSocketPoolBase<TransportSocketParams> PoolBase; | |
271 | |
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) {} | |
281 | |
282 ~TransportConnectJobFactory() override {} | |
283 | |
284 // ClientSocketPoolBase::ConnectJobFactory methods. | |
285 | |
286 scoped_ptr<ConnectJob> NewConnectJob( | |
287 const std::string& group_name, | |
288 const PoolBase::Request& request, | |
289 ConnectJob::Delegate* delegate) const override; | |
290 | |
291 base::TimeDelta ConnectionTimeout() const override; | |
292 | |
293 private: | |
294 ClientSocketFactory* const client_socket_factory_; | |
295 HostResolver* const host_resolver_; | |
296 NetLog* net_log_; | |
297 | |
298 DISALLOW_COPY_AND_ASSIGN(TransportConnectJobFactory); | |
299 }; | |
300 | |
301 PoolBase base_; | |
302 | |
303 DISALLOW_COPY_AND_ASSIGN(TransportClientSocketPool); | |
304 }; | |
305 | |
306 template <class T> | |
307 int TransportConnectJobHelper::DoConnectInternal(T* job) { | |
308 next_state_ = STATE_RESOLVE_HOST; | |
309 return this->DoLoop(job, OK); | |
310 } | |
311 | |
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)); | |
319 } | |
320 | |
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")); | |
327 | |
328 result = this->DoLoop(job, result); | |
329 | |
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")); | |
334 | |
335 if (result != ERR_IO_PENDING) | |
336 job->NotifyDelegateOfCompletion(result); // Deletes |job| and |this| | |
337 } | |
338 | |
339 template <class T> | |
340 int TransportConnectJobHelper::DoLoop(T* job, int result) { | |
341 DCHECK_NE(next_state_, STATE_NONE); | |
342 | |
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; | |
366 } | |
367 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | |
368 | |
369 return rv; | |
370 } | |
371 | |
372 } // namespace net | |
373 | |
374 #endif // NET_SOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_ | |
OLD | NEW |