| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |