Index: net/socket/transport_client_socket_pool.cc |
diff --git a/net/socket/transport_client_socket_pool.cc b/net/socket/transport_client_socket_pool.cc |
index dc481fa4b6d6004afcc102923a9c3194f91b8940..cf247c032706793693d28b4ee8ba91848d140bff 100644 |
--- a/net/socket/transport_client_socket_pool.cc |
+++ b/net/socket/transport_client_socket_pool.cc |
@@ -31,7 +31,7 @@ namespace net { |
// TODO(willchan): Base this off RTT instead of statically setting it. Note we |
// choose a timeout that is different from the backup connect job timer so they |
// don't synchronize. |
-const int TransportConnectJob::kIPv6FallbackTimerInMs = 300; |
+const int TransportConnectJobHelper::kIPv6FallbackTimerInMs = 300; |
namespace { |
@@ -81,6 +81,107 @@ TransportSocketParams::~TransportSocketParams() {} |
// See comment #12 at http://crbug.com/23364 for specifics. |
static const int kTransportConnectJobTimeoutInSeconds = 240; // 4 minutes. |
+TransportConnectJobHelper::TransportConnectJobHelper( |
+ const scoped_refptr<TransportSocketParams>& params, |
+ ClientSocketFactory* client_socket_factory, |
+ HostResolver* host_resolver, |
+ LoadTimingInfo::ConnectTiming* connect_timing) |
+ : params_(params), |
+ client_socket_factory_(client_socket_factory), |
+ resolver_(host_resolver), |
+ next_state_(STATE_NONE), |
+ connect_timing_(connect_timing) {} |
+ |
+TransportConnectJobHelper::~TransportConnectJobHelper() {} |
+ |
+int TransportConnectJobHelper::DoResolveHost(RequestPriority priority, |
+ const BoundNetLog& net_log) { |
+ next_state_ = STATE_RESOLVE_HOST_COMPLETE; |
+ connect_timing_->dns_start = base::TimeTicks::Now(); |
+ |
+ return resolver_.Resolve( |
+ params_->destination(), priority, &addresses_, on_io_complete_, net_log); |
+} |
+ |
+int TransportConnectJobHelper::DoResolveHostComplete( |
+ int result, |
+ const BoundNetLog& net_log) { |
+ connect_timing_->dns_end = base::TimeTicks::Now(); |
+ // Overwrite connection start time, since for connections that do not go |
+ // through proxies, |connect_start| should not include dns lookup time. |
+ connect_timing_->connect_start = connect_timing_->dns_end; |
+ |
+ if (result == OK) { |
+ // Invoke callback, and abort if it fails. |
+ if (!params_->host_resolution_callback().is_null()) |
+ result = params_->host_resolution_callback().Run(addresses_, net_log); |
+ |
+ if (result == OK) |
+ next_state_ = STATE_TRANSPORT_CONNECT; |
+ } |
+ return result; |
+} |
+ |
+base::TimeDelta TransportConnectJobHelper::HistogramDuration( |
+ ConnectionLatencyHistogram race_result) { |
+ DCHECK(!connect_timing_->connect_start.is_null()); |
+ DCHECK(!connect_timing_->dns_start.is_null()); |
+ base::TimeTicks now = base::TimeTicks::Now(); |
+ base::TimeDelta total_duration = now - connect_timing_->dns_start; |
+ UMA_HISTOGRAM_CUSTOM_TIMES("Net.DNS_Resolution_And_TCP_Connection_Latency2", |
+ total_duration, |
+ base::TimeDelta::FromMilliseconds(1), |
+ base::TimeDelta::FromMinutes(10), |
+ 100); |
+ |
+ base::TimeDelta connect_duration = now - connect_timing_->connect_start; |
+ UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency", |
+ connect_duration, |
+ base::TimeDelta::FromMilliseconds(1), |
+ base::TimeDelta::FromMinutes(10), |
+ 100); |
+ |
+ switch (race_result) { |
+ case CONNECTION_LATENCY_IPV4_WINS_RACE: |
+ UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_Wins_Race", |
+ connect_duration, |
+ base::TimeDelta::FromMilliseconds(1), |
+ base::TimeDelta::FromMinutes(10), |
+ 100); |
+ break; |
+ |
+ case CONNECTION_LATENCY_IPV4_NO_RACE: |
+ UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_No_Race", |
+ connect_duration, |
+ base::TimeDelta::FromMilliseconds(1), |
+ base::TimeDelta::FromMinutes(10), |
+ 100); |
+ break; |
+ |
+ case CONNECTION_LATENCY_IPV6_RACEABLE: |
+ UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Raceable", |
+ connect_duration, |
+ base::TimeDelta::FromMilliseconds(1), |
+ base::TimeDelta::FromMinutes(10), |
+ 100); |
+ break; |
+ |
+ case CONNECTION_LATENCY_IPV6_SOLO: |
+ UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Solo", |
+ connect_duration, |
+ base::TimeDelta::FromMilliseconds(1), |
+ base::TimeDelta::FromMinutes(10), |
+ 100); |
+ break; |
+ |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+ |
+ return connect_duration; |
+} |
+ |
TransportConnectJob::TransportConnectJob( |
const std::string& group_name, |
RequestPriority priority, |
@@ -92,11 +193,9 @@ TransportConnectJob::TransportConnectJob( |
NetLog* net_log) |
: ConnectJob(group_name, timeout_duration, priority, delegate, |
BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)), |
- params_(params), |
- client_socket_factory_(client_socket_factory), |
- resolver_(host_resolver), |
- next_state_(STATE_NONE), |
+ helper_(params, client_socket_factory, host_resolver, &connect_timing_), |
interval_between_connects_(CONNECT_INTERVAL_GT_20MS) { |
+ helper_.SetOnIOComplete(this); |
} |
TransportConnectJob::~TransportConnectJob() { |
@@ -105,14 +204,14 @@ TransportConnectJob::~TransportConnectJob() { |
} |
LoadState TransportConnectJob::GetLoadState() const { |
- switch (next_state_) { |
- case STATE_RESOLVE_HOST: |
- case STATE_RESOLVE_HOST_COMPLETE: |
+ switch (helper_.next_state()) { |
+ case TransportConnectJobHelper::STATE_RESOLVE_HOST: |
+ case TransportConnectJobHelper::STATE_RESOLVE_HOST_COMPLETE: |
return LOAD_STATE_RESOLVING_HOST; |
- case STATE_TRANSPORT_CONNECT: |
- case STATE_TRANSPORT_CONNECT_COMPLETE: |
+ case TransportConnectJobHelper::STATE_TRANSPORT_CONNECT: |
+ case TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE: |
return LOAD_STATE_CONNECTING; |
- case STATE_NONE: |
+ case TransportConnectJobHelper::STATE_NONE: |
return LOAD_STATE_IDLE; |
} |
NOTREACHED(); |
@@ -129,71 +228,12 @@ void TransportConnectJob::MakeAddressListStartWithIPv4(AddressList* list) { |
} |
} |
-void TransportConnectJob::OnIOComplete(int result) { |
- int rv = DoLoop(result); |
- if (rv != ERR_IO_PENDING) |
- NotifyDelegateOfCompletion(rv); // Deletes |this| |
-} |
- |
-int TransportConnectJob::DoLoop(int result) { |
- DCHECK_NE(next_state_, STATE_NONE); |
- |
- int rv = result; |
- do { |
- State state = next_state_; |
- next_state_ = STATE_NONE; |
- switch (state) { |
- case STATE_RESOLVE_HOST: |
- DCHECK_EQ(OK, rv); |
- rv = DoResolveHost(); |
- break; |
- case STATE_RESOLVE_HOST_COMPLETE: |
- rv = DoResolveHostComplete(rv); |
- break; |
- case STATE_TRANSPORT_CONNECT: |
- DCHECK_EQ(OK, rv); |
- rv = DoTransportConnect(); |
- break; |
- case STATE_TRANSPORT_CONNECT_COMPLETE: |
- rv = DoTransportConnectComplete(rv); |
- break; |
- default: |
- NOTREACHED(); |
- rv = ERR_FAILED; |
- break; |
- } |
- } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
- |
- return rv; |
-} |
- |
int TransportConnectJob::DoResolveHost() { |
- next_state_ = STATE_RESOLVE_HOST_COMPLETE; |
- connect_timing_.dns_start = base::TimeTicks::Now(); |
- |
- return resolver_.Resolve( |
- params_->destination(), |
- priority(), |
- &addresses_, |
- base::Bind(&TransportConnectJob::OnIOComplete, base::Unretained(this)), |
- net_log()); |
+ return helper_.DoResolveHost(priority(), net_log()); |
} |
int TransportConnectJob::DoResolveHostComplete(int result) { |
- connect_timing_.dns_end = base::TimeTicks::Now(); |
- // Overwrite connection start time, since for connections that do not go |
- // through proxies, |connect_start| should not include dns lookup time. |
- connect_timing_.connect_start = connect_timing_.dns_end; |
- |
- if (result == OK) { |
- // Invoke callback, and abort if it fails. |
- if (!params_->host_resolution_callback().is_null()) |
- result = params_->host_resolution_callback().Run(addresses_, net_log()); |
- |
- if (result == OK) |
- next_state_ = STATE_TRANSPORT_CONNECT; |
- } |
- return result; |
+ return helper_.DoResolveHostComplete(result, net_log()); |
} |
int TransportConnectJob::DoTransportConnect() { |
@@ -216,42 +256,42 @@ int TransportConnectJob::DoTransportConnect() { |
interval_between_connects_ = CONNECT_INTERVAL_GT_20MS; |
} |
- next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE; |
- transport_socket_ = client_socket_factory_->CreateTransportClientSocket( |
- addresses_, net_log().net_log(), net_log().source()); |
- int rv = transport_socket_->Connect( |
- base::Bind(&TransportConnectJob::OnIOComplete, base::Unretained(this))); |
+ helper_.set_next_state( |
+ TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE); |
+ transport_socket_ = |
+ helper_.client_socket_factory()->CreateTransportClientSocket( |
+ helper_.addresses(), net_log().net_log(), net_log().source()); |
+ int rv = transport_socket_->Connect(helper_.on_io_complete()); |
if (rv == ERR_IO_PENDING && |
- addresses_.front().GetFamily() == ADDRESS_FAMILY_IPV6 && |
- !AddressListOnlyContainsIPv6(addresses_)) { |
- fallback_timer_.Start(FROM_HERE, |
- base::TimeDelta::FromMilliseconds(kIPv6FallbackTimerInMs), |
- this, &TransportConnectJob::DoIPv6FallbackTransportConnect); |
+ helper_.addresses().front().GetFamily() == ADDRESS_FAMILY_IPV6 && |
+ !AddressListOnlyContainsIPv6(helper_.addresses())) { |
+ fallback_timer_.Start( |
+ FROM_HERE, |
+ base::TimeDelta::FromMilliseconds( |
+ TransportConnectJobHelper::kIPv6FallbackTimerInMs), |
+ this, |
+ &TransportConnectJob::DoIPv6FallbackTransportConnect); |
} |
return rv; |
} |
int TransportConnectJob::DoTransportConnectComplete(int result) { |
if (result == OK) { |
- bool is_ipv4 = addresses_.front().GetFamily() == ADDRESS_FAMILY_IPV4; |
- DCHECK(!connect_timing_.connect_start.is_null()); |
- DCHECK(!connect_timing_.dns_start.is_null()); |
- base::TimeTicks now = base::TimeTicks::Now(); |
- base::TimeDelta total_duration = now - connect_timing_.dns_start; |
- UMA_HISTOGRAM_CUSTOM_TIMES( |
- "Net.DNS_Resolution_And_TCP_Connection_Latency2", |
- total_duration, |
- base::TimeDelta::FromMilliseconds(1), |
- base::TimeDelta::FromMinutes(10), |
- 100); |
- |
- base::TimeDelta connect_duration = now - connect_timing_.connect_start; |
- UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency", |
- connect_duration, |
- base::TimeDelta::FromMilliseconds(1), |
- base::TimeDelta::FromMinutes(10), |
- 100); |
- |
+ bool is_ipv4 = |
+ helper_.addresses().front().GetFamily() == ADDRESS_FAMILY_IPV4; |
+ TransportConnectJobHelper::ConnectionLatencyHistogram race_result = |
+ TransportConnectJobHelper::CONNECTION_LATENCY_UNKNOWN; |
+ if (is_ipv4) { |
+ race_result = TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_NO_RACE; |
+ } else { |
+ if (AddressListOnlyContainsIPv6(helper_.addresses())) { |
+ race_result = TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_SOLO; |
+ } else { |
+ race_result = |
+ TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_RACEABLE; |
+ } |
+ } |
+ base::TimeDelta connect_duration = helper_.HistogramDuration(race_result); |
switch (interval_between_connects_) { |
case CONNECT_INTERVAL_LE_10MS: |
UMA_HISTOGRAM_CUSTOM_TIMES( |
@@ -282,27 +322,6 @@ int TransportConnectJob::DoTransportConnectComplete(int result) { |
break; |
} |
- if (is_ipv4) { |
- UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_No_Race", |
- connect_duration, |
- base::TimeDelta::FromMilliseconds(1), |
- base::TimeDelta::FromMinutes(10), |
- 100); |
- } else { |
- if (AddressListOnlyContainsIPv6(addresses_)) { |
- UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Solo", |
- connect_duration, |
- base::TimeDelta::FromMilliseconds(1), |
- base::TimeDelta::FromMinutes(10), |
- 100); |
- } else { |
- UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Raceable", |
- connect_duration, |
- base::TimeDelta::FromMilliseconds(1), |
- base::TimeDelta::FromMinutes(10), |
- 100); |
- } |
- } |
SetSocket(transport_socket_.Pass()); |
fallback_timer_.Stop(); |
} else { |
@@ -317,7 +336,8 @@ int TransportConnectJob::DoTransportConnectComplete(int result) { |
void TransportConnectJob::DoIPv6FallbackTransportConnect() { |
// The timer should only fire while we're waiting for the main connect to |
// succeed. |
- if (next_state_ != STATE_TRANSPORT_CONNECT_COMPLETE) { |
+ if (helper_.next_state() != |
+ TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE) { |
NOTREACHED(); |
return; |
} |
@@ -325,10 +345,10 @@ void TransportConnectJob::DoIPv6FallbackTransportConnect() { |
DCHECK(!fallback_transport_socket_.get()); |
DCHECK(!fallback_addresses_.get()); |
- fallback_addresses_.reset(new AddressList(addresses_)); |
+ fallback_addresses_.reset(new AddressList(helper_.addresses())); |
MakeAddressListStartWithIPv4(fallback_addresses_.get()); |
fallback_transport_socket_ = |
- client_socket_factory_->CreateTransportClientSocket( |
+ helper_.client_socket_factory()->CreateTransportClientSocket( |
*fallback_addresses_, net_log().net_log(), net_log().source()); |
fallback_connect_start_time_ = base::TimeTicks::Now(); |
int rv = fallback_transport_socket_->Connect( |
@@ -341,7 +361,8 @@ void TransportConnectJob::DoIPv6FallbackTransportConnect() { |
void TransportConnectJob::DoIPv6FallbackTransportConnectComplete(int result) { |
// This should only happen when we're waiting for the main connect to succeed. |
- if (next_state_ != STATE_TRANSPORT_CONNECT_COMPLETE) { |
+ if (helper_.next_state() != |
+ TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE) { |
NOTREACHED(); |
return; |
} |
@@ -352,30 +373,11 @@ void TransportConnectJob::DoIPv6FallbackTransportConnectComplete(int result) { |
if (result == OK) { |
DCHECK(!fallback_connect_start_time_.is_null()); |
- DCHECK(!connect_timing_.dns_start.is_null()); |
- base::TimeTicks now = base::TimeTicks::Now(); |
- base::TimeDelta total_duration = now - connect_timing_.dns_start; |
- UMA_HISTOGRAM_CUSTOM_TIMES( |
- "Net.DNS_Resolution_And_TCP_Connection_Latency2", |
- total_duration, |
- base::TimeDelta::FromMilliseconds(1), |
- base::TimeDelta::FromMinutes(10), |
- 100); |
- |
- base::TimeDelta connect_duration = now - fallback_connect_start_time_; |
- UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency", |
- connect_duration, |
- base::TimeDelta::FromMilliseconds(1), |
- base::TimeDelta::FromMinutes(10), |
- 100); |
- |
- UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_Wins_Race", |
- connect_duration, |
- base::TimeDelta::FromMilliseconds(1), |
- base::TimeDelta::FromMinutes(10), |
- 100); |
+ connect_timing_.connect_start = fallback_connect_start_time_; |
+ helper_.HistogramDuration( |
+ TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_WINS_RACE); |
SetSocket(fallback_transport_socket_.Pass()); |
- next_state_ = STATE_NONE; |
+ helper_.set_next_state(TransportConnectJobHelper::STATE_NONE); |
transport_socket_.reset(); |
} else { |
// Be a bit paranoid and kill off the fallback members to prevent reuse. |
@@ -386,8 +388,7 @@ void TransportConnectJob::DoIPv6FallbackTransportConnectComplete(int result) { |
} |
int TransportConnectJob::ConnectInternal() { |
- next_state_ = STATE_RESOLVE_HOST; |
- return DoLoop(OK); |
+ return helper_.DoConnectInternal(this); |
} |
scoped_ptr<ConnectJob> |
@@ -439,6 +440,15 @@ int TransportClientSocketPool::RequestSocket( |
const scoped_refptr<TransportSocketParams>* casted_params = |
static_cast<const scoped_refptr<TransportSocketParams>*>(params); |
+ NetLogTcpClientSocketPoolRequestedSocket(net_log, casted_params); |
+ |
+ return base_.RequestSocket(group_name, *casted_params, priority, handle, |
+ callback, net_log); |
+} |
+ |
+void TransportClientSocketPool::NetLogTcpClientSocketPoolRequestedSocket( |
+ const BoundNetLog& net_log, |
+ const scoped_refptr<TransportSocketParams>* casted_params) { |
if (net_log.IsLogging()) { |
// TODO(eroman): Split out the host and port parameters. |
net_log.AddEvent( |
@@ -446,9 +456,6 @@ int TransportClientSocketPool::RequestSocket( |
CreateNetLogHostPortPairCallback( |
&casted_params->get()->destination().host_port_pair())); |
} |
- |
- return base_.RequestSocket(group_name, *casted_params, priority, handle, |
- callback, net_log); |
} |
void TransportClientSocketPool::RequestSockets( |