Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1127)

Unified Diff: net/http/http_network_transaction.cc

Issue 3029052: Recommit 54405 - Fix late binding induced mismatch of Socket and AuthController (Closed)
Patch Set: Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/http/http_network_transaction.h ('k') | net/http/http_network_transaction_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/http/http_network_transaction.cc
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 09a4772f8b5304f85d0f8a59e85a8d992669fae1..6d77eb1532a7c75f1aaebea486d270d0ea155f14 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -348,7 +348,8 @@ int HttpNetworkTransaction::RestartWithAuth(
if (target == HttpAuth::AUTH_PROXY && using_ssl_ && proxy_info_.is_http()) {
DCHECK(establishing_tunnel_);
- next_state_ = STATE_INIT_CONNECTION;
+ next_state_ = STATE_RESTART_TUNNEL_AUTH;
+ auth_controllers_[target] = NULL;
ResetStateForRestart();
} else {
PrepareForAuthRestart(target);
@@ -549,6 +550,13 @@ int HttpNetworkTransaction::DoLoop(int result) {
case STATE_INIT_CONNECTION_COMPLETE:
rv = DoInitConnectionComplete(rv);
break;
+ case STATE_RESTART_TUNNEL_AUTH:
+ DCHECK_EQ(OK, rv);
+ rv = DoRestartTunnelAuth();
+ break;
+ case STATE_RESTART_TUNNEL_AUTH_COMPLETE:
+ rv = DoRestartTunnelAuthComplete(rv);
+ break;
case STATE_GENERATE_PROXY_AUTH_TOKEN:
DCHECK_EQ(OK, rv);
rv = DoGenerateProxyAuthToken();
@@ -726,15 +734,6 @@ int HttpNetworkTransaction::DoInitConnection() {
DCHECK(proxy_info_.proxy_server().is_valid());
next_state_ = STATE_INIT_CONNECTION_COMPLETE;
- // Now that the proxy server has been resolved, create the auth_controllers_.
- for (int i = 0; i < HttpAuth::AUTH_NUM_TARGETS; i++) {
- HttpAuth::Target target = static_cast<HttpAuth::Target>(i);
- if (!auth_controllers_[target].get())
- auth_controllers_[target] = new HttpAuthController(target,
- AuthURL(target),
- session_);
- }
-
bool want_spdy_over_npn = alternate_protocol_mode_ == kUsingAlternateProtocol
&& alternate_protocol_ == HttpAlternateProtocols::NPN_SPDY_2;
using_ssl_ = request_->url.SchemeIs("https") ||
@@ -784,29 +783,24 @@ int HttpNetworkTransaction::DoInitConnection() {
request_->referrer, disable_resolver_cache);
if (proxy_info_.is_http()) {
- scoped_refptr<HttpAuthController> http_proxy_auth;
GURL authentication_url = request_->url;
- if (using_ssl_) {
- if (!authentication_url.SchemeIs("https")) {
- // If a proxy tunnel connection needs to be established due to
- // an Alternate-Protocol, the URL needs to be changed to indicate
- // https or digest authentication attempts will fail.
- // For example, suppose the initial request was for
- // "http://www.example.com/index.html". If this is an SSL
- // upgrade due to alternate protocol, the digest authorization
- // should have a uri="www.example.com:443" field rather than a
- // "/index.html" entry, even though the original request URL has not
- // changed.
- authentication_url = UpgradeUrlToHttps(authentication_url);
- }
- http_proxy_auth = auth_controllers_[HttpAuth::AUTH_PROXY];
- establishing_tunnel_ = true;
+ if (using_ssl_ && !authentication_url.SchemeIs("https")) {
+ // If a proxy tunnel connection needs to be established due to
+ // an Alternate-Protocol, the URL needs to be changed to indicate
+ // https or digest authentication attempts will fail.
+ // For example, suppose the initial request was for
+ // "http://www.example.com/index.html". If this is an SSL
+ // upgrade due to alternate protocol, the digest authorization
+ // should have a uri="www.example.com:443" field rather than a
+ // "/index.html" entry, even though the original request URL has not
+ // changed.
+ authentication_url = UpgradeUrlToHttps(authentication_url);
}
+ establishing_tunnel_ = using_ssl_;
http_proxy_params = new HttpProxySocketParams(proxy_tcp_params,
authentication_url,
endpoint_,
- http_proxy_auth,
- using_ssl_);
+ session_, using_ssl_);
} else {
DCHECK(proxy_info_.is_socks());
char socks_version;
@@ -914,14 +908,13 @@ int HttpNetworkTransaction::DoInitConnectionComplete(int result) {
if (result == ERR_PROXY_AUTH_REQUESTED) {
DCHECK(!ssl_started);
- const HttpResponseInfo& tunnel_auth_response =
- connection_->ssl_error_response_info();
-
- response_.headers = tunnel_auth_response.headers;
- response_.auth_challenge = tunnel_auth_response.auth_challenge;
- headers_valid_ = true;
- pending_auth_target_ = HttpAuth::AUTH_PROXY;
- return OK;
+ // Other state (i.e. |using_ssl_|) suggests that |connection_| will have an
+ // SSL socket, but there was an error before that could happened. This
+ // puts the in progress HttpProxy socket into |connection_| in order to
+ // complete the auth. The tunnel restart code is carefully to remove it
+ // before returning control to the rest of this class.
+ connection_.reset(connection_->release_pending_http_proxy_connection());
+ return HandleTunnelAuthFailure(result);
}
if ((!ssl_started && result < 0 &&
@@ -1001,12 +994,44 @@ int HttpNetworkTransaction::DoInitConnectionComplete(int result) {
return OK;
}
+int HttpNetworkTransaction::DoRestartTunnelAuth() {
+ next_state_ = STATE_RESTART_TUNNEL_AUTH_COMPLETE;
+ HttpProxyClientSocket* http_proxy_socket =
+ static_cast<HttpProxyClientSocket*>(connection_->socket());
+ return http_proxy_socket->RestartWithAuth(&io_callback_);
+}
+
+int HttpNetworkTransaction::DoRestartTunnelAuthComplete(int result) {
+ if (result == ERR_PROXY_AUTH_REQUESTED)
+ return HandleTunnelAuthFailure(result);
+
+ if (result == OK) {
+ // Now that we've got the HttpProxyClientSocket connected. We have
+ // to release it as an idle socket into the pool and start the connection
+ // process from the beginning. Trying to pass it in with the
+ // SSLSocketParams might cause a deadlock since params are dispatched
+ // interchangeably. This request won't necessarily get this http proxy
+ // socket, but there will be forward progress.
+ connection_->Reset();
+ establishing_tunnel_ = false;
+ next_state_ = STATE_INIT_CONNECTION;
+ return OK;
+ }
+
+ return ReconsiderProxyAfterError(result);
+}
+
int HttpNetworkTransaction::DoGenerateProxyAuthToken() {
next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE;
if (!ShouldApplyProxyAuth())
return OK;
- return auth_controllers_[HttpAuth::AUTH_PROXY]->MaybeGenerateAuthToken(
- request_, &io_callback_, net_log_);
+ HttpAuth::Target target = HttpAuth::AUTH_PROXY;
+ if (!auth_controllers_[target].get())
+ auth_controllers_[target] = new HttpAuthController(target, AuthURL(target),
+ session_);
+ return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
+ &io_callback_,
+ net_log_);
}
int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) {
@@ -1018,10 +1043,15 @@ int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) {
int HttpNetworkTransaction::DoGenerateServerAuthToken() {
next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE;
+ HttpAuth::Target target = HttpAuth::AUTH_SERVER;
+ if (!auth_controllers_[target].get())
+ auth_controllers_[target] = new HttpAuthController(target, AuthURL(target),
+ session_);
if (!ShouldApplyServerAuth())
return OK;
- return auth_controllers_[HttpAuth::AUTH_SERVER]->MaybeGenerateAuthToken(
- request_, &io_callback_, net_log_);
+ return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
+ &io_callback_,
+ net_log_);
}
int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) {
@@ -1544,6 +1574,24 @@ void HttpNetworkTransaction::LogTransactionMetrics() const {
}
}
+int HttpNetworkTransaction::HandleTunnelAuthFailure(int error) {
+ DCHECK(establishing_tunnel_);
+ DCHECK_EQ(ERR_PROXY_AUTH_REQUESTED, error);
+ HttpProxyClientSocket* http_proxy_socket =
+ static_cast<HttpProxyClientSocket*>(connection_->socket());
+
+ const HttpResponseInfo* tunnel_auth_response =
+ http_proxy_socket->GetResponseInfo();
+ response_.headers = tunnel_auth_response->headers;
+ response_.auth_challenge = tunnel_auth_response->auth_challenge;
+ headers_valid_ = true;
+
+ auth_controllers_[HttpAuth::AUTH_PROXY] =
+ http_proxy_socket->auth_controller();
+ pending_auth_target_ = HttpAuth::AUTH_PROXY;
+ return OK;
+}
+
int HttpNetworkTransaction::HandleCertificateError(int error) {
DCHECK(using_ssl_);
DCHECK(IsCertificateError(error));
« no previous file with comments | « net/http/http_network_transaction.h ('k') | net/http/http_network_transaction_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698