| 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 <set> | 7 #include <set> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 if (target == HttpAuth::AUTH_NONE) { | 341 if (target == HttpAuth::AUTH_NONE) { |
| 342 NOTREACHED(); | 342 NOTREACHED(); |
| 343 return ERR_UNEXPECTED; | 343 return ERR_UNEXPECTED; |
| 344 } | 344 } |
| 345 pending_auth_target_ = HttpAuth::AUTH_NONE; | 345 pending_auth_target_ = HttpAuth::AUTH_NONE; |
| 346 | 346 |
| 347 auth_controllers_[target]->ResetAuth(username, password); | 347 auth_controllers_[target]->ResetAuth(username, password); |
| 348 | 348 |
| 349 if (target == HttpAuth::AUTH_PROXY && using_ssl_ && proxy_info_.is_http()) { | 349 if (target == HttpAuth::AUTH_PROXY && using_ssl_ && proxy_info_.is_http()) { |
| 350 DCHECK(establishing_tunnel_); | 350 DCHECK(establishing_tunnel_); |
| 351 next_state_ = STATE_INIT_CONNECTION; | 351 next_state_ = STATE_RESTART_TUNNEL_AUTH; |
| 352 auth_controllers_[target] = NULL; |
| 352 ResetStateForRestart(); | 353 ResetStateForRestart(); |
| 353 } else { | 354 } else { |
| 354 PrepareForAuthRestart(target); | 355 PrepareForAuthRestart(target); |
| 355 } | 356 } |
| 356 | 357 |
| 357 DCHECK(user_callback_ == NULL); | 358 DCHECK(user_callback_ == NULL); |
| 358 int rv = DoLoop(OK); | 359 int rv = DoLoop(OK); |
| 359 if (rv == ERR_IO_PENDING) | 360 if (rv == ERR_IO_PENDING) |
| 360 user_callback_ = callback; | 361 user_callback_ = callback; |
| 361 | 362 |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 case STATE_RESOLVE_PROXY_COMPLETE: | 543 case STATE_RESOLVE_PROXY_COMPLETE: |
| 543 rv = DoResolveProxyComplete(rv); | 544 rv = DoResolveProxyComplete(rv); |
| 544 break; | 545 break; |
| 545 case STATE_INIT_CONNECTION: | 546 case STATE_INIT_CONNECTION: |
| 546 DCHECK_EQ(OK, rv); | 547 DCHECK_EQ(OK, rv); |
| 547 rv = DoInitConnection(); | 548 rv = DoInitConnection(); |
| 548 break; | 549 break; |
| 549 case STATE_INIT_CONNECTION_COMPLETE: | 550 case STATE_INIT_CONNECTION_COMPLETE: |
| 550 rv = DoInitConnectionComplete(rv); | 551 rv = DoInitConnectionComplete(rv); |
| 551 break; | 552 break; |
| 553 case STATE_RESTART_TUNNEL_AUTH: |
| 554 DCHECK_EQ(OK, rv); |
| 555 rv = DoRestartTunnelAuth(); |
| 556 break; |
| 557 case STATE_RESTART_TUNNEL_AUTH_COMPLETE: |
| 558 rv = DoRestartTunnelAuthComplete(rv); |
| 559 break; |
| 552 case STATE_GENERATE_PROXY_AUTH_TOKEN: | 560 case STATE_GENERATE_PROXY_AUTH_TOKEN: |
| 553 DCHECK_EQ(OK, rv); | 561 DCHECK_EQ(OK, rv); |
| 554 rv = DoGenerateProxyAuthToken(); | 562 rv = DoGenerateProxyAuthToken(); |
| 555 break; | 563 break; |
| 556 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE: | 564 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE: |
| 557 rv = DoGenerateProxyAuthTokenComplete(rv); | 565 rv = DoGenerateProxyAuthTokenComplete(rv); |
| 558 break; | 566 break; |
| 559 case STATE_GENERATE_SERVER_AUTH_TOKEN: | 567 case STATE_GENERATE_SERVER_AUTH_TOKEN: |
| 560 DCHECK_EQ(OK, rv); | 568 DCHECK_EQ(OK, rv); |
| 561 rv = DoGenerateServerAuthToken(); | 569 rv = DoGenerateServerAuthToken(); |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 | 727 |
| 720 next_state_ = STATE_INIT_CONNECTION; | 728 next_state_ = STATE_INIT_CONNECTION; |
| 721 return OK; | 729 return OK; |
| 722 } | 730 } |
| 723 | 731 |
| 724 int HttpNetworkTransaction::DoInitConnection() { | 732 int HttpNetworkTransaction::DoInitConnection() { |
| 725 DCHECK(!connection_->is_initialized()); | 733 DCHECK(!connection_->is_initialized()); |
| 726 DCHECK(proxy_info_.proxy_server().is_valid()); | 734 DCHECK(proxy_info_.proxy_server().is_valid()); |
| 727 next_state_ = STATE_INIT_CONNECTION_COMPLETE; | 735 next_state_ = STATE_INIT_CONNECTION_COMPLETE; |
| 728 | 736 |
| 729 // Now that the proxy server has been resolved, create the auth_controllers_. | |
| 730 for (int i = 0; i < HttpAuth::AUTH_NUM_TARGETS; i++) { | |
| 731 HttpAuth::Target target = static_cast<HttpAuth::Target>(i); | |
| 732 if (!auth_controllers_[target].get()) | |
| 733 auth_controllers_[target] = new HttpAuthController(target, | |
| 734 AuthURL(target), | |
| 735 session_); | |
| 736 } | |
| 737 | |
| 738 bool want_spdy_over_npn = alternate_protocol_mode_ == kUsingAlternateProtocol | 737 bool want_spdy_over_npn = alternate_protocol_mode_ == kUsingAlternateProtocol |
| 739 && alternate_protocol_ == HttpAlternateProtocols::NPN_SPDY_2; | 738 && alternate_protocol_ == HttpAlternateProtocols::NPN_SPDY_2; |
| 740 using_ssl_ = request_->url.SchemeIs("https") || | 739 using_ssl_ = request_->url.SchemeIs("https") || |
| 741 (want_spdy_without_npn_ && want_ssl_over_spdy_without_npn_) || | 740 (want_spdy_without_npn_ && want_ssl_over_spdy_without_npn_) || |
| 742 want_spdy_over_npn; | 741 want_spdy_over_npn; |
| 743 using_spdy_ = false; | 742 using_spdy_ = false; |
| 744 response_.was_fetched_via_proxy = !proxy_info_.is_direct(); | 743 response_.was_fetched_via_proxy = !proxy_info_.is_direct(); |
| 745 | 744 |
| 746 // Check first if we have a spdy session for this group. If so, then go | 745 // Check first if we have a spdy session for this group. If so, then go |
| 747 // straight to using that. | 746 // straight to using that. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 777 request_->referrer, | 776 request_->referrer, |
| 778 disable_resolver_cache); | 777 disable_resolver_cache); |
| 779 } else { | 778 } else { |
| 780 ProxyServer proxy_server = proxy_info_.proxy_server(); | 779 ProxyServer proxy_server = proxy_info_.proxy_server(); |
| 781 proxy_host_port.reset(new HostPortPair(proxy_server.host_port_pair())); | 780 proxy_host_port.reset(new HostPortPair(proxy_server.host_port_pair())); |
| 782 scoped_refptr<TCPSocketParams> proxy_tcp_params = | 781 scoped_refptr<TCPSocketParams> proxy_tcp_params = |
| 783 new TCPSocketParams(*proxy_host_port, request_->priority, | 782 new TCPSocketParams(*proxy_host_port, request_->priority, |
| 784 request_->referrer, disable_resolver_cache); | 783 request_->referrer, disable_resolver_cache); |
| 785 | 784 |
| 786 if (proxy_info_.is_http()) { | 785 if (proxy_info_.is_http()) { |
| 787 scoped_refptr<HttpAuthController> http_proxy_auth; | |
| 788 GURL authentication_url = request_->url; | 786 GURL authentication_url = request_->url; |
| 789 if (using_ssl_) { | 787 if (using_ssl_ && !authentication_url.SchemeIs("https")) { |
| 790 if (!authentication_url.SchemeIs("https")) { | 788 // If a proxy tunnel connection needs to be established due to |
| 791 // If a proxy tunnel connection needs to be established due to | 789 // an Alternate-Protocol, the URL needs to be changed to indicate |
| 792 // an Alternate-Protocol, the URL needs to be changed to indicate | 790 // https or digest authentication attempts will fail. |
| 793 // https or digest authentication attempts will fail. | 791 // For example, suppose the initial request was for |
| 794 // For example, suppose the initial request was for | 792 // "http://www.example.com/index.html". If this is an SSL |
| 795 // "http://www.example.com/index.html". If this is an SSL | 793 // upgrade due to alternate protocol, the digest authorization |
| 796 // upgrade due to alternate protocol, the digest authorization | 794 // should have a uri="www.example.com:443" field rather than a |
| 797 // should have a uri="www.example.com:443" field rather than a | 795 // "/index.html" entry, even though the original request URL has not |
| 798 // "/index.html" entry, even though the original request URL has not | 796 // changed. |
| 799 // changed. | 797 authentication_url = UpgradeUrlToHttps(authentication_url); |
| 800 authentication_url = UpgradeUrlToHttps(authentication_url); | |
| 801 } | |
| 802 http_proxy_auth = auth_controllers_[HttpAuth::AUTH_PROXY]; | |
| 803 establishing_tunnel_ = true; | |
| 804 } | 798 } |
| 799 establishing_tunnel_ = using_ssl_; |
| 805 http_proxy_params = new HttpProxySocketParams(proxy_tcp_params, | 800 http_proxy_params = new HttpProxySocketParams(proxy_tcp_params, |
| 806 authentication_url, | 801 authentication_url, |
| 807 endpoint_, | 802 endpoint_, |
| 808 http_proxy_auth, | 803 session_, using_ssl_); |
| 809 using_ssl_); | |
| 810 } else { | 804 } else { |
| 811 DCHECK(proxy_info_.is_socks()); | 805 DCHECK(proxy_info_.is_socks()); |
| 812 char socks_version; | 806 char socks_version; |
| 813 if (proxy_server.scheme() == ProxyServer::SCHEME_SOCKS5) | 807 if (proxy_server.scheme() == ProxyServer::SCHEME_SOCKS5) |
| 814 socks_version = '5'; | 808 socks_version = '5'; |
| 815 else | 809 else |
| 816 socks_version = '4'; | 810 socks_version = '4'; |
| 817 connection_group = | 811 connection_group = |
| 818 StringPrintf("socks%c/%s", socks_version, connection_group.c_str()); | 812 StringPrintf("socks%c/%s", socks_version, connection_group.c_str()); |
| 819 | 813 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 907 if(want_ssl_over_spdy_without_npn_ && want_spdy_without_npn_) | 901 if(want_ssl_over_spdy_without_npn_ && want_spdy_without_npn_) |
| 908 using_spdy_ = true; | 902 using_spdy_ = true; |
| 909 } | 903 } |
| 910 | 904 |
| 911 // We may be using spdy without SSL | 905 // We may be using spdy without SSL |
| 912 if(!want_ssl_over_spdy_without_npn_ && want_spdy_without_npn_) | 906 if(!want_ssl_over_spdy_without_npn_ && want_spdy_without_npn_) |
| 913 using_spdy_ = true; | 907 using_spdy_ = true; |
| 914 | 908 |
| 915 if (result == ERR_PROXY_AUTH_REQUESTED) { | 909 if (result == ERR_PROXY_AUTH_REQUESTED) { |
| 916 DCHECK(!ssl_started); | 910 DCHECK(!ssl_started); |
| 917 const HttpResponseInfo& tunnel_auth_response = | 911 // Other state (i.e. |using_ssl_|) suggests that |connection_| will have an |
| 918 connection_->ssl_error_response_info(); | 912 // SSL socket, but there was an error before that could happened. This |
| 919 | 913 // puts the in progress HttpProxy socket into |connection_| in order to |
| 920 response_.headers = tunnel_auth_response.headers; | 914 // complete the auth. The tunnel restart code is carefully to remove it |
| 921 response_.auth_challenge = tunnel_auth_response.auth_challenge; | 915 // before returning control to the rest of this class. |
| 922 headers_valid_ = true; | 916 connection_.reset(connection_->release_pending_http_proxy_connection()); |
| 923 pending_auth_target_ = HttpAuth::AUTH_PROXY; | 917 return HandleTunnelAuthFailure(result); |
| 924 return OK; | |
| 925 } | 918 } |
| 926 | 919 |
| 927 if ((!ssl_started && result < 0 && | 920 if ((!ssl_started && result < 0 && |
| 928 alternate_protocol_mode_ == kUsingAlternateProtocol) || | 921 alternate_protocol_mode_ == kUsingAlternateProtocol) || |
| 929 result == ERR_NPN_NEGOTIATION_FAILED) { | 922 result == ERR_NPN_NEGOTIATION_FAILED) { |
| 930 // Mark the alternate protocol as broken and fallback. | 923 // Mark the alternate protocol as broken and fallback. |
| 931 MarkBrokenAlternateProtocolAndFallback(); | 924 MarkBrokenAlternateProtocolAndFallback(); |
| 932 return OK; | 925 return OK; |
| 933 } | 926 } |
| 934 | 927 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 994 if (using_spdy_) { | 987 if (using_spdy_) { |
| 995 UpdateConnectionTypeHistograms(CONNECTION_SPDY); | 988 UpdateConnectionTypeHistograms(CONNECTION_SPDY); |
| 996 // TODO(cbentzel): Add auth support to spdy. See http://crbug.com/46620 | 989 // TODO(cbentzel): Add auth support to spdy. See http://crbug.com/46620 |
| 997 next_state_ = STATE_SPDY_GET_STREAM; | 990 next_state_ = STATE_SPDY_GET_STREAM; |
| 998 } else { | 991 } else { |
| 999 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN; | 992 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN; |
| 1000 } | 993 } |
| 1001 return OK; | 994 return OK; |
| 1002 } | 995 } |
| 1003 | 996 |
| 997 int HttpNetworkTransaction::DoRestartTunnelAuth() { |
| 998 next_state_ = STATE_RESTART_TUNNEL_AUTH_COMPLETE; |
| 999 HttpProxyClientSocket* http_proxy_socket = |
| 1000 static_cast<HttpProxyClientSocket*>(connection_->socket()); |
| 1001 return http_proxy_socket->RestartWithAuth(&io_callback_); |
| 1002 } |
| 1003 |
| 1004 int HttpNetworkTransaction::DoRestartTunnelAuthComplete(int result) { |
| 1005 if (result == ERR_PROXY_AUTH_REQUESTED) |
| 1006 return HandleTunnelAuthFailure(result); |
| 1007 |
| 1008 if (result == OK) { |
| 1009 // Now that we've got the HttpProxyClientSocket connected. We have |
| 1010 // to release it as an idle socket into the pool and start the connection |
| 1011 // process from the beginning. Trying to pass it in with the |
| 1012 // SSLSocketParams might cause a deadlock since params are dispatched |
| 1013 // interchangeably. This request won't necessarily get this http proxy |
| 1014 // socket, but there will be forward progress. |
| 1015 connection_->Reset(); |
| 1016 establishing_tunnel_ = false; |
| 1017 next_state_ = STATE_INIT_CONNECTION; |
| 1018 return OK; |
| 1019 } |
| 1020 |
| 1021 return ReconsiderProxyAfterError(result); |
| 1022 } |
| 1023 |
| 1004 int HttpNetworkTransaction::DoGenerateProxyAuthToken() { | 1024 int HttpNetworkTransaction::DoGenerateProxyAuthToken() { |
| 1005 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE; | 1025 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE; |
| 1006 if (!ShouldApplyProxyAuth()) | 1026 if (!ShouldApplyProxyAuth()) |
| 1007 return OK; | 1027 return OK; |
| 1008 return auth_controllers_[HttpAuth::AUTH_PROXY]->MaybeGenerateAuthToken( | 1028 HttpAuth::Target target = HttpAuth::AUTH_PROXY; |
| 1009 request_, &io_callback_, net_log_); | 1029 if (!auth_controllers_[target].get()) |
| 1030 auth_controllers_[target] = new HttpAuthController(target, AuthURL(target), |
| 1031 session_); |
| 1032 return auth_controllers_[target]->MaybeGenerateAuthToken(request_, |
| 1033 &io_callback_, |
| 1034 net_log_); |
| 1010 } | 1035 } |
| 1011 | 1036 |
| 1012 int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) { | 1037 int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) { |
| 1013 DCHECK_NE(ERR_IO_PENDING, rv); | 1038 DCHECK_NE(ERR_IO_PENDING, rv); |
| 1014 if (rv == OK) | 1039 if (rv == OK) |
| 1015 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN; | 1040 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN; |
| 1016 return rv; | 1041 return rv; |
| 1017 } | 1042 } |
| 1018 | 1043 |
| 1019 int HttpNetworkTransaction::DoGenerateServerAuthToken() { | 1044 int HttpNetworkTransaction::DoGenerateServerAuthToken() { |
| 1020 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE; | 1045 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE; |
| 1046 HttpAuth::Target target = HttpAuth::AUTH_SERVER; |
| 1047 if (!auth_controllers_[target].get()) |
| 1048 auth_controllers_[target] = new HttpAuthController(target, AuthURL(target), |
| 1049 session_); |
| 1021 if (!ShouldApplyServerAuth()) | 1050 if (!ShouldApplyServerAuth()) |
| 1022 return OK; | 1051 return OK; |
| 1023 return auth_controllers_[HttpAuth::AUTH_SERVER]->MaybeGenerateAuthToken( | 1052 return auth_controllers_[target]->MaybeGenerateAuthToken(request_, |
| 1024 request_, &io_callback_, net_log_); | 1053 &io_callback_, |
| 1054 net_log_); |
| 1025 } | 1055 } |
| 1026 | 1056 |
| 1027 int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) { | 1057 int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) { |
| 1028 DCHECK_NE(ERR_IO_PENDING, rv); | 1058 DCHECK_NE(ERR_IO_PENDING, rv); |
| 1029 if (rv == OK) | 1059 if (rv == OK) |
| 1030 next_state_ = STATE_SEND_REQUEST; | 1060 next_state_ = STATE_SEND_REQUEST; |
| 1031 return rv; | 1061 return rv; |
| 1032 } | 1062 } |
| 1033 | 1063 |
| 1034 int HttpNetworkTransaction::DoSendRequest() { | 1064 int HttpNetworkTransaction::DoSendRequest() { |
| (...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1537 base::TimeDelta::FromMilliseconds(1), | 1567 base::TimeDelta::FromMilliseconds(1), |
| 1538 base::TimeDelta::FromMinutes(10), 100); | 1568 base::TimeDelta::FromMinutes(10), 100); |
| 1539 if (!reused_socket_) { | 1569 if (!reused_socket_) { |
| 1540 UMA_HISTOGRAM_CLIPPED_TIMES( | 1570 UMA_HISTOGRAM_CLIPPED_TIMES( |
| 1541 "Net.Transaction_Latency_Total_New_Connection_Under_10", | 1571 "Net.Transaction_Latency_Total_New_Connection_Under_10", |
| 1542 total_duration, base::TimeDelta::FromMilliseconds(1), | 1572 total_duration, base::TimeDelta::FromMilliseconds(1), |
| 1543 base::TimeDelta::FromMinutes(10), 100); | 1573 base::TimeDelta::FromMinutes(10), 100); |
| 1544 } | 1574 } |
| 1545 } | 1575 } |
| 1546 | 1576 |
| 1577 int HttpNetworkTransaction::HandleTunnelAuthFailure(int error) { |
| 1578 DCHECK(establishing_tunnel_); |
| 1579 DCHECK_EQ(ERR_PROXY_AUTH_REQUESTED, error); |
| 1580 HttpProxyClientSocket* http_proxy_socket = |
| 1581 static_cast<HttpProxyClientSocket*>(connection_->socket()); |
| 1582 |
| 1583 const HttpResponseInfo* tunnel_auth_response = |
| 1584 http_proxy_socket->GetResponseInfo(); |
| 1585 response_.headers = tunnel_auth_response->headers; |
| 1586 response_.auth_challenge = tunnel_auth_response->auth_challenge; |
| 1587 headers_valid_ = true; |
| 1588 |
| 1589 auth_controllers_[HttpAuth::AUTH_PROXY] = |
| 1590 http_proxy_socket->auth_controller(); |
| 1591 pending_auth_target_ = HttpAuth::AUTH_PROXY; |
| 1592 return OK; |
| 1593 } |
| 1594 |
| 1547 int HttpNetworkTransaction::HandleCertificateError(int error) { | 1595 int HttpNetworkTransaction::HandleCertificateError(int error) { |
| 1548 DCHECK(using_ssl_); | 1596 DCHECK(using_ssl_); |
| 1549 DCHECK(IsCertificateError(error)); | 1597 DCHECK(IsCertificateError(error)); |
| 1550 | 1598 |
| 1551 SSLClientSocket* ssl_socket = | 1599 SSLClientSocket* ssl_socket = |
| 1552 static_cast<SSLClientSocket*>(connection_->socket()); | 1600 static_cast<SSLClientSocket*>(connection_->socket()); |
| 1553 ssl_socket->GetSSLInfo(&response_.ssl_info); | 1601 ssl_socket->GetSSLInfo(&response_.ssl_info); |
| 1554 | 1602 |
| 1555 // Add the bad certificate to the set of allowed certificates in the | 1603 // Add the bad certificate to the set of allowed certificates in the |
| 1556 // SSL info object. This data structure will be consulted after calling | 1604 // SSL info object. This data structure will be consulted after calling |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1880 default: | 1928 default: |
| 1881 return priority; | 1929 return priority; |
| 1882 } | 1930 } |
| 1883 } | 1931 } |
| 1884 | 1932 |
| 1885 | 1933 |
| 1886 | 1934 |
| 1887 #undef STATE_CASE | 1935 #undef STATE_CASE |
| 1888 | 1936 |
| 1889 } // namespace net | 1937 } // namespace net |
| OLD | NEW |