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

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

Issue 1096203006: Collect all ConnectionAttempts from both sockets in TransportConnectJob. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@domrel_serverip1
Patch Set: Return fake ConnectionAttempt in MockTCPClientSocket Created 5 years, 7 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 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 HostResolver* host_resolver, 201 HostResolver* host_resolver,
202 Delegate* delegate, 202 Delegate* delegate,
203 NetLog* net_log) 203 NetLog* net_log)
204 : ConnectJob(group_name, 204 : ConnectJob(group_name,
205 timeout_duration, 205 timeout_duration,
206 priority, 206 priority,
207 delegate, 207 delegate,
208 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)), 208 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
209 helper_(params, client_socket_factory, host_resolver, &connect_timing_), 209 helper_(params, client_socket_factory, host_resolver, &connect_timing_),
210 interval_between_connects_(CONNECT_INTERVAL_GT_20MS), 210 interval_between_connects_(CONNECT_INTERVAL_GT_20MS),
211 resolve_result_(OK), 211 resolve_result_(OK) {
212 connect_result_(OK) {
213 helper_.SetOnIOComplete(this); 212 helper_.SetOnIOComplete(this);
214 } 213 }
215 214
216 TransportConnectJob::~TransportConnectJob() { 215 TransportConnectJob::~TransportConnectJob() {
217 // We don't worry about cancelling the host resolution and TCP connect, since 216 // We don't worry about cancelling the host resolution and TCP connect, since
218 // ~SingleRequestHostResolver and ~StreamSocket will take care of it. 217 // ~SingleRequestHostResolver and ~StreamSocket will take care of it.
219 } 218 }
220 219
221 LoadState TransportConnectJob::GetLoadState() const { 220 LoadState TransportConnectJob::GetLoadState() const {
222 switch (helper_.next_state()) { 221 switch (helper_.next_state()) {
223 case TransportConnectJobHelper::STATE_RESOLVE_HOST: 222 case TransportConnectJobHelper::STATE_RESOLVE_HOST:
224 case TransportConnectJobHelper::STATE_RESOLVE_HOST_COMPLETE: 223 case TransportConnectJobHelper::STATE_RESOLVE_HOST_COMPLETE:
225 return LOAD_STATE_RESOLVING_HOST; 224 return LOAD_STATE_RESOLVING_HOST;
226 case TransportConnectJobHelper::STATE_TRANSPORT_CONNECT: 225 case TransportConnectJobHelper::STATE_TRANSPORT_CONNECT:
227 case TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE: 226 case TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE:
228 return LOAD_STATE_CONNECTING; 227 return LOAD_STATE_CONNECTING;
229 case TransportConnectJobHelper::STATE_NONE: 228 case TransportConnectJobHelper::STATE_NONE:
230 return LOAD_STATE_IDLE; 229 return LOAD_STATE_IDLE;
231 } 230 }
232 NOTREACHED(); 231 NOTREACHED();
233 return LOAD_STATE_IDLE; 232 return LOAD_STATE_IDLE;
234 } 233 }
235 234
236 void TransportConnectJob::GetAdditionalErrorState(ClientSocketHandle* handle) { 235 void TransportConnectJob::GetAdditionalErrorState(ClientSocketHandle* handle) {
237 // If hostname resolution failed, record an empty endpoint and the result. 236 // If hostname resolution failed, record an empty endpoint and the result.
238 // If the actual socket Connect call failed, record the result and the last 237 // Also record any attempts made on either of the sockets.
239 // address attempted.
240 // TODO(ttuttle): Plumb into the socket layer and record *all* attempts.
241 ConnectionAttempts attempts; 238 ConnectionAttempts attempts;
242 if (resolve_result_ != OK) { 239 if (resolve_result_ != OK) {
243 DCHECK_EQ(0u, helper_.addresses().size()); 240 DCHECK_EQ(0u, helper_.addresses().size());
244 attempts.push_back(ConnectionAttempt(IPEndPoint(), resolve_result_)); 241 attempts.push_back(ConnectionAttempt(IPEndPoint(), resolve_result_));
245 } else if (connect_result_ != OK) {
246 DCHECK_LT(0u, helper_.addresses().size());
247 attempts.push_back(
248 ConnectionAttempt(helper_.addresses().back(), connect_result_));
249 } 242 }
243 attempts.insert(attempts.begin(), connection_attempts_.begin(),
244 connection_attempts_.end());
245 attempts.insert(attempts.begin(), fallback_connection_attempts_.begin(),
246 fallback_connection_attempts_.end());
250 handle->set_connection_attempts(attempts); 247 handle->set_connection_attempts(attempts);
251 } 248 }
252 249
253 // static 250 // static
254 void TransportConnectJob::MakeAddressListStartWithIPv4(AddressList* list) { 251 void TransportConnectJob::MakeAddressListStartWithIPv4(AddressList* list) {
255 for (AddressList::iterator i = list->begin(); i != list->end(); ++i) { 252 for (AddressList::iterator i = list->begin(); i != list->end(); ++i) {
256 if (i->GetFamily() == ADDRESS_FAMILY_IPV4) { 253 if (i->GetFamily() == ADDRESS_FAMILY_IPV4) {
257 std::rotate(list->begin(), i, list->end()); 254 std::rotate(list->begin(), i, list->end());
258 break; 255 break;
259 } 256 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 base::TimeDelta::FromMilliseconds( 320 base::TimeDelta::FromMilliseconds(
324 TransportConnectJobHelper::kIPv6FallbackTimerInMs), 321 TransportConnectJobHelper::kIPv6FallbackTimerInMs),
325 this, 322 this,
326 &TransportConnectJob::DoIPv6FallbackTransportConnect); 323 &TransportConnectJob::DoIPv6FallbackTransportConnect);
327 } 324 }
328 return rv; 325 return rv;
329 } 326 }
330 327
331 int TransportConnectJob::DoTransportConnectComplete(int result) { 328 int TransportConnectJob::DoTransportConnectComplete(int result) {
332 if (result == OK) { 329 if (result == OK) {
330 // Success will be returned via the main socket, so also include connection
331 // attempts made on the fallback socket up to this point. (Unfortunately,
332 // the only simple way to return information in the success case is through
333 // the successfully-connected socket.)
334 if (fallback_transport_socket_) {
335 ConnectionAttempts fallback_attempts;
336 fallback_transport_socket_->GetConnectionAttempts(&fallback_attempts);
337 transport_socket_->AddConnectionAttempts(fallback_attempts);
338 }
339
333 bool is_ipv4 = 340 bool is_ipv4 =
334 helper_.addresses().front().GetFamily() == ADDRESS_FAMILY_IPV4; 341 helper_.addresses().front().GetFamily() == ADDRESS_FAMILY_IPV4;
335 TransportConnectJobHelper::ConnectionLatencyHistogram race_result = 342 TransportConnectJobHelper::ConnectionLatencyHistogram race_result =
336 TransportConnectJobHelper::CONNECTION_LATENCY_UNKNOWN; 343 TransportConnectJobHelper::CONNECTION_LATENCY_UNKNOWN;
337 if (is_ipv4) { 344 if (is_ipv4) {
338 race_result = TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_NO_RACE; 345 race_result = TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_NO_RACE;
339 } else { 346 } else {
340 if (AddressListOnlyContainsIPv6(helper_.addresses())) { 347 if (AddressListOnlyContainsIPv6(helper_.addresses())) {
341 race_result = TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_SOLO; 348 race_result = TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_SOLO;
342 } else { 349 } else {
(...skipping 28 matching lines...) Expand all
371 100); 378 100);
372 break; 379 break;
373 default: 380 default:
374 NOTREACHED(); 381 NOTREACHED();
375 break; 382 break;
376 } 383 }
377 384
378 SetSocket(transport_socket_.Pass()); 385 SetSocket(transport_socket_.Pass());
379 fallback_timer_.Stop(); 386 fallback_timer_.Stop();
380 } else { 387 } else {
388 // Failure will be returned via |GetAdditionalErrorState|, so save
389 // connection attempts from both sockets for use there.
390 CopyConnectionAttemptsFromSockets();
391
381 // Be a bit paranoid and kill off the fallback members to prevent reuse. 392 // Be a bit paranoid and kill off the fallback members to prevent reuse.
382 fallback_transport_socket_.reset(); 393 fallback_transport_socket_.reset();
383 fallback_addresses_.reset(); 394 fallback_addresses_.reset();
384 } 395 }
385 396
386 connect_result_ = result; 397 // N.B.: The owner of the ConnectJob will delete it after the callback is
398 // called, so the fallback socket, if any, won't stick around for long.
387 399
388 return result; 400 return result;
389 } 401 }
390 402
391 void TransportConnectJob::DoIPv6FallbackTransportConnect() { 403 void TransportConnectJob::DoIPv6FallbackTransportConnect() {
392 // The timer should only fire while we're waiting for the main connect to 404 // The timer should only fire while we're waiting for the main connect to
393 // succeed. 405 // succeed.
394 if (helper_.next_state() != 406 if (helper_.next_state() !=
395 TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE) { 407 TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE) {
396 NOTREACHED(); 408 NOTREACHED();
(...skipping 24 matching lines...) Expand all
421 NOTREACHED(); 433 NOTREACHED();
422 return; 434 return;
423 } 435 }
424 436
425 DCHECK_NE(ERR_IO_PENDING, result); 437 DCHECK_NE(ERR_IO_PENDING, result);
426 DCHECK(fallback_transport_socket_.get()); 438 DCHECK(fallback_transport_socket_.get());
427 DCHECK(fallback_addresses_.get()); 439 DCHECK(fallback_addresses_.get());
428 440
429 if (result == OK) { 441 if (result == OK) {
430 DCHECK(!fallback_connect_start_time_.is_null()); 442 DCHECK(!fallback_connect_start_time_.is_null());
443
444 // Success will be returned via the fallback socket, so also include
445 // connection attempts made on the main socket up to this point.
446 // (Unfortunately, the only simple way to return information in the success
447 // case is through the successfully-connected socket.)
448 if (transport_socket_) {
449 ConnectionAttempts attempts;
450 transport_socket_->GetConnectionAttempts(&attempts);
451 fallback_transport_socket_->AddConnectionAttempts(attempts);
452 }
453
431 connect_timing_.connect_start = fallback_connect_start_time_; 454 connect_timing_.connect_start = fallback_connect_start_time_;
432 helper_.HistogramDuration( 455 helper_.HistogramDuration(
433 TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_WINS_RACE); 456 TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_WINS_RACE);
434 SetSocket(fallback_transport_socket_.Pass()); 457 SetSocket(fallback_transport_socket_.Pass());
435 helper_.set_next_state(TransportConnectJobHelper::STATE_NONE); 458 helper_.set_next_state(TransportConnectJobHelper::STATE_NONE);
436 transport_socket_.reset(); 459 transport_socket_.reset();
437 } else { 460 } else {
461 // Failure will be returned via |GetAdditionalErrorState|, so save
462 // connection attempts from both sockets for use there.
463 CopyConnectionAttemptsFromSockets();
464
438 // Be a bit paranoid and kill off the fallback members to prevent reuse. 465 // Be a bit paranoid and kill off the fallback members to prevent reuse.
439 fallback_transport_socket_.reset(); 466 fallback_transport_socket_.reset();
440 fallback_addresses_.reset(); 467 fallback_addresses_.reset();
441 } 468 }
469
470 // N.B.: The owner of the ConnectJob will delete it after the callback is
471 // called, so the main socket, if any, won't stick around for long.
472
442 NotifyDelegateOfCompletion(result); // Deletes |this| 473 NotifyDelegateOfCompletion(result); // Deletes |this|
443 } 474 }
444 475
445 int TransportConnectJob::ConnectInternal() { 476 int TransportConnectJob::ConnectInternal() {
446 return helper_.DoConnectInternal(this); 477 return helper_.DoConnectInternal(this);
447 } 478 }
448 479
480 void TransportConnectJob::CopyConnectionAttemptsFromSockets() {
481 if (transport_socket_)
482 transport_socket_->GetConnectionAttempts(&connection_attempts_);
483 if (fallback_transport_socket_) {
484 fallback_transport_socket_->GetConnectionAttempts(
485 &fallback_connection_attempts_);
486 }
487 }
488
449 scoped_ptr<ConnectJob> 489 scoped_ptr<ConnectJob>
450 TransportClientSocketPool::TransportConnectJobFactory::NewConnectJob( 490 TransportClientSocketPool::TransportConnectJobFactory::NewConnectJob(
451 const std::string& group_name, 491 const std::string& group_name,
452 const PoolBase::Request& request, 492 const PoolBase::Request& request,
453 ConnectJob::Delegate* delegate) const { 493 ConnectJob::Delegate* delegate) const {
454 return scoped_ptr<ConnectJob>( 494 return scoped_ptr<ConnectJob>(
455 new TransportConnectJob(group_name, 495 new TransportConnectJob(group_name,
456 request.priority(), 496 request.priority(),
457 request.params(), 497 request.params(),
458 ConnectionTimeout(), 498 ConnectionTimeout(),
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 HigherLayeredPool* higher_pool) { 628 HigherLayeredPool* higher_pool) {
589 base_.AddHigherLayeredPool(higher_pool); 629 base_.AddHigherLayeredPool(higher_pool);
590 } 630 }
591 631
592 void TransportClientSocketPool::RemoveHigherLayeredPool( 632 void TransportClientSocketPool::RemoveHigherLayeredPool(
593 HigherLayeredPool* higher_pool) { 633 HigherLayeredPool* higher_pool) {
594 base_.RemoveHigherLayeredPool(higher_pool); 634 base_.RemoveHigherLayeredPool(higher_pool);
595 } 635 }
596 636
597 } // namespace net 637 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/transport_client_socket_pool.h ('k') | net/socket/transport_client_socket_pool_test_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698