OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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_network_transaction.h" | 5 #include "net/http/http_network_transaction.h" |
6 | 6 |
7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
8 #include "base/field_trial.h" | 8 #include "base/field_trial.h" |
9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
10 #include "base/histogram.h" | 10 #include "base/histogram.h" |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 if (target == HttpAuth::AUTH_NONE) { | 324 if (target == HttpAuth::AUTH_NONE) { |
325 NOTREACHED(); | 325 NOTREACHED(); |
326 return ERR_UNEXPECTED; | 326 return ERR_UNEXPECTED; |
327 } | 327 } |
328 pending_auth_target_ = HttpAuth::AUTH_NONE; | 328 pending_auth_target_ = HttpAuth::AUTH_NONE; |
329 | 329 |
330 auth_controllers_[target]->ResetAuth(username, password); | 330 auth_controllers_[target]->ResetAuth(username, password); |
331 | 331 |
332 if (target == HttpAuth::AUTH_PROXY && using_ssl_ && proxy_info_.is_http()) { | 332 if (target == HttpAuth::AUTH_PROXY && using_ssl_ && proxy_info_.is_http()) { |
333 DCHECK(establishing_tunnel_); | 333 DCHECK(establishing_tunnel_); |
334 next_state_ = STATE_INIT_CONNECTION; | 334 next_state_ = STATE_RESTART_TUNNEL_AUTH; |
| 335 auth_controllers_[target] = NULL; |
335 ResetStateForRestart(); | 336 ResetStateForRestart(); |
336 } else { | 337 } else { |
337 PrepareForAuthRestart(target); | 338 PrepareForAuthRestart(target); |
338 } | 339 } |
339 | 340 |
340 DCHECK(user_callback_ == NULL); | 341 DCHECK(user_callback_ == NULL); |
341 int rv = DoLoop(OK); | 342 int rv = DoLoop(OK); |
342 if (rv == ERR_IO_PENDING) | 343 if (rv == ERR_IO_PENDING) |
343 user_callback_ = callback; | 344 user_callback_ = callback; |
344 | 345 |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 case STATE_RESOLVE_PROXY_COMPLETE: | 526 case STATE_RESOLVE_PROXY_COMPLETE: |
526 rv = DoResolveProxyComplete(rv); | 527 rv = DoResolveProxyComplete(rv); |
527 break; | 528 break; |
528 case STATE_INIT_CONNECTION: | 529 case STATE_INIT_CONNECTION: |
529 DCHECK_EQ(OK, rv); | 530 DCHECK_EQ(OK, rv); |
530 rv = DoInitConnection(); | 531 rv = DoInitConnection(); |
531 break; | 532 break; |
532 case STATE_INIT_CONNECTION_COMPLETE: | 533 case STATE_INIT_CONNECTION_COMPLETE: |
533 rv = DoInitConnectionComplete(rv); | 534 rv = DoInitConnectionComplete(rv); |
534 break; | 535 break; |
| 536 case STATE_RESTART_TUNNEL_AUTH: |
| 537 DCHECK_EQ(OK, rv); |
| 538 rv = DoRestartTunnelAuth(); |
| 539 break; |
| 540 case STATE_RESTART_TUNNEL_AUTH_COMPLETE: |
| 541 rv = DoRestartTunnelAuthComplete(rv); |
| 542 break; |
535 case STATE_GENERATE_PROXY_AUTH_TOKEN: | 543 case STATE_GENERATE_PROXY_AUTH_TOKEN: |
536 DCHECK_EQ(OK, rv); | 544 DCHECK_EQ(OK, rv); |
537 rv = DoGenerateProxyAuthToken(); | 545 rv = DoGenerateProxyAuthToken(); |
538 break; | 546 break; |
539 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE: | 547 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE: |
540 rv = DoGenerateProxyAuthTokenComplete(rv); | 548 rv = DoGenerateProxyAuthTokenComplete(rv); |
541 break; | 549 break; |
542 case STATE_GENERATE_SERVER_AUTH_TOKEN: | 550 case STATE_GENERATE_SERVER_AUTH_TOKEN: |
543 DCHECK_EQ(OK, rv); | 551 DCHECK_EQ(OK, rv); |
544 rv = DoGenerateServerAuthToken(); | 552 rv = DoGenerateServerAuthToken(); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 | 710 |
703 next_state_ = STATE_INIT_CONNECTION; | 711 next_state_ = STATE_INIT_CONNECTION; |
704 return OK; | 712 return OK; |
705 } | 713 } |
706 | 714 |
707 int HttpNetworkTransaction::DoInitConnection() { | 715 int HttpNetworkTransaction::DoInitConnection() { |
708 DCHECK(!connection_->is_initialized()); | 716 DCHECK(!connection_->is_initialized()); |
709 DCHECK(proxy_info_.proxy_server().is_valid()); | 717 DCHECK(proxy_info_.proxy_server().is_valid()); |
710 next_state_ = STATE_INIT_CONNECTION_COMPLETE; | 718 next_state_ = STATE_INIT_CONNECTION_COMPLETE; |
711 | 719 |
712 // Now that the proxy server has been resolved, create the auth_controllers_. | |
713 for (int i = 0; i < HttpAuth::AUTH_NUM_TARGETS; i++) { | |
714 HttpAuth::Target target = static_cast<HttpAuth::Target>(i); | |
715 if (!auth_controllers_[target].get()) | |
716 auth_controllers_[target] = new HttpAuthController(target, | |
717 AuthURL(target), | |
718 session_); | |
719 } | |
720 | |
721 bool want_spdy = alternate_protocol_mode_ == kUsingAlternateProtocol | 720 bool want_spdy = alternate_protocol_mode_ == kUsingAlternateProtocol |
722 && alternate_protocol_ == HttpAlternateProtocols::NPN_SPDY_2; | 721 && alternate_protocol_ == HttpAlternateProtocols::NPN_SPDY_2; |
723 using_ssl_ = request_->url.SchemeIs("https") || want_spdy; | 722 using_ssl_ = request_->url.SchemeIs("https") || want_spdy; |
724 using_spdy_ = false; | 723 using_spdy_ = false; |
725 response_.was_fetched_via_proxy = !proxy_info_.is_direct(); | 724 response_.was_fetched_via_proxy = !proxy_info_.is_direct(); |
726 | 725 |
727 // Use the fixed testing ports if they've been provided. | 726 // Use the fixed testing ports if they've been provided. |
728 if (using_ssl_) { | 727 if (using_ssl_) { |
729 if (session_->fixed_https_port() != 0) | 728 if (session_->fixed_https_port() != 0) |
730 endpoint_.port = session_->fixed_https_port(); | 729 endpoint_.port = session_->fixed_https_port(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
766 disable_resolver_cache); | 765 disable_resolver_cache); |
767 } else { | 766 } else { |
768 ProxyServer proxy_server = proxy_info_.proxy_server(); | 767 ProxyServer proxy_server = proxy_info_.proxy_server(); |
769 proxy_host_port.reset(new HostPortPair(proxy_server.HostNoBrackets(), | 768 proxy_host_port.reset(new HostPortPair(proxy_server.HostNoBrackets(), |
770 proxy_server.port())); | 769 proxy_server.port())); |
771 scoped_refptr<TCPSocketParams> proxy_tcp_params = | 770 scoped_refptr<TCPSocketParams> proxy_tcp_params = |
772 new TCPSocketParams(*proxy_host_port, request_->priority, | 771 new TCPSocketParams(*proxy_host_port, request_->priority, |
773 request_->referrer, disable_resolver_cache); | 772 request_->referrer, disable_resolver_cache); |
774 | 773 |
775 if (proxy_info_.is_http()) { | 774 if (proxy_info_.is_http()) { |
776 scoped_refptr<HttpAuthController> http_proxy_auth; | |
777 GURL authentication_url = request_->url; | 775 GURL authentication_url = request_->url; |
778 if (using_ssl_) { | 776 if (using_ssl_ && !authentication_url.SchemeIs("https")) { |
779 if (!authentication_url.SchemeIs("https")) { | 777 // If a proxy tunnel connection needs to be established due to |
780 // If a proxy tunnel connection needs to be established due to | 778 // an Alternate-Protocol, the URL needs to be changed to indicate |
781 // an Alternate-Protocol, the URL needs to be changed to indicate | 779 // https or digest authentication attempts will fail. |
782 // https or digest authentication attempts will fail. | 780 // For example, suppose the initial request was for |
783 // For example, suppose the initial request was for | 781 // "http://www.example.com/index.html". If this is an SSL |
784 // "http://www.example.com/index.html". If this is an SSL | 782 // upgrade due to alternate protocol, the digest authorization |
785 // upgrade due to alternate protocol, the digest authorization | 783 // should have a uri="www.example.com:443" field rather than a |
786 // should have a uri="www.example.com:443" field rather than a | 784 // "/index.html" entry, even though the original request URL has not |
787 // "/index.html" entry, even though the original request URL has not | 785 // changed. |
788 // changed. | 786 authentication_url = UpgradeUrlToHttps(authentication_url); |
789 authentication_url = UpgradeUrlToHttps(authentication_url); | |
790 } | |
791 http_proxy_auth = auth_controllers_[HttpAuth::AUTH_PROXY]; | |
792 establishing_tunnel_ = true; | |
793 } | 787 } |
| 788 establishing_tunnel_ = using_ssl_; |
794 http_proxy_params = new HttpProxySocketParams(proxy_tcp_params, | 789 http_proxy_params = new HttpProxySocketParams(proxy_tcp_params, |
795 authentication_url, | 790 authentication_url, |
796 endpoint_, | 791 endpoint_, |
797 http_proxy_auth, | 792 session_, using_ssl_); |
798 using_ssl_); | |
799 } else { | 793 } else { |
800 DCHECK(proxy_info_.is_socks()); | 794 DCHECK(proxy_info_.is_socks()); |
801 char socks_version; | 795 char socks_version; |
802 if (proxy_server.scheme() == ProxyServer::SCHEME_SOCKS5) | 796 if (proxy_server.scheme() == ProxyServer::SCHEME_SOCKS5) |
803 socks_version = '5'; | 797 socks_version = '5'; |
804 else | 798 else |
805 socks_version = '4'; | 799 socks_version = '4'; |
806 connection_group = | 800 connection_group = |
807 StringPrintf("socks%c/%s", socks_version, connection_group.c_str()); | 801 StringPrintf("socks%c/%s", socks_version, connection_group.c_str()); |
808 | 802 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
887 std::string proto; | 881 std::string proto; |
888 ssl_socket->GetNextProto(&proto); | 882 ssl_socket->GetNextProto(&proto); |
889 if (SSLClientSocket::NextProtoFromString(proto) == | 883 if (SSLClientSocket::NextProtoFromString(proto) == |
890 SSLClientSocket::kProtoSPDY2) | 884 SSLClientSocket::kProtoSPDY2) |
891 using_spdy_ = true; | 885 using_spdy_ = true; |
892 } | 886 } |
893 } | 887 } |
894 | 888 |
895 if (result == ERR_PROXY_AUTH_REQUESTED) { | 889 if (result == ERR_PROXY_AUTH_REQUESTED) { |
896 DCHECK(!ssl_started); | 890 DCHECK(!ssl_started); |
897 const HttpResponseInfo& tunnel_auth_response = | 891 // Other state (i.e. |using_ssl_|) suggests that |connection_| will have an |
898 connection_->ssl_error_response_info(); | 892 // SSL socket, but there was an error before that could happened. This |
899 | 893 // puts the in progress HttpProxy socket into |connection_| in order to |
900 response_.headers = tunnel_auth_response.headers; | 894 // complete the auth. The tunnel restart code is carefully to remove it |
901 response_.auth_challenge = tunnel_auth_response.auth_challenge; | 895 // before returning control to the rest of this class. |
902 headers_valid_ = true; | 896 connection_.reset(connection_->release_pending_http_proxy_connection()); |
903 pending_auth_target_ = HttpAuth::AUTH_PROXY; | 897 return HandleTunnelAuthFailure(result); |
904 return OK; | |
905 } | 898 } |
906 | 899 |
907 if ((!ssl_started && result < 0 && | 900 if ((!ssl_started && result < 0 && |
908 alternate_protocol_mode_ == kUsingAlternateProtocol) || | 901 alternate_protocol_mode_ == kUsingAlternateProtocol) || |
909 result == ERR_NPN_NEGOTIATION_FAILED) { | 902 result == ERR_NPN_NEGOTIATION_FAILED) { |
910 // Mark the alternate protocol as broken and fallback. | 903 // Mark the alternate protocol as broken and fallback. |
911 MarkBrokenAlternateProtocolAndFallback(); | 904 MarkBrokenAlternateProtocolAndFallback(); |
912 return OK; | 905 return OK; |
913 } | 906 } |
914 | 907 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
964 if (using_spdy_) { | 957 if (using_spdy_) { |
965 UpdateConnectionTypeHistograms(CONNECTION_SPDY); | 958 UpdateConnectionTypeHistograms(CONNECTION_SPDY); |
966 // TODO(cbentzel): Add auth support to spdy. See http://crbug.com/46620 | 959 // TODO(cbentzel): Add auth support to spdy. See http://crbug.com/46620 |
967 next_state_ = STATE_SPDY_GET_STREAM; | 960 next_state_ = STATE_SPDY_GET_STREAM; |
968 } else { | 961 } else { |
969 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN; | 962 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN; |
970 } | 963 } |
971 return OK; | 964 return OK; |
972 } | 965 } |
973 | 966 |
| 967 int HttpNetworkTransaction::DoRestartTunnelAuth() { |
| 968 next_state_ = STATE_RESTART_TUNNEL_AUTH_COMPLETE; |
| 969 HttpProxyClientSocket* http_proxy_socket = |
| 970 static_cast<HttpProxyClientSocket*>(connection_->socket()); |
| 971 return http_proxy_socket->RestartWithAuth(&io_callback_); |
| 972 } |
| 973 |
| 974 int HttpNetworkTransaction::DoRestartTunnelAuthComplete(int result) { |
| 975 if (result == ERR_PROXY_AUTH_REQUESTED) |
| 976 return HandleTunnelAuthFailure(result); |
| 977 |
| 978 if (result == OK) { |
| 979 // Now that we've got the HttpProxyClientSocket connected. We have |
| 980 // to release it as an idle socket into the pool and start the connection |
| 981 // process from the beginning. Trying to pass it in with the |
| 982 // SSLSocketParams might cause a deadlock since params are dispatched |
| 983 // interchangeably. This request won't necessarily get this http proxy |
| 984 // socket, but there will be forward progress. |
| 985 connection_->Reset(); |
| 986 establishing_tunnel_ = false; |
| 987 next_state_ = STATE_INIT_CONNECTION; |
| 988 return OK; |
| 989 } |
| 990 |
| 991 return ReconsiderProxyAfterError(result); |
| 992 } |
| 993 |
974 int HttpNetworkTransaction::DoGenerateProxyAuthToken() { | 994 int HttpNetworkTransaction::DoGenerateProxyAuthToken() { |
975 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE; | 995 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE; |
976 if (!ShouldApplyProxyAuth()) | 996 if (!ShouldApplyProxyAuth()) |
977 return OK; | 997 return OK; |
978 return auth_controllers_[HttpAuth::AUTH_PROXY]->MaybeGenerateAuthToken( | 998 HttpAuth::Target target = HttpAuth::AUTH_PROXY; |
979 request_, &io_callback_, net_log_); | 999 if (!auth_controllers_[target].get()) |
| 1000 auth_controllers_[target] = new HttpAuthController(target, AuthURL(target), |
| 1001 session_); |
| 1002 return auth_controllers_[target]->MaybeGenerateAuthToken(request_, |
| 1003 &io_callback_, |
| 1004 net_log_); |
980 } | 1005 } |
981 | 1006 |
982 int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) { | 1007 int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) { |
983 DCHECK_NE(ERR_IO_PENDING, rv); | 1008 DCHECK_NE(ERR_IO_PENDING, rv); |
984 if (rv == OK) | 1009 if (rv == OK) |
985 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN; | 1010 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN; |
986 return rv; | 1011 return rv; |
987 } | 1012 } |
988 | 1013 |
989 int HttpNetworkTransaction::DoGenerateServerAuthToken() { | 1014 int HttpNetworkTransaction::DoGenerateServerAuthToken() { |
990 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE; | 1015 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE; |
| 1016 HttpAuth::Target target = HttpAuth::AUTH_SERVER; |
| 1017 if (!auth_controllers_[target].get()) |
| 1018 auth_controllers_[target] = new HttpAuthController(target, AuthURL(target), |
| 1019 session_); |
991 if (!ShouldApplyServerAuth()) | 1020 if (!ShouldApplyServerAuth()) |
992 return OK; | 1021 return OK; |
993 return auth_controllers_[HttpAuth::AUTH_SERVER]->MaybeGenerateAuthToken( | 1022 return auth_controllers_[target]->MaybeGenerateAuthToken(request_, |
994 request_, &io_callback_, net_log_); | 1023 &io_callback_, |
| 1024 net_log_); |
995 } | 1025 } |
996 | 1026 |
997 int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) { | 1027 int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) { |
998 DCHECK_NE(ERR_IO_PENDING, rv); | 1028 DCHECK_NE(ERR_IO_PENDING, rv); |
999 if (rv == OK) | 1029 if (rv == OK) |
1000 next_state_ = STATE_SEND_REQUEST; | 1030 next_state_ = STATE_SEND_REQUEST; |
1001 return rv; | 1031 return rv; |
1002 } | 1032 } |
1003 | 1033 |
1004 int HttpNetworkTransaction::DoSendRequest() { | 1034 int HttpNetworkTransaction::DoSendRequest() { |
(...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1498 base::TimeDelta::FromMilliseconds(1), | 1528 base::TimeDelta::FromMilliseconds(1), |
1499 base::TimeDelta::FromMinutes(10), 100); | 1529 base::TimeDelta::FromMinutes(10), 100); |
1500 if (!reused_socket_) { | 1530 if (!reused_socket_) { |
1501 UMA_HISTOGRAM_CLIPPED_TIMES( | 1531 UMA_HISTOGRAM_CLIPPED_TIMES( |
1502 "Net.Transaction_Latency_Total_New_Connection_Under_10", | 1532 "Net.Transaction_Latency_Total_New_Connection_Under_10", |
1503 total_duration, base::TimeDelta::FromMilliseconds(1), | 1533 total_duration, base::TimeDelta::FromMilliseconds(1), |
1504 base::TimeDelta::FromMinutes(10), 100); | 1534 base::TimeDelta::FromMinutes(10), 100); |
1505 } | 1535 } |
1506 } | 1536 } |
1507 | 1537 |
| 1538 int HttpNetworkTransaction::HandleTunnelAuthFailure(int error) { |
| 1539 DCHECK(establishing_tunnel_); |
| 1540 DCHECK_EQ(ERR_PROXY_AUTH_REQUESTED, error); |
| 1541 HttpProxyClientSocket* http_proxy_socket = |
| 1542 static_cast<HttpProxyClientSocket*>(connection_->socket()); |
| 1543 |
| 1544 const HttpResponseInfo* tunnel_auth_response = |
| 1545 http_proxy_socket->GetResponseInfo(); |
| 1546 response_.headers = tunnel_auth_response->headers; |
| 1547 response_.auth_challenge = tunnel_auth_response->auth_challenge; |
| 1548 headers_valid_ = true; |
| 1549 |
| 1550 auth_controllers_[HttpAuth::AUTH_PROXY] = |
| 1551 http_proxy_socket->auth_controller(); |
| 1552 pending_auth_target_ = HttpAuth::AUTH_PROXY; |
| 1553 return OK; |
| 1554 } |
| 1555 |
1508 int HttpNetworkTransaction::HandleCertificateError(int error) { | 1556 int HttpNetworkTransaction::HandleCertificateError(int error) { |
1509 DCHECK(using_ssl_); | 1557 DCHECK(using_ssl_); |
1510 DCHECK(IsCertificateError(error)); | 1558 DCHECK(IsCertificateError(error)); |
1511 | 1559 |
1512 SSLClientSocket* ssl_socket = | 1560 SSLClientSocket* ssl_socket = |
1513 static_cast<SSLClientSocket*>(connection_->socket()); | 1561 static_cast<SSLClientSocket*>(connection_->socket()); |
1514 ssl_socket->GetSSLInfo(&response_.ssl_info); | 1562 ssl_socket->GetSSLInfo(&response_.ssl_info); |
1515 | 1563 |
1516 // Add the bad certificate to the set of allowed certificates in the | 1564 // Add the bad certificate to the set of allowed certificates in the |
1517 // SSL info object. This data structure will be consulted after calling | 1565 // SSL info object. This data structure will be consulted after calling |
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1824 default: | 1872 default: |
1825 description = StringPrintf("Unknown state 0x%08X (%u)", state, state); | 1873 description = StringPrintf("Unknown state 0x%08X (%u)", state, state); |
1826 break; | 1874 break; |
1827 } | 1875 } |
1828 return description; | 1876 return description; |
1829 } | 1877 } |
1830 | 1878 |
1831 #undef STATE_CASE | 1879 #undef STATE_CASE |
1832 | 1880 |
1833 } // namespace net | 1881 } // namespace net |
OLD | NEW |