| 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 #include "net/socket/transport_client_socket_pool.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "base/compiler_specific.h" | |
| 10 #include "base/lazy_instance.h" | |
| 11 #include "base/logging.h" | |
| 12 #include "base/message_loop/message_loop.h" | |
| 13 #include "base/metrics/histogram.h" | |
| 14 #include "base/strings/string_util.h" | |
| 15 #include "base/synchronization/lock.h" | |
| 16 #include "base/time/time.h" | |
| 17 #include "base/values.h" | |
| 18 #include "net/base/ip_endpoint.h" | |
| 19 #include "net/base/net_errors.h" | |
| 20 #include "net/base/net_log.h" | |
| 21 #include "net/socket/client_socket_factory.h" | |
| 22 #include "net/socket/client_socket_handle.h" | |
| 23 #include "net/socket/client_socket_pool_base.h" | |
| 24 #include "net/socket/socket_net_log_params.h" | |
| 25 #include "net/socket/tcp_client_socket.h" | |
| 26 | |
| 27 using base::TimeDelta; | |
| 28 | |
| 29 namespace net { | |
| 30 | |
| 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 | |
| 33 // don't synchronize. | |
| 34 const int TransportConnectJobHelper::kIPv6FallbackTimerInMs = 300; | |
| 35 | |
| 36 namespace { | |
| 37 | |
| 38 // Returns true iff all addresses in |list| are in the IPv6 family. | |
| 39 bool AddressListOnlyContainsIPv6(const AddressList& list) { | |
| 40 DCHECK(!list.empty()); | |
| 41 for (AddressList::const_iterator iter = list.begin(); iter != list.end(); | |
| 42 ++iter) { | |
| 43 if (iter->GetFamily() != ADDRESS_FAMILY_IPV6) | |
| 44 return false; | |
| 45 } | |
| 46 return true; | |
| 47 } | |
| 48 | |
| 49 } // namespace | |
| 50 | |
| 51 // This lock protects |g_last_connect_time|. | |
| 52 static base::LazyInstance<base::Lock>::Leaky | |
| 53 g_last_connect_time_lock = LAZY_INSTANCE_INITIALIZER; | |
| 54 | |
| 55 // |g_last_connect_time| has the last time a connect() call is made. | |
| 56 static base::LazyInstance<base::TimeTicks>::Leaky | |
| 57 g_last_connect_time = LAZY_INSTANCE_INITIALIZER; | |
| 58 | |
| 59 TransportSocketParams::TransportSocketParams( | |
| 60 const HostPortPair& host_port_pair, | |
| 61 bool disable_resolver_cache, | |
| 62 bool ignore_limits, | |
| 63 const OnHostResolutionCallback& host_resolution_callback, | |
| 64 CombineConnectAndWritePolicy combine_connect_and_write_if_supported) | |
| 65 : destination_(host_port_pair), | |
| 66 ignore_limits_(ignore_limits), | |
| 67 host_resolution_callback_(host_resolution_callback), | |
| 68 combine_connect_and_write_(combine_connect_and_write_if_supported) { | |
| 69 if (disable_resolver_cache) | |
| 70 destination_.set_allow_cached_response(false); | |
| 71 // combine_connect_and_write currently translates to TCP FastOpen. | |
| 72 // Enable TCP FastOpen if user wants it. | |
| 73 if (combine_connect_and_write_ == COMBINE_CONNECT_AND_WRITE_DEFAULT) { | |
| 74 IsTCPFastOpenUserEnabled() ? combine_connect_and_write_ = | |
| 75 COMBINE_CONNECT_AND_WRITE_DESIRED : | |
| 76 COMBINE_CONNECT_AND_WRITE_PROHIBITED; | |
| 77 } | |
| 78 } | |
| 79 | |
| 80 TransportSocketParams::~TransportSocketParams() {} | |
| 81 | |
| 82 // TransportConnectJobs will time out after this many seconds. Note this is | |
| 83 // the total time, including both host resolution and TCP connect() times. | |
| 84 // | |
| 85 // TODO(eroman): The use of this constant needs to be re-evaluated. The time | |
| 86 // needed for TCPClientSocketXXX::Connect() can be arbitrarily long, since | |
| 87 // the address list may contain many alternatives, and most of those may | |
| 88 // timeout. Even worse, the per-connect timeout threshold varies greatly | |
| 89 // between systems (anywhere from 20 seconds to 190 seconds). | |
| 90 // See comment #12 at http://crbug.com/23364 for specifics. | |
| 91 static const int kTransportConnectJobTimeoutInSeconds = 240; // 4 minutes. | |
| 92 | |
| 93 TransportConnectJobHelper::TransportConnectJobHelper( | |
| 94 const scoped_refptr<TransportSocketParams>& params, | |
| 95 ClientSocketFactory* client_socket_factory, | |
| 96 HostResolver* host_resolver, | |
| 97 LoadTimingInfo::ConnectTiming* connect_timing) | |
| 98 : params_(params), | |
| 99 client_socket_factory_(client_socket_factory), | |
| 100 resolver_(host_resolver), | |
| 101 next_state_(STATE_NONE), | |
| 102 connect_timing_(connect_timing) {} | |
| 103 | |
| 104 TransportConnectJobHelper::~TransportConnectJobHelper() {} | |
| 105 | |
| 106 int TransportConnectJobHelper::DoResolveHost(RequestPriority priority, | |
| 107 const BoundNetLog& net_log) { | |
| 108 next_state_ = STATE_RESOLVE_HOST_COMPLETE; | |
| 109 connect_timing_->dns_start = base::TimeTicks::Now(); | |
| 110 | |
| 111 return resolver_.Resolve( | |
| 112 params_->destination(), priority, &addresses_, on_io_complete_, net_log); | |
| 113 } | |
| 114 | |
| 115 int TransportConnectJobHelper::DoResolveHostComplete( | |
| 116 int result, | |
| 117 const BoundNetLog& net_log) { | |
| 118 connect_timing_->dns_end = base::TimeTicks::Now(); | |
| 119 // Overwrite connection start time, since for connections that do not go | |
| 120 // through proxies, |connect_start| should not include dns lookup time. | |
| 121 connect_timing_->connect_start = connect_timing_->dns_end; | |
| 122 | |
| 123 if (result == OK) { | |
| 124 // Invoke callback, and abort if it fails. | |
| 125 if (!params_->host_resolution_callback().is_null()) | |
| 126 result = params_->host_resolution_callback().Run(addresses_, net_log); | |
| 127 | |
| 128 if (result == OK) | |
| 129 next_state_ = STATE_TRANSPORT_CONNECT; | |
| 130 } | |
| 131 return result; | |
| 132 } | |
| 133 | |
| 134 base::TimeDelta TransportConnectJobHelper::HistogramDuration( | |
| 135 ConnectionLatencyHistogram race_result) { | |
| 136 DCHECK(!connect_timing_->connect_start.is_null()); | |
| 137 DCHECK(!connect_timing_->dns_start.is_null()); | |
| 138 base::TimeTicks now = base::TimeTicks::Now(); | |
| 139 base::TimeDelta total_duration = now - connect_timing_->dns_start; | |
| 140 UMA_HISTOGRAM_CUSTOM_TIMES("Net.DNS_Resolution_And_TCP_Connection_Latency2", | |
| 141 total_duration, | |
| 142 base::TimeDelta::FromMilliseconds(1), | |
| 143 base::TimeDelta::FromMinutes(10), | |
| 144 100); | |
| 145 | |
| 146 base::TimeDelta connect_duration = now - connect_timing_->connect_start; | |
| 147 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency", | |
| 148 connect_duration, | |
| 149 base::TimeDelta::FromMilliseconds(1), | |
| 150 base::TimeDelta::FromMinutes(10), | |
| 151 100); | |
| 152 | |
| 153 switch (race_result) { | |
| 154 case CONNECTION_LATENCY_IPV4_WINS_RACE: | |
| 155 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_Wins_Race", | |
| 156 connect_duration, | |
| 157 base::TimeDelta::FromMilliseconds(1), | |
| 158 base::TimeDelta::FromMinutes(10), | |
| 159 100); | |
| 160 break; | |
| 161 | |
| 162 case CONNECTION_LATENCY_IPV4_NO_RACE: | |
| 163 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_No_Race", | |
| 164 connect_duration, | |
| 165 base::TimeDelta::FromMilliseconds(1), | |
| 166 base::TimeDelta::FromMinutes(10), | |
| 167 100); | |
| 168 break; | |
| 169 | |
| 170 case CONNECTION_LATENCY_IPV6_RACEABLE: | |
| 171 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Raceable", | |
| 172 connect_duration, | |
| 173 base::TimeDelta::FromMilliseconds(1), | |
| 174 base::TimeDelta::FromMinutes(10), | |
| 175 100); | |
| 176 break; | |
| 177 | |
| 178 case CONNECTION_LATENCY_IPV6_SOLO: | |
| 179 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Solo", | |
| 180 connect_duration, | |
| 181 base::TimeDelta::FromMilliseconds(1), | |
| 182 base::TimeDelta::FromMinutes(10), | |
| 183 100); | |
| 184 break; | |
| 185 | |
| 186 default: | |
| 187 NOTREACHED(); | |
| 188 break; | |
| 189 } | |
| 190 | |
| 191 return connect_duration; | |
| 192 } | |
| 193 | |
| 194 TransportConnectJob::TransportConnectJob( | |
| 195 const std::string& group_name, | |
| 196 RequestPriority priority, | |
| 197 const scoped_refptr<TransportSocketParams>& params, | |
| 198 base::TimeDelta timeout_duration, | |
| 199 ClientSocketFactory* client_socket_factory, | |
| 200 HostResolver* host_resolver, | |
| 201 Delegate* delegate, | |
| 202 NetLog* net_log) | |
| 203 : ConnectJob(group_name, timeout_duration, priority, delegate, | |
| 204 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)), | |
| 205 helper_(params, client_socket_factory, host_resolver, &connect_timing_), | |
| 206 interval_between_connects_(CONNECT_INTERVAL_GT_20MS) { | |
| 207 helper_.SetOnIOComplete(this); | |
| 208 } | |
| 209 | |
| 210 TransportConnectJob::~TransportConnectJob() { | |
| 211 // We don't worry about cancelling the host resolution and TCP connect, since | |
| 212 // ~SingleRequestHostResolver and ~StreamSocket will take care of it. | |
| 213 } | |
| 214 | |
| 215 LoadState TransportConnectJob::GetLoadState() const { | |
| 216 switch (helper_.next_state()) { | |
| 217 case TransportConnectJobHelper::STATE_RESOLVE_HOST: | |
| 218 case TransportConnectJobHelper::STATE_RESOLVE_HOST_COMPLETE: | |
| 219 return LOAD_STATE_RESOLVING_HOST; | |
| 220 case TransportConnectJobHelper::STATE_TRANSPORT_CONNECT: | |
| 221 case TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE: | |
| 222 return LOAD_STATE_CONNECTING; | |
| 223 case TransportConnectJobHelper::STATE_NONE: | |
| 224 return LOAD_STATE_IDLE; | |
| 225 } | |
| 226 NOTREACHED(); | |
| 227 return LOAD_STATE_IDLE; | |
| 228 } | |
| 229 | |
| 230 // static | |
| 231 void TransportConnectJob::MakeAddressListStartWithIPv4(AddressList* list) { | |
| 232 for (AddressList::iterator i = list->begin(); i != list->end(); ++i) { | |
| 233 if (i->GetFamily() == ADDRESS_FAMILY_IPV4) { | |
| 234 std::rotate(list->begin(), i, list->end()); | |
| 235 break; | |
| 236 } | |
| 237 } | |
| 238 } | |
| 239 | |
| 240 int TransportConnectJob::DoResolveHost() { | |
| 241 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed. | |
| 242 tracked_objects::ScopedTracker tracking_profile( | |
| 243 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 244 "436634 TransportConnectJob::DoResolveHost")); | |
| 245 | |
| 246 return helper_.DoResolveHost(priority(), net_log()); | |
| 247 } | |
| 248 | |
| 249 int TransportConnectJob::DoResolveHostComplete(int result) { | |
| 250 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed. | |
| 251 tracked_objects::ScopedTracker tracking_profile( | |
| 252 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 253 "436634 TransportConnectJob::DoResolveHostComplete")); | |
| 254 | |
| 255 return helper_.DoResolveHostComplete(result, net_log()); | |
| 256 } | |
| 257 | |
| 258 int TransportConnectJob::DoTransportConnect() { | |
| 259 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed. | |
| 260 tracked_objects::ScopedTracker tracking_profile( | |
| 261 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 262 "436634 TransportConnectJob::DoTransportConnect")); | |
| 263 | |
| 264 base::TimeTicks now = base::TimeTicks::Now(); | |
| 265 base::TimeTicks last_connect_time; | |
| 266 { | |
| 267 base::AutoLock lock(g_last_connect_time_lock.Get()); | |
| 268 last_connect_time = g_last_connect_time.Get(); | |
| 269 *g_last_connect_time.Pointer() = now; | |
| 270 } | |
| 271 if (last_connect_time.is_null()) { | |
| 272 interval_between_connects_ = CONNECT_INTERVAL_GT_20MS; | |
| 273 } else { | |
| 274 int64 interval = (now - last_connect_time).InMilliseconds(); | |
| 275 if (interval <= 10) | |
| 276 interval_between_connects_ = CONNECT_INTERVAL_LE_10MS; | |
| 277 else if (interval <= 20) | |
| 278 interval_between_connects_ = CONNECT_INTERVAL_LE_20MS; | |
| 279 else | |
| 280 interval_between_connects_ = CONNECT_INTERVAL_GT_20MS; | |
| 281 } | |
| 282 | |
| 283 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed. | |
| 284 tracked_objects::ScopedTracker tracking_profile1( | |
| 285 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 286 "436634 TransportConnectJob::DoTransportConnect1")); | |
| 287 | |
| 288 helper_.set_next_state( | |
| 289 TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE); | |
| 290 transport_socket_ = | |
| 291 helper_.client_socket_factory()->CreateTransportClientSocket( | |
| 292 helper_.addresses(), net_log().net_log(), net_log().source()); | |
| 293 | |
| 294 // If the list contains IPv6 and IPv4 addresses, the first address will | |
| 295 // be IPv6, and the IPv4 addresses will be tried as fallback addresses, | |
| 296 // per "Happy Eyeballs" (RFC 6555). | |
| 297 bool try_ipv6_connect_with_ipv4_fallback = | |
| 298 helper_.addresses().front().GetFamily() == ADDRESS_FAMILY_IPV6 && | |
| 299 !AddressListOnlyContainsIPv6(helper_.addresses()); | |
| 300 | |
| 301 // Enable TCP FastOpen if indicated by transport socket params. | |
| 302 // Note: We currently do not turn on TCP FastOpen for destinations where | |
| 303 // we try a TCP connect over IPv6 with fallback to IPv4. | |
| 304 if (!try_ipv6_connect_with_ipv4_fallback && | |
| 305 helper_.params()->combine_connect_and_write() == | |
| 306 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DESIRED) { | |
| 307 transport_socket_->EnableTCPFastOpenIfSupported(); | |
| 308 } | |
| 309 | |
| 310 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed. | |
| 311 tracked_objects::ScopedTracker tracking_profile2( | |
| 312 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 313 "436634 TransportConnectJob::DoTransportConnect2")); | |
| 314 | |
| 315 int rv = transport_socket_->Connect(helper_.on_io_complete()); | |
| 316 | |
| 317 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed. | |
| 318 tracked_objects::ScopedTracker tracking_profile3( | |
| 319 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 320 "436634 TransportConnectJob::DoTransportConnect3")); | |
| 321 | |
| 322 if (rv == ERR_IO_PENDING && try_ipv6_connect_with_ipv4_fallback) { | |
| 323 fallback_timer_.Start( | |
| 324 FROM_HERE, | |
| 325 base::TimeDelta::FromMilliseconds( | |
| 326 TransportConnectJobHelper::kIPv6FallbackTimerInMs), | |
| 327 this, | |
| 328 &TransportConnectJob::DoIPv6FallbackTransportConnect); | |
| 329 } | |
| 330 return rv; | |
| 331 } | |
| 332 | |
| 333 int TransportConnectJob::DoTransportConnectComplete(int result) { | |
| 334 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed. | |
| 335 tracked_objects::ScopedTracker tracking_profile( | |
| 336 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 337 "436634 TransportConnectJob::DoTransportConnectComplete")); | |
| 338 | |
| 339 if (result == OK) { | |
| 340 bool is_ipv4 = | |
| 341 helper_.addresses().front().GetFamily() == ADDRESS_FAMILY_IPV4; | |
| 342 TransportConnectJobHelper::ConnectionLatencyHistogram race_result = | |
| 343 TransportConnectJobHelper::CONNECTION_LATENCY_UNKNOWN; | |
| 344 if (is_ipv4) { | |
| 345 race_result = TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_NO_RACE; | |
| 346 } else { | |
| 347 if (AddressListOnlyContainsIPv6(helper_.addresses())) { | |
| 348 race_result = TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_SOLO; | |
| 349 } else { | |
| 350 race_result = | |
| 351 TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_RACEABLE; | |
| 352 } | |
| 353 } | |
| 354 base::TimeDelta connect_duration = helper_.HistogramDuration(race_result); | |
| 355 switch (interval_between_connects_) { | |
| 356 case CONNECT_INTERVAL_LE_10MS: | |
| 357 UMA_HISTOGRAM_CUSTOM_TIMES( | |
| 358 "Net.TCP_Connection_Latency_Interval_LessThanOrEqual_10ms", | |
| 359 connect_duration, | |
| 360 base::TimeDelta::FromMilliseconds(1), | |
| 361 base::TimeDelta::FromMinutes(10), | |
| 362 100); | |
| 363 break; | |
| 364 case CONNECT_INTERVAL_LE_20MS: | |
| 365 UMA_HISTOGRAM_CUSTOM_TIMES( | |
| 366 "Net.TCP_Connection_Latency_Interval_LessThanOrEqual_20ms", | |
| 367 connect_duration, | |
| 368 base::TimeDelta::FromMilliseconds(1), | |
| 369 base::TimeDelta::FromMinutes(10), | |
| 370 100); | |
| 371 break; | |
| 372 case CONNECT_INTERVAL_GT_20MS: | |
| 373 UMA_HISTOGRAM_CUSTOM_TIMES( | |
| 374 "Net.TCP_Connection_Latency_Interval_GreaterThan_20ms", | |
| 375 connect_duration, | |
| 376 base::TimeDelta::FromMilliseconds(1), | |
| 377 base::TimeDelta::FromMinutes(10), | |
| 378 100); | |
| 379 break; | |
| 380 default: | |
| 381 NOTREACHED(); | |
| 382 break; | |
| 383 } | |
| 384 | |
| 385 SetSocket(transport_socket_.Pass()); | |
| 386 fallback_timer_.Stop(); | |
| 387 } else { | |
| 388 // Be a bit paranoid and kill off the fallback members to prevent reuse. | |
| 389 fallback_transport_socket_.reset(); | |
| 390 fallback_addresses_.reset(); | |
| 391 } | |
| 392 | |
| 393 return result; | |
| 394 } | |
| 395 | |
| 396 void TransportConnectJob::DoIPv6FallbackTransportConnect() { | |
| 397 // The timer should only fire while we're waiting for the main connect to | |
| 398 // succeed. | |
| 399 if (helper_.next_state() != | |
| 400 TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE) { | |
| 401 NOTREACHED(); | |
| 402 return; | |
| 403 } | |
| 404 | |
| 405 DCHECK(!fallback_transport_socket_.get()); | |
| 406 DCHECK(!fallback_addresses_.get()); | |
| 407 | |
| 408 fallback_addresses_.reset(new AddressList(helper_.addresses())); | |
| 409 MakeAddressListStartWithIPv4(fallback_addresses_.get()); | |
| 410 fallback_transport_socket_ = | |
| 411 helper_.client_socket_factory()->CreateTransportClientSocket( | |
| 412 *fallback_addresses_, net_log().net_log(), net_log().source()); | |
| 413 fallback_connect_start_time_ = base::TimeTicks::Now(); | |
| 414 int rv = fallback_transport_socket_->Connect( | |
| 415 base::Bind( | |
| 416 &TransportConnectJob::DoIPv6FallbackTransportConnectComplete, | |
| 417 base::Unretained(this))); | |
| 418 if (rv != ERR_IO_PENDING) | |
| 419 DoIPv6FallbackTransportConnectComplete(rv); | |
| 420 } | |
| 421 | |
| 422 void TransportConnectJob::DoIPv6FallbackTransportConnectComplete(int result) { | |
| 423 // This should only happen when we're waiting for the main connect to succeed. | |
| 424 if (helper_.next_state() != | |
| 425 TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE) { | |
| 426 NOTREACHED(); | |
| 427 return; | |
| 428 } | |
| 429 | |
| 430 DCHECK_NE(ERR_IO_PENDING, result); | |
| 431 DCHECK(fallback_transport_socket_.get()); | |
| 432 DCHECK(fallback_addresses_.get()); | |
| 433 | |
| 434 if (result == OK) { | |
| 435 DCHECK(!fallback_connect_start_time_.is_null()); | |
| 436 connect_timing_.connect_start = fallback_connect_start_time_; | |
| 437 helper_.HistogramDuration( | |
| 438 TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_WINS_RACE); | |
| 439 SetSocket(fallback_transport_socket_.Pass()); | |
| 440 helper_.set_next_state(TransportConnectJobHelper::STATE_NONE); | |
| 441 transport_socket_.reset(); | |
| 442 } else { | |
| 443 // Be a bit paranoid and kill off the fallback members to prevent reuse. | |
| 444 fallback_transport_socket_.reset(); | |
| 445 fallback_addresses_.reset(); | |
| 446 } | |
| 447 NotifyDelegateOfCompletion(result); // Deletes |this| | |
| 448 } | |
| 449 | |
| 450 int TransportConnectJob::ConnectInternal() { | |
| 451 return helper_.DoConnectInternal(this); | |
| 452 } | |
| 453 | |
| 454 scoped_ptr<ConnectJob> | |
| 455 TransportClientSocketPool::TransportConnectJobFactory::NewConnectJob( | |
| 456 const std::string& group_name, | |
| 457 const PoolBase::Request& request, | |
| 458 ConnectJob::Delegate* delegate) const { | |
| 459 return scoped_ptr<ConnectJob>( | |
| 460 new TransportConnectJob(group_name, | |
| 461 request.priority(), | |
| 462 request.params(), | |
| 463 ConnectionTimeout(), | |
| 464 client_socket_factory_, | |
| 465 host_resolver_, | |
| 466 delegate, | |
| 467 net_log_)); | |
| 468 } | |
| 469 | |
| 470 base::TimeDelta | |
| 471 TransportClientSocketPool::TransportConnectJobFactory::ConnectionTimeout() | |
| 472 const { | |
| 473 return base::TimeDelta::FromSeconds(kTransportConnectJobTimeoutInSeconds); | |
| 474 } | |
| 475 | |
| 476 TransportClientSocketPool::TransportClientSocketPool( | |
| 477 int max_sockets, | |
| 478 int max_sockets_per_group, | |
| 479 ClientSocketPoolHistograms* histograms, | |
| 480 HostResolver* host_resolver, | |
| 481 ClientSocketFactory* client_socket_factory, | |
| 482 NetLog* net_log) | |
| 483 : base_(NULL, max_sockets, max_sockets_per_group, histograms, | |
| 484 ClientSocketPool::unused_idle_socket_timeout(), | |
| 485 ClientSocketPool::used_idle_socket_timeout(), | |
| 486 new TransportConnectJobFactory(client_socket_factory, | |
| 487 host_resolver, net_log)) { | |
| 488 base_.EnableConnectBackupJobs(); | |
| 489 } | |
| 490 | |
| 491 TransportClientSocketPool::~TransportClientSocketPool() {} | |
| 492 | |
| 493 int TransportClientSocketPool::RequestSocket( | |
| 494 const std::string& group_name, | |
| 495 const void* params, | |
| 496 RequestPriority priority, | |
| 497 ClientSocketHandle* handle, | |
| 498 const CompletionCallback& callback, | |
| 499 const BoundNetLog& net_log) { | |
| 500 const scoped_refptr<TransportSocketParams>* casted_params = | |
| 501 static_cast<const scoped_refptr<TransportSocketParams>*>(params); | |
| 502 | |
| 503 NetLogTcpClientSocketPoolRequestedSocket(net_log, casted_params); | |
| 504 | |
| 505 return base_.RequestSocket(group_name, *casted_params, priority, handle, | |
| 506 callback, net_log); | |
| 507 } | |
| 508 | |
| 509 void TransportClientSocketPool::NetLogTcpClientSocketPoolRequestedSocket( | |
| 510 const BoundNetLog& net_log, | |
| 511 const scoped_refptr<TransportSocketParams>* casted_params) { | |
| 512 if (net_log.IsLogging()) { | |
| 513 // TODO(eroman): Split out the host and port parameters. | |
| 514 net_log.AddEvent( | |
| 515 NetLog::TYPE_TCP_CLIENT_SOCKET_POOL_REQUESTED_SOCKET, | |
| 516 CreateNetLogHostPortPairCallback( | |
| 517 &casted_params->get()->destination().host_port_pair())); | |
| 518 } | |
| 519 } | |
| 520 | |
| 521 void TransportClientSocketPool::RequestSockets( | |
| 522 const std::string& group_name, | |
| 523 const void* params, | |
| 524 int num_sockets, | |
| 525 const BoundNetLog& net_log) { | |
| 526 const scoped_refptr<TransportSocketParams>* casted_params = | |
| 527 static_cast<const scoped_refptr<TransportSocketParams>*>(params); | |
| 528 | |
| 529 if (net_log.IsLogging()) { | |
| 530 // TODO(eroman): Split out the host and port parameters. | |
| 531 net_log.AddEvent( | |
| 532 NetLog::TYPE_TCP_CLIENT_SOCKET_POOL_REQUESTED_SOCKETS, | |
| 533 CreateNetLogHostPortPairCallback( | |
| 534 &casted_params->get()->destination().host_port_pair())); | |
| 535 } | |
| 536 | |
| 537 base_.RequestSockets(group_name, *casted_params, num_sockets, net_log); | |
| 538 } | |
| 539 | |
| 540 void TransportClientSocketPool::CancelRequest( | |
| 541 const std::string& group_name, | |
| 542 ClientSocketHandle* handle) { | |
| 543 base_.CancelRequest(group_name, handle); | |
| 544 } | |
| 545 | |
| 546 void TransportClientSocketPool::ReleaseSocket( | |
| 547 const std::string& group_name, | |
| 548 scoped_ptr<StreamSocket> socket, | |
| 549 int id) { | |
| 550 base_.ReleaseSocket(group_name, socket.Pass(), id); | |
| 551 } | |
| 552 | |
| 553 void TransportClientSocketPool::FlushWithError(int error) { | |
| 554 base_.FlushWithError(error); | |
| 555 } | |
| 556 | |
| 557 void TransportClientSocketPool::CloseIdleSockets() { | |
| 558 base_.CloseIdleSockets(); | |
| 559 } | |
| 560 | |
| 561 int TransportClientSocketPool::IdleSocketCount() const { | |
| 562 return base_.idle_socket_count(); | |
| 563 } | |
| 564 | |
| 565 int TransportClientSocketPool::IdleSocketCountInGroup( | |
| 566 const std::string& group_name) const { | |
| 567 return base_.IdleSocketCountInGroup(group_name); | |
| 568 } | |
| 569 | |
| 570 LoadState TransportClientSocketPool::GetLoadState( | |
| 571 const std::string& group_name, const ClientSocketHandle* handle) const { | |
| 572 return base_.GetLoadState(group_name, handle); | |
| 573 } | |
| 574 | |
| 575 base::DictionaryValue* TransportClientSocketPool::GetInfoAsValue( | |
| 576 const std::string& name, | |
| 577 const std::string& type, | |
| 578 bool include_nested_pools) const { | |
| 579 return base_.GetInfoAsValue(name, type); | |
| 580 } | |
| 581 | |
| 582 base::TimeDelta TransportClientSocketPool::ConnectionTimeout() const { | |
| 583 return base_.ConnectionTimeout(); | |
| 584 } | |
| 585 | |
| 586 ClientSocketPoolHistograms* TransportClientSocketPool::histograms() const { | |
| 587 return base_.histograms(); | |
| 588 } | |
| 589 | |
| 590 bool TransportClientSocketPool::IsStalled() const { | |
| 591 return base_.IsStalled(); | |
| 592 } | |
| 593 | |
| 594 void TransportClientSocketPool::AddHigherLayeredPool( | |
| 595 HigherLayeredPool* higher_pool) { | |
| 596 base_.AddHigherLayeredPool(higher_pool); | |
| 597 } | |
| 598 | |
| 599 void TransportClientSocketPool::RemoveHigherLayeredPool( | |
| 600 HigherLayeredPool* higher_pool) { | |
| 601 base_.RemoveHigherLayeredPool(higher_pool); | |
| 602 } | |
| 603 | |
| 604 } // namespace net | |
| OLD | NEW |