| Index: net/http/http_network_transaction.cc
|
| diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
|
| index 159d07eeafd737cdf5f3f75da0a2584fa683a431..99a02ba41e5a5f23f3feced21cce881725094ae8 100644
|
| --- a/net/http/http_network_transaction.cc
|
| +++ b/net/http/http_network_transaction.cc
|
| @@ -182,7 +182,7 @@ int HttpNetworkTransaction::RestartIgnoringLastError(
|
| if (connection_.socket()->IsConnected()) {
|
| next_state_ = STATE_WRITE_HEADERS;
|
| } else {
|
| - connection_.socket()->Disconnect();
|
| + connection_.set_socket(NULL);
|
| connection_.Reset();
|
| next_state_ = STATE_INIT_CONNECTION;
|
| }
|
| @@ -306,7 +306,7 @@ void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
|
| reused_socket_ = true;
|
| } else {
|
| next_state_ = STATE_INIT_CONNECTION;
|
| - connection_.socket()->Disconnect();
|
| + connection_.set_socket(NULL);
|
| connection_.Reset();
|
| }
|
|
|
| @@ -356,8 +356,10 @@ LoadState HttpNetworkTransaction::GetLoadState() const {
|
| switch (next_state_) {
|
| case STATE_RESOLVE_PROXY_COMPLETE:
|
| return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
|
| - case STATE_INIT_CONNECTION_COMPLETE:
|
| - return connection_.GetLoadState();
|
| + case STATE_RESOLVE_HOST_COMPLETE:
|
| + return LOAD_STATE_RESOLVING_HOST;
|
| + case STATE_TCP_CONNECT_COMPLETE:
|
| + return LOAD_STATE_CONNECTING;
|
| case STATE_WRITE_HEADERS_COMPLETE:
|
| case STATE_WRITE_BODY_COMPLETE:
|
| return LOAD_STATE_SENDING_REQUEST;
|
| @@ -378,10 +380,10 @@ uint64 HttpNetworkTransaction::GetUploadProgress() const {
|
| }
|
|
|
| HttpNetworkTransaction::~HttpNetworkTransaction() {
|
| - // If we still have an open socket, then make sure to disconnect it so we
|
| - // don't try to reuse it later on.
|
| + // If we still have an open socket, then make sure to close it so we don't
|
| + // try to reuse it later on.
|
| if (connection_.is_initialized())
|
| - connection_.socket()->Disconnect();
|
| + connection_.set_socket(NULL);
|
|
|
| if (pac_request_)
|
| session_->proxy_service()->CancelPacRequest(pac_request_);
|
| @@ -429,6 +431,24 @@ int HttpNetworkTransaction::DoLoop(int result) {
|
| rv = DoInitConnectionComplete(rv);
|
| TRACE_EVENT_END("http.init_conn", request_, request_->url.spec());
|
| break;
|
| + case STATE_RESOLVE_HOST:
|
| + DCHECK_EQ(OK, rv);
|
| + TRACE_EVENT_BEGIN("http.resolve_host", request_, request_->url.spec());
|
| + rv = DoResolveHost();
|
| + break;
|
| + case STATE_RESOLVE_HOST_COMPLETE:
|
| + rv = DoResolveHostComplete(rv);
|
| + TRACE_EVENT_END("http.resolve_host", request_, request_->url.spec());
|
| + break;
|
| + case STATE_TCP_CONNECT:
|
| + DCHECK_EQ(OK, rv);
|
| + TRACE_EVENT_BEGIN("http.connect", request_, request_->url.spec());
|
| + rv = DoTCPConnect();
|
| + break;
|
| + case STATE_TCP_CONNECT_COMPLETE:
|
| + rv = DoTCPConnectComplete(rv);
|
| + TRACE_EVENT_END("http.connect", request_, request_->url.spec());
|
| + break;
|
| case STATE_SSL_CONNECT:
|
| DCHECK_EQ(OK, rv);
|
| TRACE_EVENT_BEGIN("http.ssl_connect", request_, request_->url.spec());
|
| @@ -538,41 +558,83 @@ int HttpNetworkTransaction::DoInitConnection() {
|
|
|
| // Build the string used to uniquely identify connections of this type.
|
| std::string connection_group;
|
| - std::string host;
|
| - int port;
|
| - if (using_proxy_ || using_tunnel_) {
|
| - ProxyServer proxy_server = proxy_info_.proxy_server();
|
| - connection_group = "proxy/" + proxy_server.ToURI() + "/";
|
| - host = proxy_server.HostNoBrackets();
|
| - port = proxy_server.port();
|
| - } else {
|
| - host = request_->url.HostNoBrackets();
|
| - port = request_->url.EffectiveIntPort();
|
| - }
|
| + if (using_proxy_ || using_tunnel_)
|
| + connection_group = "proxy/" + proxy_info_.proxy_server().ToURI() + "/";
|
| if (!using_proxy_)
|
| connection_group.append(request_->url.GetOrigin().spec());
|
|
|
| DCHECK(!connection_group.empty());
|
| - int rv = connection_.Init(connection_group, host, port, request_->priority,
|
| - &io_callback_);
|
| - return rv;
|
| + return connection_.Init(connection_group, request_->priority, &io_callback_);
|
| }
|
|
|
| int HttpNetworkTransaction::DoInitConnectionComplete(int result) {
|
| if (result < 0)
|
| - return ReconsiderProxyAfterError(result);
|
| + return result;
|
|
|
| DCHECK(connection_.is_initialized());
|
|
|
| // Set the reused_socket_ flag to indicate that we are using a keep-alive
|
| // connection. This flag is used to handle errors that occur while we are
|
| // trying to reuse a keep-alive connection.
|
| - reused_socket_ = connection_.is_reused();
|
| + reused_socket_ = (connection_.socket() != NULL);
|
| if (reused_socket_) {
|
| next_state_ = STATE_WRITE_HEADERS;
|
| } else {
|
| - // Now we have a TCP connected socket. Perform other connection setup as
|
| - // needed.
|
| + next_state_ = STATE_RESOLVE_HOST;
|
| + }
|
| + return OK;
|
| +}
|
| +
|
| +int HttpNetworkTransaction::DoResolveHost() {
|
| + next_state_ = STATE_RESOLVE_HOST_COMPLETE;
|
| +
|
| + std::string host;
|
| + int port;
|
| +
|
| + // Determine the host and port to connect to.
|
| + if (using_proxy_ || using_tunnel_) {
|
| + ProxyServer proxy_server = proxy_info_.proxy_server();
|
| + host = proxy_server.HostNoBrackets();
|
| + port = proxy_server.port();
|
| + } else {
|
| + // Direct connection
|
| + host = request_->url.HostNoBrackets();
|
| + port = request_->url.EffectiveIntPort();
|
| + }
|
| +
|
| + host_resolution_start_time_ = base::Time::Now();
|
| +
|
| + DidStartDnsResolution(host, this);
|
| + return resolver_.Resolve(host, port, &addresses_, &io_callback_);
|
| +}
|
| +
|
| +int HttpNetworkTransaction::DoResolveHostComplete(int result) {
|
| + bool ok = (result == OK);
|
| + DidFinishDnsResolutionWithStatus(ok, request_->referrer, this);
|
| + if (ok) {
|
| + next_state_ = STATE_TCP_CONNECT;
|
| + } else {
|
| + result = ReconsiderProxyAfterError(result);
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +int HttpNetworkTransaction::DoTCPConnect() {
|
| + next_state_ = STATE_TCP_CONNECT_COMPLETE;
|
| +
|
| + DCHECK(!connection_.socket());
|
| +
|
| + connect_start_time_ = base::Time::Now();
|
| +
|
| + ClientSocket* s = socket_factory_->CreateTCPClientSocket(addresses_);
|
| + connection_.set_socket(s);
|
| + return connection_.socket()->Connect(&io_callback_);
|
| +}
|
| +
|
| +int HttpNetworkTransaction::DoTCPConnectComplete(int result) {
|
| + // If we are using a direct SSL connection, then go ahead and establish the
|
| + // SSL connection, now. Otherwise, we need to first issue a CONNECT request.
|
| + if (result == OK) {
|
| LogTCPConnectedMetrics();
|
| if (using_ssl_ && !using_tunnel_) {
|
| next_state_ = STATE_SSL_CONNECT;
|
| @@ -581,8 +643,10 @@ int HttpNetworkTransaction::DoInitConnectionComplete(int result) {
|
| if (using_tunnel_)
|
| establishing_tunnel_ = true;
|
| }
|
| + } else {
|
| + result = ReconsiderProxyAfterError(result);
|
| }
|
| - return OK;
|
| + return result;
|
| }
|
|
|
| int HttpNetworkTransaction::DoSSLConnect() {
|
| @@ -883,7 +947,7 @@ int HttpNetworkTransaction::DoReadBodyComplete(int result) {
|
| if (done) {
|
| LogTransactionMetrics();
|
| if (!keep_alive)
|
| - connection_.socket()->Disconnect();
|
| + connection_.set_socket(NULL);
|
| connection_.Reset();
|
| // The next Read call will return 0 (EOF).
|
| }
|
| @@ -955,6 +1019,15 @@ int HttpNetworkTransaction::DoDrainBodyForAuthRestartComplete(int result) {
|
| }
|
|
|
| void HttpNetworkTransaction::LogTCPConnectedMetrics() const {
|
| + DCHECK(connect_start_time_ != base::Time());
|
| + base::TimeDelta connect_duration =
|
| + base::Time::Now() - connect_start_time_;
|
| +
|
| + UMA_HISTOGRAM_CLIPPED_TIMES(FieldTrial::MakeName(
|
| + "Net.TCP_Connection_Latency", "DnsImpact").data(), connect_duration,
|
| + base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
|
| + 100);
|
| +
|
| base::TimeDelta host_resolution_and_tcp_connection_latency =
|
| base::Time::Now() - host_resolution_start_time_;
|
|
|
| @@ -1227,7 +1300,7 @@ int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
|
| // This could be a TLS-intolerant server or an SSL 3.0 server that
|
| // chose a TLS-only cipher suite. Turn off TLS 1.0 and retry.
|
| ssl_config_.tls1_enabled = false;
|
| - connection_.socket()->Disconnect();
|
| + connection_.set_socket(NULL);
|
| connection_.Reset();
|
| next_state_ = STATE_INIT_CONNECTION;
|
| error = OK;
|
| @@ -1290,7 +1363,7 @@ bool HttpNetworkTransaction::ShouldResendRequest() const {
|
| }
|
|
|
| void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
|
| - connection_.socket()->Disconnect();
|
| + connection_.set_socket(NULL);
|
| connection_.Reset();
|
| // There are two reasons we need to clear request_headers_. 1) It contains
|
| // the real request headers, but we may need to resend the CONNECT request
|
| @@ -1335,7 +1408,7 @@ int HttpNetworkTransaction::ReconsiderProxyAfterError(int error) {
|
| int rv = session_->proxy_service()->ReconsiderProxyAfterError(
|
| request_->url, &proxy_info_, &io_callback_, &pac_request_);
|
| if (rv == OK || rv == ERR_IO_PENDING) {
|
| - connection_.socket()->Disconnect();
|
| + connection_.set_socket(NULL);
|
| connection_.Reset();
|
| DCHECK(!request_headers_bytes_sent_);
|
| next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
|
|
|