diff options
Diffstat (limited to 'net/http/http_network_transaction.cc')
-rw-r--r-- | net/http/http_network_transaction.cc | 133 |
1 files changed, 103 insertions, 30 deletions
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index 159d07e..99a02ba 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; |