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 |