Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(330)

Side by Side Diff: net/socket/transport_client_socket_pool.cc

Issue 240873003: Create WebSocketTransportClientSocketPool (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rebase. Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/socket/transport_client_socket_pool.h" 5 #include "net/socket/transport_client_socket_pool.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
(...skipping 13 matching lines...) Expand all
24 #include "net/socket/socket_net_log_params.h" 24 #include "net/socket/socket_net_log_params.h"
25 #include "net/socket/tcp_client_socket.h" 25 #include "net/socket/tcp_client_socket.h"
26 26
27 using base::TimeDelta; 27 using base::TimeDelta;
28 28
29 namespace net { 29 namespace net {
30 30
31 // TODO(willchan): Base this off RTT instead of statically setting it. Note we 31 // TODO(willchan): Base this off RTT instead of statically setting it. Note we
32 // choose a timeout that is different from the backup connect job timer so they 32 // choose a timeout that is different from the backup connect job timer so they
33 // don't synchronize. 33 // don't synchronize.
34 const int TransportConnectJob::kIPv6FallbackTimerInMs = 300; 34 const int TransportConnectJobHelper::kIPv6FallbackTimerInMs = 300;
35 35
36 namespace { 36 namespace {
37 37
38 // Returns true iff all addresses in |list| are in the IPv6 family. 38 // Returns true iff all addresses in |list| are in the IPv6 family.
39 bool AddressListOnlyContainsIPv6(const AddressList& list) { 39 bool AddressListOnlyContainsIPv6(const AddressList& list) {
40 DCHECK(!list.empty()); 40 DCHECK(!list.empty());
41 for (AddressList::const_iterator iter = list.begin(); iter != list.end(); 41 for (AddressList::const_iterator iter = list.begin(); iter != list.end();
42 ++iter) { 42 ++iter) {
43 if (iter->GetFamily() != ADDRESS_FAMILY_IPV6) 43 if (iter->GetFamily() != ADDRESS_FAMILY_IPV6)
44 return false; 44 return false;
(...skipping 29 matching lines...) Expand all
74 // the total time, including both host resolution and TCP connect() times. 74 // the total time, including both host resolution and TCP connect() times.
75 // 75 //
76 // TODO(eroman): The use of this constant needs to be re-evaluated. The time 76 // TODO(eroman): The use of this constant needs to be re-evaluated. The time
77 // needed for TCPClientSocketXXX::Connect() can be arbitrarily long, since 77 // needed for TCPClientSocketXXX::Connect() can be arbitrarily long, since
78 // the address list may contain many alternatives, and most of those may 78 // the address list may contain many alternatives, and most of those may
79 // timeout. Even worse, the per-connect timeout threshold varies greatly 79 // timeout. Even worse, the per-connect timeout threshold varies greatly
80 // between systems (anywhere from 20 seconds to 190 seconds). 80 // between systems (anywhere from 20 seconds to 190 seconds).
81 // See comment #12 at http://crbug.com/23364 for specifics. 81 // See comment #12 at http://crbug.com/23364 for specifics.
82 static const int kTransportConnectJobTimeoutInSeconds = 240; // 4 minutes. 82 static const int kTransportConnectJobTimeoutInSeconds = 240; // 4 minutes.
83 83
84 TransportConnectJobHelper::TransportConnectJobHelper(
85 const scoped_refptr<TransportSocketParams>& params,
86 ClientSocketFactory* client_socket_factory,
87 HostResolver* host_resolver,
88 LoadTimingInfo::ConnectTiming* connect_timing)
89 : params_(params),
90 client_socket_factory_(client_socket_factory),
91 resolver_(host_resolver),
92 next_state_(STATE_NONE),
93 connect_timing_(connect_timing) {}
94
95 TransportConnectJobHelper::~TransportConnectJobHelper() {}
96
97 int TransportConnectJobHelper::DoResolveHost(RequestPriority priority,
98 const BoundNetLog& net_log) {
99 next_state_ = STATE_RESOLVE_HOST_COMPLETE;
100 connect_timing_->dns_start = base::TimeTicks::Now();
101
102 return resolver_.Resolve(
103 params_->destination(), priority, &addresses_, on_io_complete_, net_log);
104 }
105
106 int TransportConnectJobHelper::DoResolveHostComplete(
107 int result,
108 const BoundNetLog& net_log) {
109 connect_timing_->dns_end = base::TimeTicks::Now();
110 // Overwrite connection start time, since for connections that do not go
111 // through proxies, |connect_start| should not include dns lookup time.
112 connect_timing_->connect_start = connect_timing_->dns_end;
113
114 if (result == OK) {
115 // Invoke callback, and abort if it fails.
116 if (!params_->host_resolution_callback().is_null())
117 result = params_->host_resolution_callback().Run(addresses_, net_log);
118
119 if (result == OK)
120 next_state_ = STATE_TRANSPORT_CONNECT;
121 }
122 return result;
123 }
124
125 base::TimeDelta TransportConnectJobHelper::HistogramDuration(
126 ConnectionLatencyHistogram race_result) {
127 DCHECK(!connect_timing_->connect_start.is_null());
128 DCHECK(!connect_timing_->dns_start.is_null());
129 base::TimeTicks now = base::TimeTicks::Now();
130 base::TimeDelta total_duration = now - connect_timing_->dns_start;
131 UMA_HISTOGRAM_CUSTOM_TIMES("Net.DNS_Resolution_And_TCP_Connection_Latency2",
132 total_duration,
133 base::TimeDelta::FromMilliseconds(1),
134 base::TimeDelta::FromMinutes(10),
135 100);
136
137 base::TimeDelta connect_duration = now - connect_timing_->connect_start;
138 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency",
139 connect_duration,
140 base::TimeDelta::FromMilliseconds(1),
141 base::TimeDelta::FromMinutes(10),
142 100);
143
144 switch (race_result) {
145 case CONNECTION_LATENCY_IPV4_WINS_RACE:
146 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_Wins_Race",
147 connect_duration,
148 base::TimeDelta::FromMilliseconds(1),
149 base::TimeDelta::FromMinutes(10),
150 100);
151 break;
152
153 case CONNECTION_LATENCY_IPV4_NO_RACE:
154 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_No_Race",
155 connect_duration,
156 base::TimeDelta::FromMilliseconds(1),
157 base::TimeDelta::FromMinutes(10),
158 100);
159 break;
160
161 case CONNECTION_LATENCY_IPV6_RACEABLE:
162 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Raceable",
163 connect_duration,
164 base::TimeDelta::FromMilliseconds(1),
165 base::TimeDelta::FromMinutes(10),
166 100);
167 break;
168
169 case CONNECTION_LATENCY_IPV6_SOLO:
170 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Solo",
171 connect_duration,
172 base::TimeDelta::FromMilliseconds(1),
173 base::TimeDelta::FromMinutes(10),
174 100);
175 break;
176
177 default:
178 NOTREACHED();
179 break;
180 }
181
182 return connect_duration;
183 }
184
84 TransportConnectJob::TransportConnectJob( 185 TransportConnectJob::TransportConnectJob(
85 const std::string& group_name, 186 const std::string& group_name,
86 RequestPriority priority, 187 RequestPriority priority,
87 const scoped_refptr<TransportSocketParams>& params, 188 const scoped_refptr<TransportSocketParams>& params,
88 base::TimeDelta timeout_duration, 189 base::TimeDelta timeout_duration,
89 ClientSocketFactory* client_socket_factory, 190 ClientSocketFactory* client_socket_factory,
90 HostResolver* host_resolver, 191 HostResolver* host_resolver,
91 Delegate* delegate, 192 Delegate* delegate,
92 NetLog* net_log) 193 NetLog* net_log)
93 : ConnectJob(group_name, timeout_duration, priority, delegate, 194 : ConnectJob(group_name, timeout_duration, priority, delegate,
94 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)), 195 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
95 params_(params), 196 helper_(params, client_socket_factory, host_resolver, &connect_timing_),
96 client_socket_factory_(client_socket_factory),
97 resolver_(host_resolver),
98 next_state_(STATE_NONE),
99 interval_between_connects_(CONNECT_INTERVAL_GT_20MS) { 197 interval_between_connects_(CONNECT_INTERVAL_GT_20MS) {
198 helper_.SetOnIOComplete(this);
100 } 199 }
101 200
102 TransportConnectJob::~TransportConnectJob() { 201 TransportConnectJob::~TransportConnectJob() {
103 // We don't worry about cancelling the host resolution and TCP connect, since 202 // We don't worry about cancelling the host resolution and TCP connect, since
104 // ~SingleRequestHostResolver and ~StreamSocket will take care of it. 203 // ~SingleRequestHostResolver and ~StreamSocket will take care of it.
105 } 204 }
106 205
107 LoadState TransportConnectJob::GetLoadState() const { 206 LoadState TransportConnectJob::GetLoadState() const {
108 switch (next_state_) { 207 switch (helper_.next_state()) {
109 case STATE_RESOLVE_HOST: 208 case TransportConnectJobHelper::STATE_RESOLVE_HOST:
110 case STATE_RESOLVE_HOST_COMPLETE: 209 case TransportConnectJobHelper::STATE_RESOLVE_HOST_COMPLETE:
111 return LOAD_STATE_RESOLVING_HOST; 210 return LOAD_STATE_RESOLVING_HOST;
112 case STATE_TRANSPORT_CONNECT: 211 case TransportConnectJobHelper::STATE_TRANSPORT_CONNECT:
113 case STATE_TRANSPORT_CONNECT_COMPLETE: 212 case TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE:
114 return LOAD_STATE_CONNECTING; 213 return LOAD_STATE_CONNECTING;
115 case STATE_NONE: 214 case TransportConnectJobHelper::STATE_NONE:
116 return LOAD_STATE_IDLE; 215 return LOAD_STATE_IDLE;
117 } 216 }
118 NOTREACHED(); 217 NOTREACHED();
119 return LOAD_STATE_IDLE; 218 return LOAD_STATE_IDLE;
120 } 219 }
121 220
122 // static 221 // static
123 void TransportConnectJob::MakeAddressListStartWithIPv4(AddressList* list) { 222 void TransportConnectJob::MakeAddressListStartWithIPv4(AddressList* list) {
124 for (AddressList::iterator i = list->begin(); i != list->end(); ++i) { 223 for (AddressList::iterator i = list->begin(); i != list->end(); ++i) {
125 if (i->GetFamily() == ADDRESS_FAMILY_IPV4) { 224 if (i->GetFamily() == ADDRESS_FAMILY_IPV4) {
126 std::rotate(list->begin(), i, list->end()); 225 std::rotate(list->begin(), i, list->end());
127 break; 226 break;
128 } 227 }
129 } 228 }
130 } 229 }
131 230
132 void TransportConnectJob::OnIOComplete(int result) {
133 int rv = DoLoop(result);
134 if (rv != ERR_IO_PENDING)
135 NotifyDelegateOfCompletion(rv); // Deletes |this|
136 }
137
138 int TransportConnectJob::DoLoop(int result) {
139 DCHECK_NE(next_state_, STATE_NONE);
140
141 int rv = result;
142 do {
143 State state = next_state_;
144 next_state_ = STATE_NONE;
145 switch (state) {
146 case STATE_RESOLVE_HOST:
147 DCHECK_EQ(OK, rv);
148 rv = DoResolveHost();
149 break;
150 case STATE_RESOLVE_HOST_COMPLETE:
151 rv = DoResolveHostComplete(rv);
152 break;
153 case STATE_TRANSPORT_CONNECT:
154 DCHECK_EQ(OK, rv);
155 rv = DoTransportConnect();
156 break;
157 case STATE_TRANSPORT_CONNECT_COMPLETE:
158 rv = DoTransportConnectComplete(rv);
159 break;
160 default:
161 NOTREACHED();
162 rv = ERR_FAILED;
163 break;
164 }
165 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
166
167 return rv;
168 }
169
170 int TransportConnectJob::DoResolveHost() { 231 int TransportConnectJob::DoResolveHost() {
171 next_state_ = STATE_RESOLVE_HOST_COMPLETE; 232 return helper_.DoResolveHost(priority(), net_log());
172 connect_timing_.dns_start = base::TimeTicks::Now();
173
174 return resolver_.Resolve(
175 params_->destination(),
176 priority(),
177 &addresses_,
178 base::Bind(&TransportConnectJob::OnIOComplete, base::Unretained(this)),
179 net_log());
180 } 233 }
181 234
182 int TransportConnectJob::DoResolveHostComplete(int result) { 235 int TransportConnectJob::DoResolveHostComplete(int result) {
183 connect_timing_.dns_end = base::TimeTicks::Now(); 236 return helper_.DoResolveHostComplete(result, net_log());
184 // Overwrite connection start time, since for connections that do not go
185 // through proxies, |connect_start| should not include dns lookup time.
186 connect_timing_.connect_start = connect_timing_.dns_end;
187
188 if (result == OK) {
189 // Invoke callback, and abort if it fails.
190 if (!params_->host_resolution_callback().is_null())
191 result = params_->host_resolution_callback().Run(addresses_, net_log());
192
193 if (result == OK)
194 next_state_ = STATE_TRANSPORT_CONNECT;
195 }
196 return result;
197 } 237 }
198 238
199 int TransportConnectJob::DoTransportConnect() { 239 int TransportConnectJob::DoTransportConnect() {
200 base::TimeTicks now = base::TimeTicks::Now(); 240 base::TimeTicks now = base::TimeTicks::Now();
201 base::TimeTicks last_connect_time; 241 base::TimeTicks last_connect_time;
202 { 242 {
203 base::AutoLock lock(g_last_connect_time_lock.Get()); 243 base::AutoLock lock(g_last_connect_time_lock.Get());
204 last_connect_time = g_last_connect_time.Get(); 244 last_connect_time = g_last_connect_time.Get();
205 *g_last_connect_time.Pointer() = now; 245 *g_last_connect_time.Pointer() = now;
206 } 246 }
207 if (last_connect_time.is_null()) { 247 if (last_connect_time.is_null()) {
208 interval_between_connects_ = CONNECT_INTERVAL_GT_20MS; 248 interval_between_connects_ = CONNECT_INTERVAL_GT_20MS;
209 } else { 249 } else {
210 int64 interval = (now - last_connect_time).InMilliseconds(); 250 int64 interval = (now - last_connect_time).InMilliseconds();
211 if (interval <= 10) 251 if (interval <= 10)
212 interval_between_connects_ = CONNECT_INTERVAL_LE_10MS; 252 interval_between_connects_ = CONNECT_INTERVAL_LE_10MS;
213 else if (interval <= 20) 253 else if (interval <= 20)
214 interval_between_connects_ = CONNECT_INTERVAL_LE_20MS; 254 interval_between_connects_ = CONNECT_INTERVAL_LE_20MS;
215 else 255 else
216 interval_between_connects_ = CONNECT_INTERVAL_GT_20MS; 256 interval_between_connects_ = CONNECT_INTERVAL_GT_20MS;
217 } 257 }
218 258
219 next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE; 259 helper_.set_next_state(
220 transport_socket_ = client_socket_factory_->CreateTransportClientSocket( 260 TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE);
221 addresses_, net_log().net_log(), net_log().source()); 261 transport_socket_ =
222 int rv = transport_socket_->Connect( 262 helper_.client_socket_factory()->CreateTransportClientSocket(
223 base::Bind(&TransportConnectJob::OnIOComplete, base::Unretained(this))); 263 helper_.addresses(), net_log().net_log(), net_log().source());
264 int rv = transport_socket_->Connect(helper_.on_io_complete());
224 if (rv == ERR_IO_PENDING && 265 if (rv == ERR_IO_PENDING &&
225 addresses_.front().GetFamily() == ADDRESS_FAMILY_IPV6 && 266 helper_.addresses().front().GetFamily() == ADDRESS_FAMILY_IPV6 &&
226 !AddressListOnlyContainsIPv6(addresses_)) { 267 !AddressListOnlyContainsIPv6(helper_.addresses())) {
227 fallback_timer_.Start(FROM_HERE, 268 fallback_timer_.Start(
228 base::TimeDelta::FromMilliseconds(kIPv6FallbackTimerInMs), 269 FROM_HERE,
229 this, &TransportConnectJob::DoIPv6FallbackTransportConnect); 270 base::TimeDelta::FromMilliseconds(
271 TransportConnectJobHelper::kIPv6FallbackTimerInMs),
272 this,
273 &TransportConnectJob::DoIPv6FallbackTransportConnect);
230 } 274 }
231 return rv; 275 return rv;
232 } 276 }
233 277
234 int TransportConnectJob::DoTransportConnectComplete(int result) { 278 int TransportConnectJob::DoTransportConnectComplete(int result) {
235 if (result == OK) { 279 if (result == OK) {
236 bool is_ipv4 = addresses_.front().GetFamily() == ADDRESS_FAMILY_IPV4; 280 bool is_ipv4 =
237 DCHECK(!connect_timing_.connect_start.is_null()); 281 helper_.addresses().front().GetFamily() == ADDRESS_FAMILY_IPV4;
238 DCHECK(!connect_timing_.dns_start.is_null()); 282 TransportConnectJobHelper::ConnectionLatencyHistogram race_result =
239 base::TimeTicks now = base::TimeTicks::Now(); 283 TransportConnectJobHelper::CONNECTION_LATENCY_UNKNOWN;
240 base::TimeDelta total_duration = now - connect_timing_.dns_start; 284 if (is_ipv4) {
241 UMA_HISTOGRAM_CUSTOM_TIMES( 285 race_result = TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_NO_RACE;
242 "Net.DNS_Resolution_And_TCP_Connection_Latency2", 286 } else {
243 total_duration, 287 if (AddressListOnlyContainsIPv6(helper_.addresses())) {
244 base::TimeDelta::FromMilliseconds(1), 288 race_result = TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_SOLO;
245 base::TimeDelta::FromMinutes(10), 289 } else {
246 100); 290 race_result =
247 291 TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_RACEABLE;
248 base::TimeDelta connect_duration = now - connect_timing_.connect_start; 292 }
249 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency", 293 }
250 connect_duration, 294 base::TimeDelta connect_duration = helper_.HistogramDuration(race_result);
251 base::TimeDelta::FromMilliseconds(1),
252 base::TimeDelta::FromMinutes(10),
253 100);
254
255 switch (interval_between_connects_) { 295 switch (interval_between_connects_) {
256 case CONNECT_INTERVAL_LE_10MS: 296 case CONNECT_INTERVAL_LE_10MS:
257 UMA_HISTOGRAM_CUSTOM_TIMES( 297 UMA_HISTOGRAM_CUSTOM_TIMES(
258 "Net.TCP_Connection_Latency_Interval_LessThanOrEqual_10ms", 298 "Net.TCP_Connection_Latency_Interval_LessThanOrEqual_10ms",
259 connect_duration, 299 connect_duration,
260 base::TimeDelta::FromMilliseconds(1), 300 base::TimeDelta::FromMilliseconds(1),
261 base::TimeDelta::FromMinutes(10), 301 base::TimeDelta::FromMinutes(10),
262 100); 302 100);
263 break; 303 break;
264 case CONNECT_INTERVAL_LE_20MS: 304 case CONNECT_INTERVAL_LE_20MS:
(...skipping 10 matching lines...) Expand all
275 connect_duration, 315 connect_duration,
276 base::TimeDelta::FromMilliseconds(1), 316 base::TimeDelta::FromMilliseconds(1),
277 base::TimeDelta::FromMinutes(10), 317 base::TimeDelta::FromMinutes(10),
278 100); 318 100);
279 break; 319 break;
280 default: 320 default:
281 NOTREACHED(); 321 NOTREACHED();
282 break; 322 break;
283 } 323 }
284 324
285 if (is_ipv4) {
286 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_No_Race",
287 connect_duration,
288 base::TimeDelta::FromMilliseconds(1),
289 base::TimeDelta::FromMinutes(10),
290 100);
291 } else {
292 if (AddressListOnlyContainsIPv6(addresses_)) {
293 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Solo",
294 connect_duration,
295 base::TimeDelta::FromMilliseconds(1),
296 base::TimeDelta::FromMinutes(10),
297 100);
298 } else {
299 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Raceable",
300 connect_duration,
301 base::TimeDelta::FromMilliseconds(1),
302 base::TimeDelta::FromMinutes(10),
303 100);
304 }
305 }
306 SetSocket(transport_socket_.Pass()); 325 SetSocket(transport_socket_.Pass());
307 fallback_timer_.Stop(); 326 fallback_timer_.Stop();
308 } else { 327 } else {
309 // Be a bit paranoid and kill off the fallback members to prevent reuse. 328 // Be a bit paranoid and kill off the fallback members to prevent reuse.
310 fallback_transport_socket_.reset(); 329 fallback_transport_socket_.reset();
311 fallback_addresses_.reset(); 330 fallback_addresses_.reset();
312 } 331 }
313 332
314 return result; 333 return result;
315 } 334 }
316 335
317 void TransportConnectJob::DoIPv6FallbackTransportConnect() { 336 void TransportConnectJob::DoIPv6FallbackTransportConnect() {
318 // The timer should only fire while we're waiting for the main connect to 337 // The timer should only fire while we're waiting for the main connect to
319 // succeed. 338 // succeed.
320 if (next_state_ != STATE_TRANSPORT_CONNECT_COMPLETE) { 339 if (helper_.next_state() !=
340 TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE) {
321 NOTREACHED(); 341 NOTREACHED();
322 return; 342 return;
323 } 343 }
324 344
325 DCHECK(!fallback_transport_socket_.get()); 345 DCHECK(!fallback_transport_socket_.get());
326 DCHECK(!fallback_addresses_.get()); 346 DCHECK(!fallback_addresses_.get());
327 347
328 fallback_addresses_.reset(new AddressList(addresses_)); 348 fallback_addresses_.reset(new AddressList(helper_.addresses()));
329 MakeAddressListStartWithIPv4(fallback_addresses_.get()); 349 MakeAddressListStartWithIPv4(fallback_addresses_.get());
330 fallback_transport_socket_ = 350 fallback_transport_socket_ =
331 client_socket_factory_->CreateTransportClientSocket( 351 helper_.client_socket_factory()->CreateTransportClientSocket(
332 *fallback_addresses_, net_log().net_log(), net_log().source()); 352 *fallback_addresses_, net_log().net_log(), net_log().source());
333 fallback_connect_start_time_ = base::TimeTicks::Now(); 353 fallback_connect_start_time_ = base::TimeTicks::Now();
334 int rv = fallback_transport_socket_->Connect( 354 int rv = fallback_transport_socket_->Connect(
335 base::Bind( 355 base::Bind(
336 &TransportConnectJob::DoIPv6FallbackTransportConnectComplete, 356 &TransportConnectJob::DoIPv6FallbackTransportConnectComplete,
337 base::Unretained(this))); 357 base::Unretained(this)));
338 if (rv != ERR_IO_PENDING) 358 if (rv != ERR_IO_PENDING)
339 DoIPv6FallbackTransportConnectComplete(rv); 359 DoIPv6FallbackTransportConnectComplete(rv);
340 } 360 }
341 361
342 void TransportConnectJob::DoIPv6FallbackTransportConnectComplete(int result) { 362 void TransportConnectJob::DoIPv6FallbackTransportConnectComplete(int result) {
343 // This should only happen when we're waiting for the main connect to succeed. 363 // This should only happen when we're waiting for the main connect to succeed.
344 if (next_state_ != STATE_TRANSPORT_CONNECT_COMPLETE) { 364 if (helper_.next_state() !=
365 TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE) {
345 NOTREACHED(); 366 NOTREACHED();
346 return; 367 return;
347 } 368 }
348 369
349 DCHECK_NE(ERR_IO_PENDING, result); 370 DCHECK_NE(ERR_IO_PENDING, result);
350 DCHECK(fallback_transport_socket_.get()); 371 DCHECK(fallback_transport_socket_.get());
351 DCHECK(fallback_addresses_.get()); 372 DCHECK(fallback_addresses_.get());
352 373
353 if (result == OK) { 374 if (result == OK) {
354 DCHECK(!fallback_connect_start_time_.is_null()); 375 DCHECK(!fallback_connect_start_time_.is_null());
355 DCHECK(!connect_timing_.dns_start.is_null()); 376 connect_timing_.connect_start = fallback_connect_start_time_;
356 base::TimeTicks now = base::TimeTicks::Now(); 377 helper_.HistogramDuration(
357 base::TimeDelta total_duration = now - connect_timing_.dns_start; 378 TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_WINS_RACE);
358 UMA_HISTOGRAM_CUSTOM_TIMES(
359 "Net.DNS_Resolution_And_TCP_Connection_Latency2",
360 total_duration,
361 base::TimeDelta::FromMilliseconds(1),
362 base::TimeDelta::FromMinutes(10),
363 100);
364
365 base::TimeDelta connect_duration = now - fallback_connect_start_time_;
366 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency",
367 connect_duration,
368 base::TimeDelta::FromMilliseconds(1),
369 base::TimeDelta::FromMinutes(10),
370 100);
371
372 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_Wins_Race",
373 connect_duration,
374 base::TimeDelta::FromMilliseconds(1),
375 base::TimeDelta::FromMinutes(10),
376 100);
377 SetSocket(fallback_transport_socket_.Pass()); 379 SetSocket(fallback_transport_socket_.Pass());
378 next_state_ = STATE_NONE; 380 helper_.set_next_state(TransportConnectJobHelper::STATE_NONE);
379 transport_socket_.reset(); 381 transport_socket_.reset();
380 } else { 382 } else {
381 // Be a bit paranoid and kill off the fallback members to prevent reuse. 383 // Be a bit paranoid and kill off the fallback members to prevent reuse.
382 fallback_transport_socket_.reset(); 384 fallback_transport_socket_.reset();
383 fallback_addresses_.reset(); 385 fallback_addresses_.reset();
384 } 386 }
385 NotifyDelegateOfCompletion(result); // Deletes |this| 387 NotifyDelegateOfCompletion(result); // Deletes |this|
386 } 388 }
387 389
388 int TransportConnectJob::ConnectInternal() { 390 int TransportConnectJob::ConnectInternal() {
389 next_state_ = STATE_RESOLVE_HOST; 391 return helper_.DoConnectInternal(this);
390 return DoLoop(OK);
391 } 392 }
392 393
393 scoped_ptr<ConnectJob> 394 scoped_ptr<ConnectJob>
394 TransportClientSocketPool::TransportConnectJobFactory::NewConnectJob( 395 TransportClientSocketPool::TransportConnectJobFactory::NewConnectJob(
395 const std::string& group_name, 396 const std::string& group_name,
396 const PoolBase::Request& request, 397 const PoolBase::Request& request,
397 ConnectJob::Delegate* delegate) const { 398 ConnectJob::Delegate* delegate) const {
398 return scoped_ptr<ConnectJob>( 399 return scoped_ptr<ConnectJob>(
399 new TransportConnectJob(group_name, 400 new TransportConnectJob(group_name,
400 request.priority(), 401 request.priority(),
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 int TransportClientSocketPool::RequestSocket( 433 int TransportClientSocketPool::RequestSocket(
433 const std::string& group_name, 434 const std::string& group_name,
434 const void* params, 435 const void* params,
435 RequestPriority priority, 436 RequestPriority priority,
436 ClientSocketHandle* handle, 437 ClientSocketHandle* handle,
437 const CompletionCallback& callback, 438 const CompletionCallback& callback,
438 const BoundNetLog& net_log) { 439 const BoundNetLog& net_log) {
439 const scoped_refptr<TransportSocketParams>* casted_params = 440 const scoped_refptr<TransportSocketParams>* casted_params =
440 static_cast<const scoped_refptr<TransportSocketParams>*>(params); 441 static_cast<const scoped_refptr<TransportSocketParams>*>(params);
441 442
443 NetLogTcpClientSocketPoolRequestedSocket(net_log, casted_params);
444
445 return base_.RequestSocket(group_name, *casted_params, priority, handle,
446 callback, net_log);
447 }
448
449 void TransportClientSocketPool::NetLogTcpClientSocketPoolRequestedSocket(
450 const BoundNetLog& net_log,
451 const scoped_refptr<TransportSocketParams>* casted_params) {
442 if (net_log.IsLogging()) { 452 if (net_log.IsLogging()) {
443 // TODO(eroman): Split out the host and port parameters. 453 // TODO(eroman): Split out the host and port parameters.
444 net_log.AddEvent( 454 net_log.AddEvent(
445 NetLog::TYPE_TCP_CLIENT_SOCKET_POOL_REQUESTED_SOCKET, 455 NetLog::TYPE_TCP_CLIENT_SOCKET_POOL_REQUESTED_SOCKET,
446 CreateNetLogHostPortPairCallback( 456 CreateNetLogHostPortPairCallback(
447 &casted_params->get()->destination().host_port_pair())); 457 &casted_params->get()->destination().host_port_pair()));
448 } 458 }
449
450 return base_.RequestSocket(group_name, *casted_params, priority, handle,
451 callback, net_log);
452 } 459 }
453 460
454 void TransportClientSocketPool::RequestSockets( 461 void TransportClientSocketPool::RequestSockets(
455 const std::string& group_name, 462 const std::string& group_name,
456 const void* params, 463 const void* params,
457 int num_sockets, 464 int num_sockets,
458 const BoundNetLog& net_log) { 465 const BoundNetLog& net_log) {
459 const scoped_refptr<TransportSocketParams>* casted_params = 466 const scoped_refptr<TransportSocketParams>* casted_params =
460 static_cast<const scoped_refptr<TransportSocketParams>*>(params); 467 static_cast<const scoped_refptr<TransportSocketParams>*>(params);
461 468
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 HigherLayeredPool* higher_pool) { 535 HigherLayeredPool* higher_pool) {
529 base_.AddHigherLayeredPool(higher_pool); 536 base_.AddHigherLayeredPool(higher_pool);
530 } 537 }
531 538
532 void TransportClientSocketPool::RemoveHigherLayeredPool( 539 void TransportClientSocketPool::RemoveHigherLayeredPool(
533 HigherLayeredPool* higher_pool) { 540 HigherLayeredPool* higher_pool) {
534 base_.RemoveHigherLayeredPool(higher_pool); 541 base_.RemoveHigherLayeredPool(higher_pool);
535 } 542 }
536 543
537 } // namespace net 544 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698