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 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 CopyConnectionAttemptsFromClientSocketHandles(); | |
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 Loading... | |
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 CopyConnectionAttemptsFromClientSocketHandles(); | |
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::CopyConnectionAttemptsFromClientSocketHandles() { | |
Randy Smith (Not in Mondays)
2015/05/14 19:42:05
I think this name is misleading, since we have a C
Deprecated (see juliatuttle)
2015/05/14 20:02:35
Gosh, you're right. That was a think-o when I wrot
Randy Smith (Not in Mondays)
2015/05/14 20:29:55
I zoned over it several times myself. "ClientSock
| |
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 Loading... | |
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 |
OLD | NEW |