| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/http/http_proxy_client_socket_wrapper.h" | 5 #include "net/http/http_proxy_client_socket_wrapper.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 11 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
| 12 #include "base/memory/weak_ptr.h" | 12 #include "base/memory/weak_ptr.h" |
| 13 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/profiler/scoped_tracker.h" | 14 #include "base/profiler/scoped_tracker.h" |
| 14 #include "base/values.h" | 15 #include "base/values.h" |
| 15 #include "net/base/proxy_delegate.h" | 16 #include "net/base/proxy_delegate.h" |
| 16 #include "net/http/http_proxy_client_socket.h" | 17 #include "net/http/http_proxy_client_socket.h" |
| 17 #include "net/http/http_response_info.h" | 18 #include "net/http/http_response_info.h" |
| 18 #include "net/log/net_log_event_type.h" | 19 #include "net/log/net_log_event_type.h" |
| 19 #include "net/log/net_log_source.h" | 20 #include "net/log/net_log_source.h" |
| 20 #include "net/log/net_log_source_type.h" | 21 #include "net/log/net_log_source_type.h" |
| 21 #include "net/socket/client_socket_handle.h" | 22 #include "net/socket/client_socket_handle.h" |
| 22 #include "net/spdy/spdy_proxy_client_socket.h" | 23 #include "net/spdy/spdy_proxy_client_socket.h" |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 NOTREACHED() << "bad state"; | 381 NOTREACHED() << "bad state"; |
| 381 rv = ERR_FAILED; | 382 rv = ERR_FAILED; |
| 382 break; | 383 break; |
| 383 } | 384 } |
| 384 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 385 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
| 385 | 386 |
| 386 return rv; | 387 return rv; |
| 387 } | 388 } |
| 388 | 389 |
| 389 int HttpProxyClientSocketWrapper::DoBeginConnect() { | 390 int HttpProxyClientSocketWrapper::DoBeginConnect() { |
| 391 connect_start_time_ = base::TimeTicks::Now(); |
| 390 SetConnectTimer(connect_timeout_duration_); | 392 SetConnectTimer(connect_timeout_duration_); |
| 391 if (transport_params_) { | 393 if (transport_params_) { |
| 392 next_state_ = STATE_TCP_CONNECT; | 394 next_state_ = STATE_TCP_CONNECT; |
| 393 } else { | 395 } else { |
| 394 next_state_ = STATE_SSL_CONNECT; | 396 next_state_ = STATE_SSL_CONNECT; |
| 395 } | 397 } |
| 396 | 398 |
| 397 return OK; | 399 return OK; |
| 398 } | 400 } |
| 399 | 401 |
| 400 int HttpProxyClientSocketWrapper::DoTransportConnect() { | 402 int HttpProxyClientSocketWrapper::DoTransportConnect() { |
| 401 next_state_ = STATE_TCP_CONNECT_COMPLETE; | 403 next_state_ = STATE_TCP_CONNECT_COMPLETE; |
| 402 transport_socket_handle_.reset(new ClientSocketHandle()); | 404 transport_socket_handle_.reset(new ClientSocketHandle()); |
| 403 return transport_socket_handle_->Init( | 405 return transport_socket_handle_->Init( |
| 404 group_name_, transport_params_, priority_, respect_limits_, | 406 group_name_, transport_params_, priority_, respect_limits_, |
| 405 base::Bind(&HttpProxyClientSocketWrapper::OnIOComplete, | 407 base::Bind(&HttpProxyClientSocketWrapper::OnIOComplete, |
| 406 base::Unretained(this)), | 408 base::Unretained(this)), |
| 407 transport_pool_, net_log_); | 409 transport_pool_, net_log_); |
| 408 } | 410 } |
| 409 | 411 |
| 410 int HttpProxyClientSocketWrapper::DoTransportConnectComplete(int result) { | 412 int HttpProxyClientSocketWrapper::DoTransportConnectComplete(int result) { |
| 411 if (result != OK) | 413 if (result != OK) { |
| 414 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpProxy.ConnectLatency.Insecure.Error", |
| 415 base::TimeTicks::Now() - connect_start_time_); |
| 412 return ERR_PROXY_CONNECTION_FAILED; | 416 return ERR_PROXY_CONNECTION_FAILED; |
| 417 } |
| 413 | 418 |
| 414 // Reset the timer to just the length of time allowed for HttpProxy handshake | 419 // Reset the timer to just the length of time allowed for HttpProxy handshake |
| 415 // so that a fast TCP connection plus a slow HttpProxy failure doesn't take | 420 // so that a fast TCP connection plus a slow HttpProxy failure doesn't take |
| 416 // longer to timeout than it should. | 421 // longer to timeout than it should. |
| 417 SetConnectTimer(proxy_negotiation_timeout_duration_); | 422 SetConnectTimer(proxy_negotiation_timeout_duration_); |
| 418 | 423 |
| 419 next_state_ = STATE_HTTP_PROXY_CONNECT; | 424 next_state_ = STATE_HTTP_PROXY_CONNECT; |
| 420 return result; | 425 return result; |
| 421 } | 426 } |
| 422 | 427 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 438 group_name_, ssl_params_, priority_, respect_limits_, | 443 group_name_, ssl_params_, priority_, respect_limits_, |
| 439 base::Bind(&HttpProxyClientSocketWrapper::OnIOComplete, | 444 base::Bind(&HttpProxyClientSocketWrapper::OnIOComplete, |
| 440 base::Unretained(this)), | 445 base::Unretained(this)), |
| 441 ssl_pool_, net_log_); | 446 ssl_pool_, net_log_); |
| 442 } | 447 } |
| 443 | 448 |
| 444 int HttpProxyClientSocketWrapper::DoSSLConnectComplete(int result) { | 449 int HttpProxyClientSocketWrapper::DoSSLConnectComplete(int result) { |
| 445 if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { | 450 if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { |
| 446 DCHECK( | 451 DCHECK( |
| 447 transport_socket_handle_->ssl_error_response_info().cert_request_info); | 452 transport_socket_handle_->ssl_error_response_info().cert_request_info); |
| 453 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpProxy.ConnectLatency.Secure.Error", |
| 454 base::TimeTicks::Now() - connect_start_time_); |
| 448 error_response_info_.reset(new HttpResponseInfo( | 455 error_response_info_.reset(new HttpResponseInfo( |
| 449 transport_socket_handle_->ssl_error_response_info())); | 456 transport_socket_handle_->ssl_error_response_info())); |
| 450 error_response_info_->cert_request_info->is_proxy = true; | 457 error_response_info_->cert_request_info->is_proxy = true; |
| 451 return result; | 458 return result; |
| 452 } | 459 } |
| 453 | 460 |
| 454 if (IsCertificateError(result)) { | 461 if (IsCertificateError(result)) { |
| 462 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpProxy.ConnectLatency.Secure.Error", |
| 463 base::TimeTicks::Now() - connect_start_time_); |
| 455 if (ssl_params_->load_flags() & LOAD_IGNORE_ALL_CERT_ERRORS) { | 464 if (ssl_params_->load_flags() & LOAD_IGNORE_ALL_CERT_ERRORS) { |
| 456 result = OK; | 465 result = OK; |
| 457 } else { | 466 } else { |
| 458 // TODO(rch): allow the user to deal with proxy cert errors in the | 467 // TODO(rch): allow the user to deal with proxy cert errors in the |
| 459 // same way as server cert errors. | 468 // same way as server cert errors. |
| 460 transport_socket_handle_->socket()->Disconnect(); | 469 transport_socket_handle_->socket()->Disconnect(); |
| 461 return ERR_PROXY_CERTIFICATE_INVALID; | 470 return ERR_PROXY_CERTIFICATE_INVALID; |
| 462 } | 471 } |
| 463 } | 472 } |
| 464 // A SPDY session to the proxy completed prior to resolving the proxy | 473 // A SPDY session to the proxy completed prior to resolving the proxy |
| 465 // hostname. Surface this error, and allow the delegate to retry. | 474 // hostname. Surface this error, and allow the delegate to retry. |
| 466 // See crbug.com/334413. | 475 // See crbug.com/334413. |
| 467 if (result == ERR_SPDY_SESSION_ALREADY_EXISTS) { | 476 if (result == ERR_SPDY_SESSION_ALREADY_EXISTS) { |
| 468 DCHECK(!transport_socket_handle_->socket()); | 477 DCHECK(!transport_socket_handle_->socket()); |
| 469 return ERR_SPDY_SESSION_ALREADY_EXISTS; | 478 return ERR_SPDY_SESSION_ALREADY_EXISTS; |
| 470 } | 479 } |
| 471 if (result < 0) { | 480 if (result < 0) { |
| 481 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpProxy.ConnectLatency.Secure.Error", |
| 482 base::TimeTicks::Now() - connect_start_time_); |
| 472 if (transport_socket_handle_->socket()) | 483 if (transport_socket_handle_->socket()) |
| 473 transport_socket_handle_->socket()->Disconnect(); | 484 transport_socket_handle_->socket()->Disconnect(); |
| 474 return ERR_PROXY_CONNECTION_FAILED; | 485 return ERR_PROXY_CONNECTION_FAILED; |
| 475 } | 486 } |
| 476 | 487 |
| 477 SSLClientSocket* ssl = | 488 SSLClientSocket* ssl = |
| 478 static_cast<SSLClientSocket*>(transport_socket_handle_->socket()); | 489 static_cast<SSLClientSocket*>(transport_socket_handle_->socket()); |
| 479 negotiated_protocol_ = ssl->GetNegotiatedProtocol(); | 490 negotiated_protocol_ = ssl->GetNegotiatedProtocol(); |
| 480 using_spdy_ = negotiated_protocol_ == kProtoHTTP2; | 491 using_spdy_ = negotiated_protocol_ == kProtoHTTP2; |
| 481 | 492 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 494 next_state_ = STATE_SPDY_PROXY_CREATE_STREAM; | 505 next_state_ = STATE_SPDY_PROXY_CREATE_STREAM; |
| 495 } else { | 506 } else { |
| 496 next_state_ = STATE_HTTP_PROXY_CONNECT; | 507 next_state_ = STATE_HTTP_PROXY_CONNECT; |
| 497 } | 508 } |
| 498 return result; | 509 return result; |
| 499 } | 510 } |
| 500 | 511 |
| 501 int HttpProxyClientSocketWrapper::DoHttpProxyConnect() { | 512 int HttpProxyClientSocketWrapper::DoHttpProxyConnect() { |
| 502 next_state_ = STATE_HTTP_PROXY_CONNECT_COMPLETE; | 513 next_state_ = STATE_HTTP_PROXY_CONNECT_COMPLETE; |
| 503 | 514 |
| 515 if (transport_params_) { |
| 516 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpProxy.ConnectLatency.Insecure.Success", |
| 517 base::TimeTicks::Now() - connect_start_time_); |
| 518 } else { |
| 519 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpProxy.ConnectLatency.Secure.Success", |
| 520 base::TimeTicks::Now() - connect_start_time_); |
| 521 } |
| 522 |
| 504 // Add a HttpProxy connection on top of the tcp socket. | 523 // Add a HttpProxy connection on top of the tcp socket. |
| 505 transport_socket_.reset(new HttpProxyClientSocket( | 524 transport_socket_.reset(new HttpProxyClientSocket( |
| 506 transport_socket_handle_.release(), user_agent_, endpoint_, | 525 transport_socket_handle_.release(), user_agent_, endpoint_, |
| 507 GetDestination().host_port_pair(), http_auth_controller_.get(), tunnel_, | 526 GetDestination().host_port_pair(), http_auth_controller_.get(), tunnel_, |
| 508 using_spdy_, negotiated_protocol_, proxy_delegate_, | 527 using_spdy_, negotiated_protocol_, proxy_delegate_, |
| 509 ssl_params_.get() != nullptr)); | 528 ssl_params_.get() != nullptr)); |
| 510 return transport_socket_->Connect(base::Bind( | 529 return transport_socket_->Connect(base::Bind( |
| 511 &HttpProxyClientSocketWrapper::OnIOComplete, base::Unretained(this))); | 530 &HttpProxyClientSocketWrapper::OnIOComplete, base::Unretained(this))); |
| 512 } | 531 } |
| 513 | 532 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 611 connect_timer_.Stop(); | 630 connect_timer_.Stop(); |
| 612 connect_timer_.Start(FROM_HERE, delay, this, | 631 connect_timer_.Start(FROM_HERE, delay, this, |
| 613 &HttpProxyClientSocketWrapper::ConnectTimeout); | 632 &HttpProxyClientSocketWrapper::ConnectTimeout); |
| 614 } | 633 } |
| 615 | 634 |
| 616 void HttpProxyClientSocketWrapper::ConnectTimeout() { | 635 void HttpProxyClientSocketWrapper::ConnectTimeout() { |
| 617 // Timer shouldn't be running if next_state_ is STATE_NONE. | 636 // Timer shouldn't be running if next_state_ is STATE_NONE. |
| 618 DCHECK_NE(STATE_NONE, next_state_); | 637 DCHECK_NE(STATE_NONE, next_state_); |
| 619 DCHECK(!connect_callback_.is_null()); | 638 DCHECK(!connect_callback_.is_null()); |
| 620 | 639 |
| 640 if (next_state_ == STATE_TCP_CONNECT_COMPLETE || |
| 641 next_state_ == STATE_SSL_CONNECT_COMPLETE) { |
| 642 if (transport_params_) { |
| 643 UMA_HISTOGRAM_MEDIUM_TIMES( |
| 644 "Net.HttpProxy.ConnectLatency.Insecure.TimedOut", |
| 645 base::TimeTicks::Now() - connect_start_time_); |
| 646 } else { |
| 647 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpProxy.ConnectLatency.Secure.TimedOut", |
| 648 base::TimeTicks::Now() - connect_start_time_); |
| 649 } |
| 650 } |
| 651 |
| 621 NotifyProxyDelegateOfCompletion(ERR_CONNECTION_TIMED_OUT); | 652 NotifyProxyDelegateOfCompletion(ERR_CONNECTION_TIMED_OUT); |
| 622 | 653 |
| 623 CompletionCallback callback = connect_callback_; | 654 CompletionCallback callback = connect_callback_; |
| 624 Disconnect(); | 655 Disconnect(); |
| 625 callback.Run(ERR_CONNECTION_TIMED_OUT); | 656 callback.Run(ERR_CONNECTION_TIMED_OUT); |
| 626 } | 657 } |
| 627 | 658 |
| 628 const HostResolver::RequestInfo& | 659 const HostResolver::RequestInfo& |
| 629 HttpProxyClientSocketWrapper::GetDestination() { | 660 HttpProxyClientSocketWrapper::GetDestination() { |
| 630 if (transport_params_) { | 661 if (transport_params_) { |
| 631 return transport_params_->destination(); | 662 return transport_params_->destination(); |
| 632 } else { | 663 } else { |
| 633 return ssl_params_->GetDirectConnectionParams()->destination(); | 664 return ssl_params_->GetDirectConnectionParams()->destination(); |
| 634 } | 665 } |
| 635 } | 666 } |
| 636 | 667 |
| 637 } // namespace net | 668 } // namespace net |
| OLD | NEW |