#include "net/socket/ssl_client_socket.h"
#include "net/socket/ssl_client_socket_pool.h"
#include "net/socket/transport_client_socket_pool.h"
+#include "net/spdy/hpack_huffman_aggregator.h"
#include "net/spdy/spdy_http_stream.h"
#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_session_pool.h"
proxy_ssl_config_.rev_checking_enabled = false;
}
- // Channel ID is enabled unless --disable-tls-channel-id flag is set,
- // or if privacy mode is enabled.
+ // Channel ID is disabled if privacy mode is enabled for this request.
bool channel_id_enabled = server_ssl_config_.channel_id_enabled &&
- (request_->privacy_mode == kPrivacyModeDisabled);
+ (request_->privacy_mode == PRIVACY_MODE_DISABLED);
server_ssl_config_.channel_id_enabled = channel_id_enabled;
next_state_ = STATE_NOTIFY_BEFORE_CREATE_STREAM;
return stream_->ReadResponseHeaders(io_callback_);
}
-int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() {
- if (!response_.headers.get() && !stream_->IsConnectionReused()) {
- // The connection was closed before any data was sent. Likely an error
- // rather than empty HTTP/0.9 response.
- return ERR_EMPTY_RESPONSE;
- }
-
- return OK;
-}
-
int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
// We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here
// due to SSL renegotiation.
return OK;
}
- if (result < 0 && result != ERR_CONNECTION_CLOSED)
- return HandleIOError(result);
-
- if (result == ERR_CONNECTION_CLOSED && ShouldResendRequest(result)) {
- ResetConnectionAndRequestForResend();
- return OK;
- }
-
// After we call RestartWithAuth a new response_time will be recorded, and
// we need to be cautious about incorrectly logging the duration across the
// authentication activity.
if (result == OK)
LogTransactionConnectedMetrics();
- if (result == ERR_CONNECTION_CLOSED) {
- // For now, if we get at least some data, we do the best we can to make
- // sense of it and send it back up the stack.
- int rv = HandleConnectionClosedBeforeEndOfHeaders();
- if (rv != OK)
- return rv;
- }
+ // ERR_CONNECTION_CLOSED is treated differently at this point; if partial
+ // response headers were received, we do the best we can to make sense of it
+ // and send it back up the stack.
+ //
+ // TODO(davidben): Consider moving this to HttpBasicStream, It's a little
+ // bizarre for SPDY. Assuming this logic is useful at all.
+ // TODO(davidben): Bubble the error code up so we do not cache?
+ if (result == ERR_CONNECTION_CLOSED && response_.headers.get())
+ result = OK;
+
+ if (result < 0)
+ return HandleIOError(result);
+
DCHECK(response_.headers.get());
#if defined(SPDY_PROXY_AUTH_ORIGIN)
// Server-induced fallback; see: http://crbug.com/143712
- if (response_.was_fetched_via_proxy && response_.headers.get() != NULL) {
+ if (response_.was_fetched_via_proxy) {
ProxyService::DataReductionProxyBypassEventType proxy_bypass_event =
ProxyService::BYPASS_EVENT_TYPE_MAX;
- net::HttpResponseHeaders::ChromeProxyInfo chrome_proxy_info;
- bool chrome_proxy_used =
+ bool data_reduction_proxy_used =
proxy_info_.proxy_server().isDataReductionProxy();
- bool chrome_fallback_proxy_used = false;
+ bool data_reduction_fallback_proxy_used = false;
#if defined(DATA_REDUCTION_FALLBACK_HOST)
- if (!chrome_proxy_used) {
- chrome_fallback_proxy_used =
+ if (!data_reduction_proxy_used) {
+ data_reduction_fallback_proxy_used =
proxy_info_.proxy_server().isDataReductionProxyFallback();
}
#endif
- if (chrome_proxy_used || chrome_fallback_proxy_used) {
- // A Via header might not be present in a 304. Since the goal of a 304
- // response is to minimize information transfer, a sender in general
- // should not generate representation metadata other than Cache-Control,
- // Content-Location, Date, ETag, Expires, and Vary.
- if (!response_.headers->IsChromeProxyResponse() &&
- (response_.headers->response_code() != HTTP_NOT_MODIFIED)) {
- proxy_bypass_event = ProxyService::MISSING_VIA_HEADER;
- } else if (response_.headers->GetChromeProxyInfo(&chrome_proxy_info)) {
- if (chrome_proxy_info.bypass_duration < TimeDelta::FromMinutes(30))
- proxy_bypass_event = ProxyService::SHORT_BYPASS;
- else
- proxy_bypass_event = ProxyService::LONG_BYPASS;
- } else {
- // Additionally, fallback if a 500, 502 or 503 is returned via the data
- // reduction proxy. This is conservative, as the 500, 502 or 503 might
- // have been generated by the origin, and not the proxy.
- if (response_.headers->response_code() == HTTP_INTERNAL_SERVER_ERROR ||
- response_.headers->response_code() == HTTP_BAD_GATEWAY ||
- response_.headers->response_code() == HTTP_SERVICE_UNAVAILABLE) {
- proxy_bypass_event = ProxyService::INTERNAL_SERVER_ERROR_BYPASS;
- }
- }
-
+ if (data_reduction_proxy_used || data_reduction_fallback_proxy_used) {
+ net::HttpResponseHeaders::DataReductionProxyInfo
+ data_reduction_proxy_info;
+ proxy_bypass_event
+ = response_.headers->GetDataReductionProxyBypassEventType(
+ &data_reduction_proxy_info);
if (proxy_bypass_event < ProxyService::BYPASS_EVENT_TYPE_MAX) {
ProxyService* proxy_service = session_->proxy_service();
proxy_service->RecordDataReductionProxyBypassInfo(
- chrome_proxy_used, proxy_info_.proxy_server(), proxy_bypass_event);
+ data_reduction_proxy_used, proxy_info_.proxy_server(),
+ proxy_bypass_event);
ProxyServer proxy_server;
#if defined(DATA_REDUCTION_FALLBACK_HOST)
- if (chrome_proxy_used && chrome_proxy_info.bypass_all) {
+ if (data_reduction_proxy_used && data_reduction_proxy_info.bypass_all) {
// TODO(bengr): Rename as DATA_REDUCTION_FALLBACK_ORIGIN.
GURL proxy_url(DATA_REDUCTION_FALLBACK_HOST);
if (proxy_url.SchemeIsHTTPOrHTTPS()) {
#endif
if (proxy_service->MarkProxiesAsBadUntil(
proxy_info_,
- chrome_proxy_info.bypass_duration,
+ data_reduction_proxy_info.bypass_duration,
proxy_server,
net_log_)) {
// Only retry idempotent methods. We don't want to resubmit a POST
stream_->GetSSLInfo(&response_.ssl_info);
headers_valid_ = true;
+
+ if (session_->huffman_aggregator()) {
+ session_->huffman_aggregator()->AggregateTransactionCharacterCounts(
+ *request_,
+ request_headers_,
+ proxy_info_.proxy_server(),
+ *response_.headers);
+ }
return OK;
}
// likely happen when trying to retrieve its IP address.
// See http://crbug.com/105824 for more details.
case ERR_SOCKET_NOT_CONNECTED:
- if (ShouldResendRequest(error)) {
+ // If a socket is closed on its initial request, HttpStreamParser returns
+ // ERR_EMPTY_RESPONSE. This may still be close/reuse race if the socket was
+ // preconnected but failed to be used before the server timed it out.
+ case ERR_EMPTY_RESPONSE:
+ if (ShouldResendRequest()) {
net_log_.AddEventWithNetErrorCode(
NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR, error);
ResetConnectionAndRequestForResend();
return response_.headers.get();
}
-bool HttpNetworkTransaction::ShouldResendRequest(int error) const {
+bool HttpNetworkTransaction::ShouldResendRequest() const {
bool connection_is_proven = stream_->IsConnectionReused();
bool has_received_headers = GetResponseHeaders() != NULL;