blob: 0a88bb813ed4e3a00425d7ab02bd3f9a5b27f7ab [file] [log] [blame]
[email protected]49ed6cc2012-02-02 08:59:161// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]d102f542010-06-30 14:51:052// Use of this source code is governed by a BSD-style license that can be
license.botbf09a502008-08-24 00:55:553// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
5#include "net/http/http_network_transaction.h"
6
[email protected]2fbaecf22010-07-22 22:20:357#include <set>
8#include <vector>
9
[email protected]49639fa2011-12-20 23:22:4110#include "base/bind.h"
11#include "base/bind_helpers.h"
[email protected]68bf9152008-09-25 19:47:3012#include "base/compiler_specific.h"
[email protected]270c6412010-03-29 22:02:4713#include "base/format_macros.h"
[email protected]3b63f8f42011-03-28 01:54:1514#include "base/memory/scoped_ptr.h"
[email protected]835d7c82010-10-14 04:38:3815#include "base/metrics/field_trial.h"
16#include "base/metrics/histogram.h"
17#include "base/metrics/stats_counters.h"
[email protected]7286e3fc2011-07-19 22:13:2418#include "base/stl_util.h"
[email protected]528c56d2010-07-30 19:28:4419#include "base/string_number_conversions.h"
[email protected]d8eb84242010-09-25 02:25:0620#include "base/string_util.h"
21#include "base/stringprintf.h"
[email protected]68bf9152008-09-25 19:47:3022#include "build/build_config.h"
[email protected]631f1322010-04-30 17:59:1123#include "googleurl/src/gurl.h"
[email protected]277d5942010-08-11 21:02:3524#include "net/base/auth.h"
[email protected]2d6728692011-03-12 01:39:5525#include "net/base/host_port_pair.h"
[email protected]74a85ce2009-02-12 00:03:1926#include "net/base/io_buffer.h"
initial.commit586acc5fe2008-07-26 22:42:5227#include "net/base/load_flags.h"
[email protected]597cf6e2009-05-29 09:43:2628#include "net/base/net_errors.h"
[email protected]c3b35c22008-09-27 03:19:4229#include "net/base/net_util.h"
[email protected]0b45559b2009-06-12 21:45:1130#include "net/base/ssl_cert_request_info.h"
[email protected]fc7de492010-07-12 14:49:0431#include "net/base/ssl_connection_status_flags.h"
initial.commit586acc5fe2008-07-26 22:42:5232#include "net/base/upload_data_stream.h"
[email protected]c3b35c22008-09-27 03:19:4233#include "net/http/http_auth.h"
34#include "net/http/http_auth_handler.h"
[email protected]fa82f932010-05-20 11:09:2435#include "net/http/http_auth_handler_factory.h"
[email protected]8d5a34e2009-06-11 21:21:3636#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5237#include "net/http/http_chunked_decoder.h"
[email protected]a7ea8832010-07-12 17:54:5438#include "net/http/http_net_log_params.h"
initial.commit586acc5fe2008-07-26 22:42:5239#include "net/http/http_network_session.h"
[email protected]a7ea8832010-07-12 17:54:5440#include "net/http/http_proxy_client_socket.h"
[email protected]e772db3f2010-07-12 18:11:1341#include "net/http/http_proxy_client_socket_pool.h"
[email protected]270c6412010-03-29 22:02:4742#include "net/http/http_request_headers.h"
initial.commit586acc5fe2008-07-26 22:42:5243#include "net/http/http_request_info.h"
[email protected]319d9e6f2009-02-18 19:47:2144#include "net/http/http_response_headers.h"
[email protected]0877e3d2009-10-17 22:29:5745#include "net/http/http_response_info.h"
[email protected]17291a022011-10-10 07:32:5346#include "net/http/http_server_properties.h"
[email protected]9094b602012-02-27 21:44:5847#include "net/http/http_status_code.h"
[email protected]102e27c2011-02-23 01:01:3148#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5249#include "net/http/http_util.h"
[email protected]d7f16632010-03-29 18:02:3650#include "net/http/url_security_manager.h"
[email protected]f7984fc62009-06-22 23:26:4451#include "net/socket/client_socket_factory.h"
[email protected]a796bcec2010-03-22 17:17:2652#include "net/socket/socks_client_socket_pool.h"
[email protected]f7984fc62009-06-22 23:26:4453#include "net/socket/ssl_client_socket.h"
[email protected]e60e47a2010-07-14 03:37:1854#include "net/socket/ssl_client_socket_pool.h"
[email protected]ab739042011-04-07 15:22:2855#include "net/socket/transport_client_socket_pool.h"
[email protected]65d56aa2010-06-14 04:13:4056#include "net/spdy/spdy_http_stream.h"
[email protected]dab9c7d2010-02-06 21:44:3257#include "net/spdy/spdy_session.h"
58#include "net/spdy/spdy_session_pool.h"
initial.commit586acc5fe2008-07-26 22:42:5259
[email protected]e1acf6f2008-10-27 20:43:3360using base::Time;
61
initial.commit586acc5fe2008-07-26 22:42:5262namespace net {
63
[email protected]1c773ea12009-04-28 19:58:4264namespace {
65
[email protected]8e6441ca2010-08-19 05:56:3866void ProcessAlternateProtocol(HttpStreamFactory* factory,
[email protected]17291a022011-10-10 07:32:5367 HttpServerProperties* http_server_properties,
[email protected]8e6441ca2010-08-19 05:56:3868 const HttpResponseHeaders& headers,
69 const HostPortPair& http_host_port_pair) {
[email protected]564b4912010-03-09 16:30:4270 std::string alternate_protocol_str;
[email protected]8e6441ca2010-08-19 05:56:3871
[email protected]17291a022011-10-10 07:32:5372 if (!headers.EnumerateHeader(NULL, kAlternateProtocolHeader,
[email protected]564b4912010-03-09 16:30:4273 &alternate_protocol_str)) {
74 // Header is not present.
75 return;
76 }
77
[email protected]17291a022011-10-10 07:32:5378 factory->ProcessAlternateProtocol(http_server_properties,
[email protected]8e6441ca2010-08-19 05:56:3879 alternate_protocol_str,
80 http_host_port_pair);
[email protected]f45c1ee2010-08-03 00:54:3081}
82
[email protected]a1cb2cd2011-02-05 02:02:0883// Returns true if |error| is a client certificate authentication error.
84bool IsClientCertificateError(int error) {
85 switch (error) {
86 case ERR_BAD_SSL_CLIENT_AUTH_CERT:
87 case ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED:
88 case ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY:
89 case ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED:
90 return true;
91 default:
92 return false;
93 }
94}
95
[email protected]1c773ea12009-04-28 19:58:4296} // namespace
97
initial.commit586acc5fe2008-07-26 22:42:5298//-----------------------------------------------------------------------------
99
[email protected]5695b8c2009-09-30 21:36:43100HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session)
[email protected]0757e7702009-03-27 04:00:22101 : pending_auth_target_(HttpAuth::AUTH_NONE),
[email protected]49639fa2011-12-20 23:22:41102 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(
103 base::Bind(&HttpNetworkTransaction::OnIOComplete,
104 base::Unretained(this)))),
initial.commit586acc5fe2008-07-26 22:42:52105 session_(session),
106 request_(NULL),
[email protected]0877e3d2009-10-17 22:29:57107 headers_valid_(false),
[email protected]8e3d2d32010-06-13 18:46:23108 logged_response_time_(false),
[email protected]b94f92d2010-10-27 16:45:20109 request_headers_(),
initial.commit586acc5fe2008-07-26 22:42:52110 read_buf_len_(0),
[email protected]a7ea8832010-07-12 17:54:54111 next_state_(STATE_NONE),
112 establishing_tunnel_(false) {
[email protected]102957f2011-09-02 17:10:14113 session->ssl_config_service()->GetSSLConfig(&server_ssl_config_);
[email protected]5285d972011-10-18 18:56:34114 if (session->http_stream_factory()->has_next_protos()) {
[email protected]102957f2011-09-02 17:10:14115 server_ssl_config_.next_protos =
[email protected]5285d972011-10-18 18:56:34116 session->http_stream_factory()->next_protos();
[email protected]102957f2011-09-02 17:10:14117 }
[email protected]99ffa5a2011-10-06 04:20:19118 proxy_ssl_config_ = server_ssl_config_;
[email protected]3ce7df0f2010-03-03 00:30:50119}
120
[email protected]0b0bf032010-09-21 18:08:50121HttpNetworkTransaction::~HttpNetworkTransaction() {
122 if (stream_.get()) {
123 HttpResponseHeaders* headers = GetResponseHeaders();
124 // TODO(mbelshe): The stream_ should be able to compute whether or not the
125 // stream should be kept alive. No reason to compute here
126 // and pass it in.
127 bool try_to_keep_alive =
128 next_state_ == STATE_NONE &&
129 stream_->CanFindEndOfResponse() &&
130 (!headers || headers->IsKeepAlive());
131 if (!try_to_keep_alive) {
132 stream_->Close(true /* not reusable */);
133 } else {
134 if (stream_->IsResponseBodyComplete()) {
135 // If the response body is complete, we can just reuse the socket.
136 stream_->Close(false /* reusable */);
[email protected]3a8d6852011-03-11 23:43:44137 } else if (stream_->IsSpdyHttpStream()) {
138 // Doesn't really matter for SpdyHttpStream. Just close it.
139 stream_->Close(true /* not reusable */);
[email protected]0b0bf032010-09-21 18:08:50140 } else {
141 // Otherwise, we try to drain the response body.
[email protected]5a60c8b2011-10-19 20:14:29142 HttpStream* stream = stream_.release();
143 stream->Drain(session_);
[email protected]0b0bf032010-09-21 18:08:50144 }
145 }
146 }
[email protected]0b0bf032010-09-21 18:08:50147}
148
[email protected]684970b2009-08-14 04:54:46149int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
[email protected]49639fa2011-12-20 23:22:41150 const CompletionCallback& callback,
[email protected]9e743cd2010-03-16 07:03:53151 const BoundNetLog& net_log) {
[email protected]5e2e6c77d12009-12-24 21:57:16152 SIMPLE_STATS_COUNTER("HttpNetworkTransaction.Count");
[email protected]5d0153c512009-01-12 19:08:36153
[email protected]9e743cd2010-03-16 07:03:53154 net_log_ = net_log;
[email protected]96d570e42008-08-05 22:43:04155 request_ = request_info;
[email protected]21b316a2009-03-23 18:25:06156 start_time_ = base::Time::Now();
[email protected]96d570e42008-08-05 22:43:04157
[email protected]99ffa5a2011-10-06 04:20:19158 if (request_->load_flags & LOAD_DISABLE_CERT_REVOCATION_CHECKING) {
[email protected]102957f2011-09-02 17:10:14159 server_ssl_config_.rev_checking_enabled = false;
[email protected]99ffa5a2011-10-06 04:20:19160 proxy_ssl_config_.rev_checking_enabled = false;
161 }
[email protected]6fbac162011-06-20 00:29:04162
[email protected]82918cc2010-08-25 17:24:50163 next_state_ = STATE_CREATE_STREAM;
[email protected]96d570e42008-08-05 22:43:04164 int rv = DoLoop(OK);
165 if (rv == ERR_IO_PENDING)
[email protected]49639fa2011-12-20 23:22:41166 callback_ = callback;
[email protected]96d570e42008-08-05 22:43:04167 return rv;
168}
169
170int HttpNetworkTransaction::RestartIgnoringLastError(
[email protected]49639fa2011-12-20 23:22:41171 const CompletionCallback& callback) {
[email protected]8e6441ca2010-08-19 05:56:38172 DCHECK(!stream_.get());
173 DCHECK(!stream_request_.get());
174 DCHECK_EQ(STATE_NONE, next_state_);
175
[email protected]82918cc2010-08-25 17:24:50176 next_state_ = STATE_CREATE_STREAM;
[email protected]8e6441ca2010-08-19 05:56:38177
[email protected]ccb40e52008-09-17 20:54:40178 int rv = DoLoop(OK);
179 if (rv == ERR_IO_PENDING)
[email protected]49639fa2011-12-20 23:22:41180 callback_ = callback;
[email protected]aaead502008-10-15 00:20:11181 return rv;
[email protected]96d570e42008-08-05 22:43:04182}
183
[email protected]0b45559b2009-06-12 21:45:11184int HttpNetworkTransaction::RestartWithCertificate(
[email protected]49639fa2011-12-20 23:22:41185 X509Certificate* client_cert, const CompletionCallback& callback) {
[email protected]8e6441ca2010-08-19 05:56:38186 // In HandleCertificateRequest(), we always tear down existing stream
187 // requests to force a new connection. So we shouldn't have one here.
188 DCHECK(!stream_request_.get());
189 DCHECK(!stream_.get());
190 DCHECK_EQ(STATE_NONE, next_state_);
191
[email protected]102957f2011-09-02 17:10:14192 SSLConfig* ssl_config = response_.cert_request_info->is_proxy ?
193 &proxy_ssl_config_ : &server_ssl_config_;
194 ssl_config->send_client_cert = true;
195 ssl_config->client_cert = client_cert;
[email protected]ec229bc92010-11-22 09:51:45196 session_->ssl_client_auth_cache()->Add(
197 response_.cert_request_info->host_and_port, client_cert);
[email protected]0b45559b2009-06-12 21:45:11198 // Reset the other member variables.
199 // Note: this is necessary only with SSL renegotiation.
200 ResetStateForRestart();
[email protected]82918cc2010-08-25 17:24:50201 next_state_ = STATE_CREATE_STREAM;
[email protected]0b45559b2009-06-12 21:45:11202 int rv = DoLoop(OK);
203 if (rv == ERR_IO_PENDING)
[email protected]49639fa2011-12-20 23:22:41204 callback_ = callback;
[email protected]0b45559b2009-06-12 21:45:11205 return rv;
206}
207
[email protected]49639fa2011-12-20 23:22:41208int HttpNetworkTransaction::RestartWithAuth(
209 const AuthCredentials& credentials, const CompletionCallback& callback) {
[email protected]0757e7702009-03-27 04:00:22210 HttpAuth::Target target = pending_auth_target_;
211 if (target == HttpAuth::AUTH_NONE) {
212 NOTREACHED();
213 return ERR_UNEXPECTED;
214 }
[email protected]0757e7702009-03-27 04:00:22215 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:42216
[email protected]f3cf9802011-10-28 18:44:58217 auth_controllers_[target]->ResetAuth(credentials);
[email protected]e772db3f2010-07-12 18:11:13218
[email protected]49639fa2011-12-20 23:22:41219 DCHECK(callback_.is_null());
[email protected]8e6441ca2010-08-19 05:56:38220
221 int rv = OK;
222 if (target == HttpAuth::AUTH_PROXY && establishing_tunnel_) {
223 // In this case, we've gathered credentials for use with proxy
224 // authentication of a tunnel.
[email protected]82918cc2010-08-25 17:24:50225 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38226 DCHECK(stream_request_ != NULL);
[email protected]394816e92010-08-03 07:38:59227 auth_controllers_[target] = NULL;
[email protected]a7ea8832010-07-12 17:54:54228 ResetStateForRestart();
[email protected]f3cf9802011-10-28 18:44:58229 rv = stream_request_->RestartTunnelWithProxyAuth(credentials);
[email protected]a7ea8832010-07-12 17:54:54230 } else {
[email protected]8e6441ca2010-08-19 05:56:38231 // In this case, we've gathered credentials for the server or the proxy
232 // but it is not during the tunneling phase.
233 DCHECK(stream_request_ == NULL);
[email protected]a7ea8832010-07-12 17:54:54234 PrepareForAuthRestart(target);
[email protected]8e6441ca2010-08-19 05:56:38235 rv = DoLoop(OK);
[email protected]a7ea8832010-07-12 17:54:54236 }
[email protected]c3b35c22008-09-27 03:19:42237
[email protected]c3b35c22008-09-27 03:19:42238 if (rv == ERR_IO_PENDING)
[email protected]49639fa2011-12-20 23:22:41239 callback_ = callback;
[email protected]c3b35c22008-09-27 03:19:42240 return rv;
[email protected]96d570e42008-08-05 22:43:04241}
242
[email protected]f9ee6b52008-11-08 06:46:23243void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) {
244 DCHECK(HaveAuth(target));
[email protected]8e6441ca2010-08-19 05:56:38245 DCHECK(!stream_request_.get());
246
[email protected]2d2697f92009-02-18 21:00:32247 bool keep_alive = false;
[email protected]0877e3d2009-10-17 22:29:57248 // Even if the server says the connection is keep-alive, we have to be
249 // able to find the end of each response in order to reuse the connection.
250 if (GetResponseHeaders()->IsKeepAlive() &&
[email protected]351ab642010-08-05 16:55:31251 stream_->CanFindEndOfResponse()) {
[email protected]0877e3d2009-10-17 22:29:57252 // If the response body hasn't been completely read, we need to drain
253 // it first.
[email protected]351ab642010-08-05 16:55:31254 if (!stream_->IsResponseBodyComplete()) {
[email protected]2d2697f92009-02-18 21:00:32255 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
[email protected]0877e3d2009-10-17 22:29:57256 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket.
[email protected]2d2697f92009-02-18 21:00:32257 read_buf_len_ = kDrainBodyBufferSize;
258 return;
259 }
[email protected]0877e3d2009-10-17 22:29:57260 keep_alive = true;
[email protected]37832c6d2009-06-05 19:44:09261 }
262
[email protected]2d2697f92009-02-18 21:00:32263 // We don't need to drain the response body, so we act as if we had drained
264 // the response body.
265 DidDrainBodyForAuthRestart(keep_alive);
266}
267
268void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
[email protected]8e6441ca2010-08-19 05:56:38269 DCHECK(!stream_request_.get());
270
271 if (stream_.get()) {
[email protected]697ef4c2010-10-14 16:38:58272 HttpStream* new_stream = NULL;
[email protected]2d0a4f92011-05-05 16:38:46273 if (keep_alive && stream_->IsConnectionReusable()) {
[email protected]8e6441ca2010-08-19 05:56:38274 // We should call connection_->set_idle_time(), but this doesn't occur
275 // often enough to be worth the trouble.
276 stream_->SetConnectionReused();
[email protected]697ef4c2010-10-14 16:38:58277 new_stream = stream_->RenewStreamForAuth();
[email protected]8e6441ca2010-08-19 05:56:38278 }
[email protected]697ef4c2010-10-14 16:38:58279
280 if (!new_stream) {
[email protected]2d0a4f92011-05-05 16:38:46281 // Close the stream and mark it as not_reusable. Even in the
282 // keep_alive case, we've determined that the stream_ is not
283 // reusable if new_stream is NULL.
284 stream_->Close(true);
[email protected]697ef4c2010-10-14 16:38:58285 next_state_ = STATE_CREATE_STREAM;
286 } else {
287 next_state_ = STATE_INIT_STREAM;
288 }
289 stream_.reset(new_stream);
[email protected]2d2697f92009-02-18 21:00:32290 }
[email protected]f9ee6b52008-11-08 06:46:23291
292 // Reset the other member variables.
[email protected]697ef4c2010-10-14 16:38:58293 ResetStateForAuthRestart();
[email protected]f9ee6b52008-11-08 06:46:23294}
295
[email protected]8e6441ca2010-08-19 05:56:38296bool HttpNetworkTransaction::IsReadyToRestartForAuth() {
297 return pending_auth_target_ != HttpAuth::AUTH_NONE &&
298 HaveAuth(pending_auth_target_);
299}
300
[email protected]9dea9e1f2009-01-29 00:30:47301int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
[email protected]49639fa2011-12-20 23:22:41302 const CompletionCallback& callback) {
[email protected]96d570e42008-08-05 22:43:04303 DCHECK(buf);
[email protected]e0c27be2009-07-15 13:09:35304 DCHECK_LT(0, buf_len);
[email protected]96d570e42008-08-05 22:43:04305
[email protected]1f14a912009-12-21 20:32:44306 State next_state = STATE_NONE;
[email protected]96d570e42008-08-05 22:43:04307
[email protected]ad8e04a2010-11-01 04:16:27308 scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders());
[email protected]8e6441ca2010-08-19 05:56:38309 if (headers_valid_ && headers.get() && stream_request_.get()) {
[email protected]8a1f3312010-05-25 19:25:04310 // We're trying to read the body of the response but we're still trying
[email protected]511f6f52010-12-17 03:58:29311 // to establish an SSL tunnel through an HTTP proxy. We can't read these
[email protected]8a1f3312010-05-25 19:25:04312 // bytes when establishing a tunnel because they might be controlled by
313 // an active network attacker. We don't worry about this for HTTP
314 // because an active network attacker can already control HTTP sessions.
[email protected]511f6f52010-12-17 03:58:29315 // We reach this case when the user cancels a 407 proxy auth prompt. We
316 // also don't worry about this for an HTTPS Proxy, because the
317 // communication with the proxy is secure.
[email protected]8a1f3312010-05-25 19:25:04318 // See http://crbug.com/8473.
[email protected]2df19bb2010-08-25 20:13:46319 DCHECK(proxy_info_.is_http() || proxy_info_.is_https());
[email protected]9094b602012-02-27 21:44:58320 DCHECK_EQ(headers->response_code(), HTTP_PROXY_AUTHENTICATION_REQUIRED);
[email protected]a7ea8832010-07-12 17:54:54321 LOG(WARNING) << "Blocked proxy response with status "
322 << headers->response_code() << " to CONNECT request for "
323 << GetHostAndPort(request_->url) << ".";
[email protected]8a1f3312010-05-25 19:25:04324 return ERR_TUNNEL_CONNECTION_FAILED;
[email protected]a8e9b162009-03-12 00:06:44325 }
326
[email protected]e60e47a2010-07-14 03:37:18327 // Are we using SPDY or HTTP?
[email protected]351ab642010-08-05 16:55:31328 next_state = STATE_READ_BODY;
[email protected]e60e47a2010-07-14 03:37:18329
[email protected]96d570e42008-08-05 22:43:04330 read_buf_ = buf;
331 read_buf_len_ = buf_len;
332
[email protected]1f14a912009-12-21 20:32:44333 next_state_ = next_state;
[email protected]96d570e42008-08-05 22:43:04334 int rv = DoLoop(OK);
335 if (rv == ERR_IO_PENDING)
[email protected]49639fa2011-12-20 23:22:41336 callback_ = callback;
[email protected]96d570e42008-08-05 22:43:04337 return rv;
338}
339
340const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const {
[email protected]a7e41312009-12-16 23:18:14341 return ((headers_valid_ && response_.headers) || response_.ssl_info.cert ||
342 response_.cert_request_info) ? &response_ : NULL;
[email protected]96d570e42008-08-05 22:43:04343}
344
345LoadState HttpNetworkTransaction::GetLoadState() const {
346 // TODO(wtc): Define a new LoadState value for the
347 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request.
348 switch (next_state_) {
[email protected]82918cc2010-08-25 17:24:50349 case STATE_CREATE_STREAM_COMPLETE:
[email protected]8e6441ca2010-08-19 05:56:38350 return stream_request_->GetLoadState();
[email protected]044de0642010-06-17 10:42:15351 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
352 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
[email protected]0877e3d2009-10-17 22:29:57353 case STATE_SEND_REQUEST_COMPLETE:
[email protected]96d570e42008-08-05 22:43:04354 return LOAD_STATE_SENDING_REQUEST;
355 case STATE_READ_HEADERS_COMPLETE:
356 return LOAD_STATE_WAITING_FOR_RESPONSE;
357 case STATE_READ_BODY_COMPLETE:
358 return LOAD_STATE_READING_RESPONSE;
359 default:
360 return LOAD_STATE_IDLE;
361 }
362}
363
364uint64 HttpNetworkTransaction::GetUploadProgress() const {
[email protected]351ab642010-08-05 16:55:31365 if (!stream_.get())
[email protected]96d570e42008-08-05 22:43:04366 return 0;
367
[email protected]351ab642010-08-05 16:55:31368 return stream_->GetUploadProgress();
[email protected]96d570e42008-08-05 22:43:04369}
370
[email protected]102e27c2011-02-23 01:01:31371void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config,
372 const ProxyInfo& used_proxy_info,
373 HttpStream* stream) {
[email protected]82918cc2010-08-25 17:24:50374 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38375 DCHECK(stream_request_.get());
376
377 stream_.reset(stream);
[email protected]102957f2011-09-02 17:10:14378 server_ssl_config_ = used_ssl_config;
[email protected]102e27c2011-02-23 01:01:31379 proxy_info_ = used_proxy_info;
[email protected]8e6441ca2010-08-19 05:56:38380 response_.was_npn_negotiated = stream_request_->was_npn_negotiated();
[email protected]c30bcce2011-12-20 17:50:51381 response_.npn_negotiated_protocol = SSLClientSocket::NextProtoToString(
382 stream_request_->protocol_negotiated());
[email protected]8e6441ca2010-08-19 05:56:38383 response_.was_fetched_via_spdy = stream_request_->using_spdy();
384 response_.was_fetched_via_proxy = !proxy_info_.is_direct();
[email protected]8e6441ca2010-08-19 05:56:38385
386 OnIOComplete(OK);
387}
388
[email protected]102e27c2011-02-23 01:01:31389void HttpNetworkTransaction::OnStreamFailed(int result,
390 const SSLConfig& used_ssl_config) {
[email protected]82918cc2010-08-25 17:24:50391 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38392 DCHECK_NE(OK, result);
393 DCHECK(stream_request_.get());
394 DCHECK(!stream_.get());
[email protected]102957f2011-09-02 17:10:14395 server_ssl_config_ = used_ssl_config;
[email protected]8e6441ca2010-08-19 05:56:38396
397 OnIOComplete(result);
398}
399
[email protected]102e27c2011-02-23 01:01:31400void HttpNetworkTransaction::OnCertificateError(
401 int result,
402 const SSLConfig& used_ssl_config,
403 const SSLInfo& ssl_info) {
[email protected]82918cc2010-08-25 17:24:50404 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38405 DCHECK_NE(OK, result);
406 DCHECK(stream_request_.get());
407 DCHECK(!stream_.get());
408
409 response_.ssl_info = ssl_info;
[email protected]102957f2011-09-02 17:10:14410 server_ssl_config_ = used_ssl_config;
[email protected]8e6441ca2010-08-19 05:56:38411
412 // TODO(mbelshe): For now, we're going to pass the error through, and that
413 // will close the stream_request in all cases. This means that we're always
[email protected]82918cc2010-08-25 17:24:50414 // going to restart an entire STATE_CREATE_STREAM, even if the connection is
415 // good and the user chooses to ignore the error. This is not ideal, but not
416 // the end of the world either.
[email protected]8e6441ca2010-08-19 05:56:38417
418 OnIOComplete(result);
419}
420
421void HttpNetworkTransaction::OnNeedsProxyAuth(
[email protected]6dc476da2010-09-01 04:43:50422 const HttpResponseInfo& proxy_response,
[email protected]102e27c2011-02-23 01:01:31423 const SSLConfig& used_ssl_config,
424 const ProxyInfo& used_proxy_info,
[email protected]6dc476da2010-09-01 04:43:50425 HttpAuthController* auth_controller) {
[email protected]8e6441ca2010-08-19 05:56:38426 DCHECK(stream_request_.get());
[email protected]82918cc2010-08-25 17:24:50427 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38428
429 establishing_tunnel_ = true;
430 response_.headers = proxy_response.headers;
431 response_.auth_challenge = proxy_response.auth_challenge;
432 headers_valid_ = true;
[email protected]102957f2011-09-02 17:10:14433 server_ssl_config_ = used_ssl_config;
[email protected]102e27c2011-02-23 01:01:31434 proxy_info_ = used_proxy_info;
[email protected]8e6441ca2010-08-19 05:56:38435
436 auth_controllers_[HttpAuth::AUTH_PROXY] = auth_controller;
437 pending_auth_target_ = HttpAuth::AUTH_PROXY;
438
439 DoCallback(OK);
440}
441
442void HttpNetworkTransaction::OnNeedsClientAuth(
[email protected]102e27c2011-02-23 01:01:31443 const SSLConfig& used_ssl_config,
[email protected]6dc476da2010-09-01 04:43:50444 SSLCertRequestInfo* cert_info) {
[email protected]82918cc2010-08-25 17:24:50445 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38446
[email protected]102957f2011-09-02 17:10:14447 server_ssl_config_ = used_ssl_config;
[email protected]8e6441ca2010-08-19 05:56:38448 response_.cert_request_info = cert_info;
[email protected]65a3b912010-08-21 05:46:58449 OnIOComplete(ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8e6441ca2010-08-19 05:56:38450}
451
[email protected]511f6f52010-12-17 03:58:29452void HttpNetworkTransaction::OnHttpsProxyTunnelResponse(
453 const HttpResponseInfo& response_info,
[email protected]102e27c2011-02-23 01:01:31454 const SSLConfig& used_ssl_config,
455 const ProxyInfo& used_proxy_info,
[email protected]511f6f52010-12-17 03:58:29456 HttpStream* stream) {
457 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
458
459 headers_valid_ = true;
460 response_ = response_info;
[email protected]102957f2011-09-02 17:10:14461 server_ssl_config_ = used_ssl_config;
[email protected]102e27c2011-02-23 01:01:31462 proxy_info_ = used_proxy_info;
[email protected]511f6f52010-12-17 03:58:29463 stream_.reset(stream);
464 stream_request_.reset(); // we're done with the stream request
465 OnIOComplete(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
466}
467
[email protected]8e6441ca2010-08-19 05:56:38468bool HttpNetworkTransaction::is_https_request() const {
469 return request_->url.SchemeIs("https");
initial.commit586acc5fe2008-07-26 22:42:52470}
471
initial.commit586acc5fe2008-07-26 22:42:52472void HttpNetworkTransaction::DoCallback(int rv) {
[email protected]0b0bf032010-09-21 18:08:50473 DCHECK_NE(rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:41474 DCHECK(!callback_.is_null());
initial.commit586acc5fe2008-07-26 22:42:52475
[email protected]96d570e42008-08-05 22:43:04476 // Since Run may result in Read being called, clear user_callback_ up front.
[email protected]49639fa2011-12-20 23:22:41477 CompletionCallback c = callback_;
478 callback_.Reset();
479 c.Run(rv);
initial.commit586acc5fe2008-07-26 22:42:52480}
481
482void HttpNetworkTransaction::OnIOComplete(int result) {
483 int rv = DoLoop(result);
484 if (rv != ERR_IO_PENDING)
485 DoCallback(rv);
486}
487
488int HttpNetworkTransaction::DoLoop(int result) {
489 DCHECK(next_state_ != STATE_NONE);
490
491 int rv = result;
492 do {
493 State state = next_state_;
494 next_state_ = STATE_NONE;
495 switch (state) {
[email protected]82918cc2010-08-25 17:24:50496 case STATE_CREATE_STREAM:
497 DCHECK_EQ(OK, rv);
498 rv = DoCreateStream();
499 break;
500 case STATE_CREATE_STREAM_COMPLETE:
501 rv = DoCreateStreamComplete(rv);
502 break;
[email protected]351ab642010-08-05 16:55:31503 case STATE_INIT_STREAM:
504 DCHECK_EQ(OK, rv);
505 rv = DoInitStream();
506 break;
507 case STATE_INIT_STREAM_COMPLETE:
508 rv = DoInitStreamComplete(rv);
509 break;
[email protected]044de0642010-06-17 10:42:15510 case STATE_GENERATE_PROXY_AUTH_TOKEN:
511 DCHECK_EQ(OK, rv);
512 rv = DoGenerateProxyAuthToken();
513 break;
514 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
515 rv = DoGenerateProxyAuthTokenComplete(rv);
516 break;
517 case STATE_GENERATE_SERVER_AUTH_TOKEN:
518 DCHECK_EQ(OK, rv);
519 rv = DoGenerateServerAuthToken();
520 break;
521 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
522 rv = DoGenerateServerAuthTokenComplete(rv);
523 break;
[email protected]4875ba12011-03-30 22:31:51524 case STATE_BUILD_REQUEST:
[email protected]725355a2009-03-25 20:42:55525 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09526 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, NULL);
[email protected]4875ba12011-03-30 22:31:51527 rv = DoBuildRequest();
528 break;
529 case STATE_BUILD_REQUEST_COMPLETE:
530 rv = DoBuildRequestComplete(rv);
531 break;
532 case STATE_SEND_REQUEST:
533 DCHECK_EQ(OK, rv);
[email protected]0877e3d2009-10-17 22:29:57534 rv = DoSendRequest();
initial.commit586acc5fe2008-07-26 22:42:52535 break;
[email protected]0877e3d2009-10-17 22:29:57536 case STATE_SEND_REQUEST_COMPLETE:
537 rv = DoSendRequestComplete(rv);
[email protected]d7fd1782011-02-08 19:16:43538 net_log_.EndEventWithNetErrorCode(
539 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, rv);
initial.commit586acc5fe2008-07-26 22:42:52540 break;
541 case STATE_READ_HEADERS:
[email protected]725355a2009-03-25 20:42:55542 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09543 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, NULL);
initial.commit586acc5fe2008-07-26 22:42:52544 rv = DoReadHeaders();
545 break;
546 case STATE_READ_HEADERS_COMPLETE:
547 rv = DoReadHeadersComplete(rv);
[email protected]d7fd1782011-02-08 19:16:43548 net_log_.EndEventWithNetErrorCode(
549 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, rv);
initial.commit586acc5fe2008-07-26 22:42:52550 break;
551 case STATE_READ_BODY:
[email protected]725355a2009-03-25 20:42:55552 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09553 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, NULL);
initial.commit586acc5fe2008-07-26 22:42:52554 rv = DoReadBody();
555 break;
556 case STATE_READ_BODY_COMPLETE:
557 rv = DoReadBodyComplete(rv);
[email protected]d7fd1782011-02-08 19:16:43558 net_log_.EndEventWithNetErrorCode(
559 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, rv);
initial.commit586acc5fe2008-07-26 22:42:52560 break;
[email protected]2d2697f92009-02-18 21:00:32561 case STATE_DRAIN_BODY_FOR_AUTH_RESTART:
[email protected]725355a2009-03-25 20:42:55562 DCHECK_EQ(OK, rv);
[email protected]9e743cd2010-03-16 07:03:53563 net_log_.BeginEvent(
[email protected]ec11be62010-04-28 19:28:09564 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, NULL);
[email protected]2d2697f92009-02-18 21:00:32565 rv = DoDrainBodyForAuthRestart();
566 break;
567 case STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE:
568 rv = DoDrainBodyForAuthRestartComplete(rv);
[email protected]d7fd1782011-02-08 19:16:43569 net_log_.EndEventWithNetErrorCode(
570 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, rv);
[email protected]2d2697f92009-02-18 21:00:32571 break;
initial.commit586acc5fe2008-07-26 22:42:52572 default:
573 NOTREACHED() << "bad state";
574 rv = ERR_FAILED;
[email protected]96d570e42008-08-05 22:43:04575 break;
initial.commit586acc5fe2008-07-26 22:42:52576 }
577 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
578
579 return rv;
580}
581
[email protected]82918cc2010-08-25 17:24:50582int HttpNetworkTransaction::DoCreateStream() {
583 next_state_ = STATE_CREATE_STREAM_COMPLETE;
[email protected]351ab642010-08-05 16:55:31584
[email protected]26816882010-10-14 18:03:09585 stream_request_.reset(
586 session_->http_stream_factory()->RequestStream(
[email protected]102e27c2011-02-23 01:01:31587 *request_,
[email protected]102957f2011-09-02 17:10:14588 server_ssl_config_,
589 proxy_ssl_config_,
[email protected]26816882010-10-14 18:03:09590 this,
591 net_log_));
592 DCHECK(stream_request_.get());
[email protected]8e6441ca2010-08-19 05:56:38593 return ERR_IO_PENDING;
[email protected]351ab642010-08-05 16:55:31594}
595
[email protected]82918cc2010-08-25 17:24:50596int HttpNetworkTransaction::DoCreateStreamComplete(int result) {
[email protected]394816e92010-08-03 07:38:59597 if (result == OK) {
[email protected]82918cc2010-08-25 17:24:50598 next_state_ = STATE_INIT_STREAM;
[email protected]8e6441ca2010-08-19 05:56:38599 DCHECK(stream_.get());
[email protected]adb00242010-10-29 03:04:33600 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
601 result = HandleCertificateRequest(result);
[email protected]511f6f52010-12-17 03:58:29602 } else if (result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
603 // Return OK and let the caller read the proxy's error page
604 next_state_ = STATE_NONE;
605 return OK;
[email protected]394816e92010-08-03 07:38:59606 }
607
[email protected]bd0b6772011-01-11 19:59:30608 // Handle possible handshake errors that may have occurred if the stream
609 // used SSL for one or more of the layers.
610 result = HandleSSLHandshakeError(result);
611
[email protected]8e6441ca2010-08-19 05:56:38612 // At this point we are done with the stream_request_.
[email protected]26816882010-10-14 18:03:09613 stream_request_.reset();
[email protected]8e6441ca2010-08-19 05:56:38614 return result;
[email protected]394816e92010-08-03 07:38:59615}
616
[email protected]82918cc2010-08-25 17:24:50617int HttpNetworkTransaction::DoInitStream() {
618 DCHECK(stream_.get());
619 next_state_ = STATE_INIT_STREAM_COMPLETE;
[email protected]49639fa2011-12-20 23:22:41620 return stream_->InitializeStream(request_, net_log_, io_callback_);
[email protected]82918cc2010-08-25 17:24:50621}
622
623int HttpNetworkTransaction::DoInitStreamComplete(int result) {
624 if (result == OK) {
625 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
[email protected]82918cc2010-08-25 17:24:50626 } else {
[email protected]82918cc2010-08-25 17:24:50627 if (result < 0)
[email protected]044dcc52010-09-17 15:44:26628 result = HandleIOError(result);
629
630 // The stream initialization failed, so this stream will never be useful.
631 stream_.reset();
[email protected]82918cc2010-08-25 17:24:50632 }
633
634 return result;
635}
636
[email protected]044de0642010-06-17 10:42:15637int HttpNetworkTransaction::DoGenerateProxyAuthToken() {
638 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE;
639 if (!ShouldApplyProxyAuth())
640 return OK;
[email protected]394816e92010-08-03 07:38:59641 HttpAuth::Target target = HttpAuth::AUTH_PROXY;
642 if (!auth_controllers_[target].get())
[email protected]3598c6022010-09-17 23:13:09643 auth_controllers_[target] =
644 new HttpAuthController(target,
645 AuthURL(target),
[email protected]102e27c2011-02-23 01:01:31646 session_->http_auth_cache(),
[email protected]3598c6022010-09-17 23:13:09647 session_->http_auth_handler_factory());
[email protected]394816e92010-08-03 07:38:59648 return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
[email protected]49639fa2011-12-20 23:22:41649 io_callback_,
[email protected]394816e92010-08-03 07:38:59650 net_log_);
[email protected]044de0642010-06-17 10:42:15651}
652
653int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) {
654 DCHECK_NE(ERR_IO_PENDING, rv);
655 if (rv == OK)
656 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN;
657 return rv;
658}
659
660int HttpNetworkTransaction::DoGenerateServerAuthToken() {
661 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE;
[email protected]394816e92010-08-03 07:38:59662 HttpAuth::Target target = HttpAuth::AUTH_SERVER;
663 if (!auth_controllers_[target].get())
[email protected]3598c6022010-09-17 23:13:09664 auth_controllers_[target] =
665 new HttpAuthController(target,
666 AuthURL(target),
[email protected]102e27c2011-02-23 01:01:31667 session_->http_auth_cache(),
[email protected]3598c6022010-09-17 23:13:09668 session_->http_auth_handler_factory());
[email protected]044de0642010-06-17 10:42:15669 if (!ShouldApplyServerAuth())
670 return OK;
[email protected]394816e92010-08-03 07:38:59671 return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
[email protected]49639fa2011-12-20 23:22:41672 io_callback_,
[email protected]394816e92010-08-03 07:38:59673 net_log_);
[email protected]044de0642010-06-17 10:42:15674}
675
676int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) {
677 DCHECK_NE(ERR_IO_PENDING, rv);
678 if (rv == OK)
[email protected]4875ba12011-03-30 22:31:51679 next_state_ = STATE_BUILD_REQUEST;
[email protected]044de0642010-06-17 10:42:15680 return rv;
681}
682
[email protected]2979a492011-04-06 00:29:14683void HttpNetworkTransaction::BuildRequestHeaders(bool using_proxy) {
684 request_headers_.SetHeader(HttpRequestHeaders::kHost,
685 GetHostAndOptionalPort(request_->url));
686
687 // For compat with HTTP/1.0 servers and proxies:
688 if (using_proxy) {
689 request_headers_.SetHeader(HttpRequestHeaders::kProxyConnection,
690 "keep-alive");
691 } else {
692 request_headers_.SetHeader(HttpRequestHeaders::kConnection, "keep-alive");
693 }
694
[email protected]2979a492011-04-06 00:29:14695 // Add a content length header?
696 if (request_body_.get()) {
697 if (request_body_->is_chunked()) {
698 request_headers_.SetHeader(
699 HttpRequestHeaders::kTransferEncoding, "chunked");
700 } else {
701 request_headers_.SetHeader(
702 HttpRequestHeaders::kContentLength,
703 base::Uint64ToString(request_body_->size()));
704 }
705 } else if (request_->method == "POST" || request_->method == "PUT" ||
706 request_->method == "HEAD") {
707 // An empty POST/PUT request still needs a content length. As for HEAD,
708 // IE and Safari also add a content length header. Presumably it is to
709 // support sending a HEAD request to an URL that only expects to be sent a
710 // POST or some other method that normally would have a message body.
711 request_headers_.SetHeader(HttpRequestHeaders::kContentLength, "0");
712 }
713
714 // Honor load flags that impact proxy caches.
715 if (request_->load_flags & LOAD_BYPASS_CACHE) {
716 request_headers_.SetHeader(HttpRequestHeaders::kPragma, "no-cache");
717 request_headers_.SetHeader(HttpRequestHeaders::kCacheControl, "no-cache");
718 } else if (request_->load_flags & LOAD_VALIDATE_CACHE) {
719 request_headers_.SetHeader(HttpRequestHeaders::kCacheControl, "max-age=0");
720 }
721
722 if (ShouldApplyProxyAuth() && HaveAuth(HttpAuth::AUTH_PROXY))
723 auth_controllers_[HttpAuth::AUTH_PROXY]->AddAuthorizationHeader(
724 &request_headers_);
725 if (ShouldApplyServerAuth() && HaveAuth(HttpAuth::AUTH_SERVER))
726 auth_controllers_[HttpAuth::AUTH_SERVER]->AddAuthorizationHeader(
727 &request_headers_);
728
[email protected]c10450102011-06-27 09:06:16729 request_headers_.MergeFrom(request_->extra_headers);
[email protected]2979a492011-04-06 00:29:14730}
731
[email protected]4875ba12011-03-30 22:31:51732int HttpNetworkTransaction::DoBuildRequest() {
733 next_state_ = STATE_BUILD_REQUEST_COMPLETE;
[email protected]4875ba12011-03-30 22:31:51734 request_body_.reset(NULL);
735 if (request_->upload_data) {
[email protected]49ed6cc2012-02-02 08:59:16736 request_body_.reset(new UploadDataStream(request_->upload_data));
737 const int error_code = request_body_->Init();
738 if (error_code != OK) {
739 request_body_.reset(NULL);
[email protected]4875ba12011-03-30 22:31:51740 return error_code;
[email protected]49ed6cc2012-02-02 08:59:16741 }
[email protected]4875ba12011-03-30 22:31:51742 }
743
744 headers_valid_ = false;
745
746 // This is constructed lazily (instead of within our Start method), so that
747 // we have proxy info available.
748 if (request_headers_.IsEmpty()) {
749 bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) &&
750 !is_https_request();
[email protected]2979a492011-04-06 00:29:14751 BuildRequestHeaders(using_proxy);
[email protected]4875ba12011-03-30 22:31:51752 }
753
[email protected]4875ba12011-03-30 22:31:51754 return OK;
755}
756
757int HttpNetworkTransaction::DoBuildRequestComplete(int result) {
[email protected]9f489d72011-04-04 23:29:24758 if (result == OK)
759 next_state_ = STATE_SEND_REQUEST;
[email protected]4875ba12011-03-30 22:31:51760 return result;
761}
762
[email protected]0877e3d2009-10-17 22:29:57763int HttpNetworkTransaction::DoSendRequest() {
764 next_state_ = STATE_SEND_REQUEST_COMPLETE;
765
[email protected]4875ba12011-03-30 22:31:51766 return stream_->SendRequest(
[email protected]49639fa2011-12-20 23:22:41767 request_headers_, request_body_.release(), &response_, io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52768}
769
[email protected]0877e3d2009-10-17 22:29:57770int HttpNetworkTransaction::DoSendRequestComplete(int result) {
initial.commit586acc5fe2008-07-26 22:42:52771 if (result < 0)
772 return HandleIOError(result);
[email protected]0877e3d2009-10-17 22:29:57773 next_state_ = STATE_READ_HEADERS;
initial.commit586acc5fe2008-07-26 22:42:52774 return OK;
775}
776
777int HttpNetworkTransaction::DoReadHeaders() {
778 next_state_ = STATE_READ_HEADERS_COMPLETE;
[email protected]49639fa2011-12-20 23:22:41779 return stream_->ReadResponseHeaders(io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52780}
781
[email protected]0e75a732008-10-16 20:36:09782int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() {
[email protected]8e6441ca2010-08-19 05:56:38783 if (!response_.headers && !stream_->IsConnectionReused()) {
[email protected]0e75a732008-10-16 20:36:09784 // The connection was closed before any data was sent. Likely an error
785 // rather than empty HTTP/0.9 response.
[email protected]aecfbf22008-10-16 02:02:47786 return ERR_EMPTY_RESPONSE;
787 }
788
[email protected]aecfbf22008-10-16 02:02:47789 return OK;
790}
791
initial.commit586acc5fe2008-07-26 22:42:52792int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
[email protected]0b45559b2009-06-12 21:45:11793 // We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here
794 // due to SSL renegotiation.
[email protected]8e6441ca2010-08-19 05:56:38795 if (IsCertificateError(result)) {
796 // We don't handle a certificate error during SSL renegotiation, so we
797 // have to return an error that's not in the certificate error range
798 // (-2xx).
799 LOG(ERROR) << "Got a server certificate with error " << result
800 << " during SSL renegotiation";
801 result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION;
802 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
803 // TODO(wtc): Need a test case for this code path!
804 DCHECK(stream_.get());
805 DCHECK(is_https_request());
806 response_.cert_request_info = new SSLCertRequestInfo;
807 stream_->GetSSLCertRequestInfo(response_.cert_request_info);
808 result = HandleCertificateRequest(result);
809 if (result == OK)
810 return result;
[email protected]2181ea002009-06-09 01:37:27811 }
812
[email protected]0877e3d2009-10-17 22:29:57813 if (result < 0 && result != ERR_CONNECTION_CLOSED)
initial.commit586acc5fe2008-07-26 22:42:52814 return HandleIOError(result);
815
[email protected]0877e3d2009-10-17 22:29:57816 if (result == ERR_CONNECTION_CLOSED && ShouldResendRequest(result)) {
[email protected]1c773ea12009-04-28 19:58:42817 ResetConnectionAndRequestForResend();
[email protected]0877e3d2009-10-17 22:29:57818 return OK;
[email protected]1c773ea12009-04-28 19:58:42819 }
[email protected]2a5c76b2008-09-25 22:15:16820
[email protected]0877e3d2009-10-17 22:29:57821 // After we call RestartWithAuth a new response_time will be recorded, and
822 // we need to be cautious about incorrectly logging the duration across the
823 // authentication activity.
[email protected]8e6441ca2010-08-19 05:56:38824 if (result == OK)
825 LogTransactionConnectedMetrics();
initial.commit586acc5fe2008-07-26 22:42:52826
[email protected]0877e3d2009-10-17 22:29:57827 if (result == ERR_CONNECTION_CLOSED) {
[email protected]02c92c492010-03-08 21:28:14828 // For now, if we get at least some data, we do the best we can to make
[email protected]9492e4a2010-02-24 00:58:46829 // sense of it and send it back up the stack.
[email protected]0e75a732008-10-16 20:36:09830 int rv = HandleConnectionClosedBeforeEndOfHeaders();
[email protected]aecfbf22008-10-16 02:02:47831 if (rv != OK)
832 return rv;
[email protected]0877e3d2009-10-17 22:29:57833 }
[email protected]a1ff6e22012-03-27 15:31:34834 DCHECK(response_.headers);
initial.commit586acc5fe2008-07-26 22:42:52835
[email protected]93f8b562012-03-27 01:00:16836 // Like Net.HttpResponseCode, but only for MAIN_FRAME loads.
837 if (request_->load_flags & LOAD_MAIN_FRAME) {
838 const int response_code = response_.headers->response_code();
839 UMA_HISTOGRAM_ENUMERATION(
840 "Net.HttpResponseCode_Nxx_MainFrame", response_code/100, 10);
841 }
842
[email protected]465aeb942010-10-14 19:58:14843 if (net_log_.IsLoggingAllEvents()) {
[email protected]8a1f3312010-05-25 19:25:04844 net_log_.AddEvent(
845 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
[email protected]00cd9c42010-11-02 20:15:57846 make_scoped_refptr(new NetLogHttpResponseParameter(response_.headers)));
[email protected]dbb83db2010-05-11 18:13:39847 }
848
[email protected]a7e41312009-12-16 23:18:14849 if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
[email protected]0877e3d2009-10-17 22:29:57850 // HTTP/0.9 doesn't support the PUT method, so lack of response headers
851 // indicates a buggy server. See:
852 // https://bugzilla.mozilla.org/show_bug.cgi?id=193921
853 if (request_->method == "PUT")
854 return ERR_METHOD_NOT_SUPPORTED;
855 }
[email protected]4ddaf2502008-10-23 18:26:19856
[email protected]0877e3d2009-10-17 22:29:57857 // Check for an intermediate 100 Continue response. An origin server is
858 // allowed to send this response even if we didn't ask for it, so we just
859 // need to skip over it.
860 // We treat any other 1xx in this same way (although in practice getting
861 // a 1xx that isn't a 100 is rare).
[email protected]a7e41312009-12-16 23:18:14862 if (response_.headers->response_code() / 100 == 1) {
[email protected]ee9410e72010-01-07 01:42:38863 response_.headers = new HttpResponseHeaders("");
[email protected]0877e3d2009-10-17 22:29:57864 next_state_ = STATE_READ_HEADERS;
865 return OK;
866 }
867
[email protected]8e6441ca2010-08-19 05:56:38868 HostPortPair endpoint = HostPortPair(request_->url.HostNoBrackets(),
869 request_->url.EffectiveIntPort());
870 ProcessAlternateProtocol(session_->http_stream_factory(),
[email protected]17291a022011-10-10 07:32:53871 session_->http_server_properties(),
[email protected]8e6441ca2010-08-19 05:56:38872 *response_.headers,
873 endpoint);
[email protected]564b4912010-03-09 16:30:42874
[email protected]e772db3f2010-07-12 18:11:13875 int rv = HandleAuthChallenge();
[email protected]0877e3d2009-10-17 22:29:57876 if (rv != OK)
877 return rv;
878
[email protected]8536ef52010-09-30 16:18:21879 if (is_https_request())
880 stream_->GetSSLInfo(&response_.ssl_info);
881
[email protected]0877e3d2009-10-17 22:29:57882 headers_valid_ = true;
883 return OK;
initial.commit586acc5fe2008-07-26 22:42:52884}
885
886int HttpNetworkTransaction::DoReadBody() {
887 DCHECK(read_buf_);
[email protected]6501bc02009-06-25 20:55:13888 DCHECK_GT(read_buf_len_, 0);
[email protected]8e6441ca2010-08-19 05:56:38889 DCHECK(stream_ != NULL);
initial.commit586acc5fe2008-07-26 22:42:52890
891 next_state_ = STATE_READ_BODY_COMPLETE;
[email protected]49639fa2011-12-20 23:22:41892 return stream_->ReadResponseBody(read_buf_, read_buf_len_, io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52893}
894
895int HttpNetworkTransaction::DoReadBodyComplete(int result) {
896 // We are done with the Read call.
[email protected]8e6441ca2010-08-19 05:56:38897 bool done = false;
898 if (result <= 0) {
899 DCHECK_NE(ERR_IO_PENDING, result);
initial.commit586acc5fe2008-07-26 22:42:52900 done = true;
[email protected]8e6441ca2010-08-19 05:56:38901 }
[email protected]9492e4a2010-02-24 00:58:46902
[email protected]8e6441ca2010-08-19 05:56:38903 bool keep_alive = false;
[email protected]351ab642010-08-05 16:55:31904 if (stream_->IsResponseBodyComplete()) {
[email protected]8e6441ca2010-08-19 05:56:38905 // Note: Just because IsResponseBodyComplete is true, we're not
906 // necessarily "done". We're only "done" when it is the last
907 // read on this HttpNetworkTransaction, which will be signified
908 // by a zero-length read.
909 // TODO(mbelshe): The keepalive property is really a property of
910 // the stream. No need to compute it here just to pass back
911 // to the stream's Close function.
[email protected]351ab642010-08-05 16:55:31912 if (stream_->CanFindEndOfResponse())
[email protected]02c92c492010-03-08 21:28:14913 keep_alive = GetResponseHeaders()->IsKeepAlive();
initial.commit586acc5fe2008-07-26 22:42:52914 }
915
[email protected]8e6441ca2010-08-19 05:56:38916 // Clean up connection if we are done.
initial.commit586acc5fe2008-07-26 22:42:52917 if (done) {
[email protected]56300172008-11-06 18:42:55918 LogTransactionMetrics();
[email protected]5e6efa52011-06-27 17:26:41919 stream_->LogNumRttVsBytesMetrics();
[email protected]8e6441ca2010-08-19 05:56:38920 stream_->Close(!keep_alive);
[email protected]e2a915a2010-08-19 07:55:01921 // Note: we don't reset the stream here. We've closed it, but we still
922 // need it around so that callers can call methods such as
923 // GetUploadProgress() and have them be meaningful.
924 // TODO(mbelshe): This means we closed the stream here, and we close it
925 // again in ~HttpNetworkTransaction. Clean that up.
926
[email protected]8e6441ca2010-08-19 05:56:38927 // The next Read call will return 0 (EOF).
initial.commit586acc5fe2008-07-26 22:42:52928 }
929
930 // Clear these to avoid leaving around old state.
931 read_buf_ = NULL;
932 read_buf_len_ = 0;
933
934 return result;
935}
936
[email protected]2d2697f92009-02-18 21:00:32937int HttpNetworkTransaction::DoDrainBodyForAuthRestart() {
938 // This method differs from DoReadBody only in the next_state_. So we just
939 // call DoReadBody and override the next_state_. Perhaps there is a more
940 // elegant way for these two methods to share code.
941 int rv = DoReadBody();
942 DCHECK(next_state_ == STATE_READ_BODY_COMPLETE);
943 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE;
944 return rv;
945}
946
[email protected]0877e3d2009-10-17 22:29:57947// TODO(wtc): This method and the DoReadBodyComplete method are almost
948// the same. Figure out a good way for these two methods to share code.
[email protected]2d2697f92009-02-18 21:00:32949int HttpNetworkTransaction::DoDrainBodyForAuthRestartComplete(int result) {
[email protected]68873ba2009-06-04 21:49:23950 // keep_alive defaults to true because the very reason we're draining the
951 // response body is to reuse the connection for auth restart.
952 bool done = false, keep_alive = true;
[email protected]2d2697f92009-02-18 21:00:32953 if (result < 0) {
[email protected]0877e3d2009-10-17 22:29:57954 // Error or closed connection while reading the socket.
[email protected]2d2697f92009-02-18 21:00:32955 done = true;
[email protected]68873ba2009-06-04 21:49:23956 keep_alive = false;
[email protected]351ab642010-08-05 16:55:31957 } else if (stream_->IsResponseBodyComplete()) {
[email protected]0877e3d2009-10-17 22:29:57958 done = true;
[email protected]2d2697f92009-02-18 21:00:32959 }
960
961 if (done) {
962 DidDrainBodyForAuthRestart(keep_alive);
963 } else {
964 // Keep draining.
965 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
966 }
967
968 return OK;
969}
970
[email protected]8e3d2d32010-06-13 18:46:23971void HttpNetworkTransaction::LogTransactionConnectedMetrics() {
972 if (logged_response_time_)
973 return;
974
975 logged_response_time_ = true;
976
[email protected]a7e41312009-12-16 23:18:14977 base::TimeDelta total_duration = response_.response_time - start_time_;
[email protected]9a0a55f2009-04-13 23:23:03978
[email protected]d6b55392011-08-05 04:04:35979 UMA_HISTOGRAM_CUSTOM_TIMES(
980 "Net.Transaction_Connected",
[email protected]510e854f2009-04-20 18:39:08981 total_duration,
[email protected]9a0a55f2009-04-13 23:23:03982 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
983 100);
[email protected]1fa47592009-07-27 22:45:00984
[email protected]c38ec5a2010-08-25 23:32:38985 bool reused_socket = stream_->IsConnectionReused();
986 if (!reused_socket) {
[email protected]d6b55392011-08-05 04:04:35987 UMA_HISTOGRAM_CUSTOM_TIMES(
988 "Net.Transaction_Connected_New_b",
[email protected]b01998a2009-04-21 01:01:11989 total_duration,
990 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
991 100);
[email protected]d068f7a2010-06-07 15:12:59992
[email protected]edafd4c2011-05-10 17:18:53993 static const bool use_conn_impact_histogram =
994 base::FieldTrialList::TrialExists("ConnCountImpact");
[email protected]d068f7a2010-06-07 15:12:59995 if (use_conn_impact_histogram) {
[email protected]d6b55392011-08-05 04:04:35996 UMA_HISTOGRAM_CUSTOM_TIMES(
997 base::FieldTrial::MakeName("Net.Transaction_Connected_New_b",
[email protected]d068f7a2010-06-07 15:12:59998 "ConnCountImpact"),
999 total_duration,
1000 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1001 100);
1002 }
[email protected]0310d432009-08-25 07:49:521003 }
1004
[email protected]edafd4c2011-05-10 17:18:531005 static const bool use_spdy_histogram =
1006 base::FieldTrialList::TrialExists("SpdyImpact");
[email protected]8e3d2d32010-06-13 18:46:231007 if (use_spdy_histogram && response_.was_npn_negotiated) {
[email protected]d6b55392011-08-05 04:04:351008 UMA_HISTOGRAM_CUSTOM_TIMES(
1009 base::FieldTrial::MakeName("Net.Transaction_Connected",
[email protected]835d7c82010-10-14 04:38:381010 "SpdyImpact"),
[email protected]8e3d2d32010-06-13 18:46:231011 total_duration, base::TimeDelta::FromMilliseconds(1),
1012 base::TimeDelta::FromMinutes(10), 100);
1013
[email protected]c38ec5a2010-08-25 23:32:381014 if (!reused_socket) {
[email protected]d6b55392011-08-05 04:04:351015 UMA_HISTOGRAM_CUSTOM_TIMES(
1016 base::FieldTrial::MakeName("Net.Transaction_Connected_New_b",
[email protected]835d7c82010-10-14 04:38:381017 "SpdyImpact"),
[email protected]8e3d2d32010-06-13 18:46:231018 total_duration, base::TimeDelta::FromMilliseconds(1),
1019 base::TimeDelta::FromMinutes(10), 100);
1020 }
1021 }
1022
[email protected]510e854f2009-04-20 18:39:081023 // Currently, non-zero priority requests are frame or sub-frame resource
1024 // types. This will change when we also prioritize certain subresources like
1025 // css, js, etc.
1026 if (request_->priority) {
[email protected]d6b55392011-08-05 04:04:351027 UMA_HISTOGRAM_CUSTOM_TIMES(
1028 "Net.Priority_High_Latency_b",
[email protected]510e854f2009-04-20 18:39:081029 total_duration,
1030 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1031 100);
1032 } else {
[email protected]d6b55392011-08-05 04:04:351033 UMA_HISTOGRAM_CUSTOM_TIMES(
1034 "Net.Priority_Low_Latency_b",
[email protected]510e854f2009-04-20 18:39:081035 total_duration,
1036 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1037 100);
1038 }
[email protected]9a0a55f2009-04-13 23:23:031039}
1040
[email protected]56300172008-11-06 18:42:551041void HttpNetworkTransaction::LogTransactionMetrics() const {
[email protected]0877e3d2009-10-17 22:29:571042 base::TimeDelta duration = base::Time::Now() -
[email protected]2227c692010-05-04 15:36:111043 response_.request_time;
[email protected]56300172008-11-06 18:42:551044 if (60 < duration.InMinutes())
1045 return;
[email protected]0b48db42009-03-23 02:45:111046
[email protected]21b316a2009-03-23 18:25:061047 base::TimeDelta total_duration = base::Time::Now() - start_time_;
1048
[email protected]d6b55392011-08-05 04:04:351049 UMA_HISTOGRAM_CUSTOM_TIMES("Net.Transaction_Latency_b", duration,
1050 base::TimeDelta::FromMilliseconds(1),
1051 base::TimeDelta::FromMinutes(10),
1052 100);
1053 UMA_HISTOGRAM_CUSTOM_TIMES("Net.Transaction_Latency_Total",
1054 total_duration,
1055 base::TimeDelta::FromMilliseconds(1),
1056 base::TimeDelta::FromMinutes(10), 100);
[email protected]5c68d692011-08-24 04:59:411057
1058 static const bool use_warm_socket_impact_histogram =
1059 base::FieldTrialList::TrialExists("WarmSocketImpact");
1060 if (use_warm_socket_impact_histogram) {
1061 UMA_HISTOGRAM_CUSTOM_TIMES(
1062 base::FieldTrial::MakeName("Net.Transaction_Latency_b",
1063 "WarmSocketImpact"),
1064 duration,
1065 base::TimeDelta::FromMilliseconds(1),
1066 base::TimeDelta::FromMinutes(10),
1067 100);
1068 UMA_HISTOGRAM_CUSTOM_TIMES(
1069 base::FieldTrial::MakeName("Net.Transaction_Latency_Total",
1070 "WarmSocketImpact"),
1071 total_duration,
1072 base::TimeDelta::FromMilliseconds(1),
1073 base::TimeDelta::FromMinutes(10), 100);
1074 }
1075
[email protected]c38ec5a2010-08-25 23:32:381076 if (!stream_->IsConnectionReused()) {
[email protected]d6b55392011-08-05 04:04:351077 UMA_HISTOGRAM_CUSTOM_TIMES(
1078 "Net.Transaction_Latency_Total_New_Connection",
[email protected]808f6402009-03-30 20:02:071079 total_duration, base::TimeDelta::FromMilliseconds(1),
1080 base::TimeDelta::FromMinutes(10), 100);
1081 }
[email protected]56300172008-11-06 18:42:551082}
1083
[email protected]5e363962009-06-19 19:57:011084int HttpNetworkTransaction::HandleCertificateRequest(int error) {
[email protected]8e6441ca2010-08-19 05:56:381085 // There are two paths through which the server can request a certificate
1086 // from us. The first is during the initial handshake, the second is
1087 // during SSL renegotiation.
1088 //
1089 // In both cases, we want to close the connection before proceeding.
1090 // We do this for two reasons:
1091 // First, we don't want to keep the connection to the server hung for a
1092 // long time while the user selects a certificate.
1093 // Second, even if we did keep the connection open, NSS has a bug where
1094 // restarting the handshake for ClientAuth is currently broken.
[email protected]65a3b912010-08-21 05:46:581095 DCHECK_EQ(error, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8e6441ca2010-08-19 05:56:381096
1097 if (stream_.get()) {
1098 // Since we already have a stream, we're being called as part of SSL
1099 // renegotiation.
1100 DCHECK(!stream_request_.get());
1101 stream_->Close(true);
1102 stream_.reset();
1103 }
1104
[email protected]26816882010-10-14 18:03:091105 // The server is asking for a client certificate during the initial
1106 // handshake.
1107 stream_request_.reset();
[email protected]5e363962009-06-19 19:57:011108
[email protected]ec229bc92010-11-22 09:51:451109 // If the user selected one of the certificates in client_certs or declined
1110 // to provide one for this server before, use the past decision
1111 // automatically.
1112 scoped_refptr<X509Certificate> client_cert;
1113 bool found_cached_cert = session_->ssl_client_auth_cache()->Lookup(
1114 response_.cert_request_info->host_and_port, &client_cert);
1115 if (!found_cached_cert)
1116 return error;
1117
1118 // Check that the certificate selected is still a certificate the server
1119 // is likely to accept, based on the criteria supplied in the
1120 // CertificateRequest message.
[email protected]5e363962009-06-19 19:57:011121 if (client_cert) {
1122 const std::vector<scoped_refptr<X509Certificate> >& client_certs =
[email protected]a7e41312009-12-16 23:18:141123 response_.cert_request_info->client_certs;
[email protected]ec229bc92010-11-22 09:51:451124 bool cert_still_valid = false;
[email protected]5e363962009-06-19 19:57:011125 for (size_t i = 0; i < client_certs.size(); ++i) {
[email protected]ec229bc92010-11-22 09:51:451126 if (client_cert->Equals(client_certs[i])) {
1127 cert_still_valid = true;
1128 break;
[email protected]5e363962009-06-19 19:57:011129 }
1130 }
[email protected]ec229bc92010-11-22 09:51:451131
1132 if (!cert_still_valid)
1133 return error;
[email protected]5e363962009-06-19 19:57:011134 }
[email protected]ec229bc92010-11-22 09:51:451135
1136 // TODO(davidben): Add a unit test which covers this path; we need to be
1137 // able to send a legitimate certificate and also bypass/clear the
1138 // SSL session cache.
[email protected]102957f2011-09-02 17:10:141139 SSLConfig* ssl_config = response_.cert_request_info->is_proxy ?
1140 &proxy_ssl_config_ : &server_ssl_config_;
1141 ssl_config->send_client_cert = true;
1142 ssl_config->client_cert = client_cert;
[email protected]ec229bc92010-11-22 09:51:451143 next_state_ = STATE_CREATE_STREAM;
1144 // Reset the other member variables.
1145 // Note: this is necessary only with SSL renegotiation.
1146 ResetStateForRestart();
1147 return OK;
[email protected]0b45559b2009-06-12 21:45:111148}
1149
[email protected]bd0b6772011-01-11 19:59:301150// TODO(rch): This does not correctly handle errors when an SSL proxy is
1151// being used, as all of the errors are handled as if they were generated
1152// by the endpoint host, request_->url, rather than considering if they were
[email protected]1c53a1f2011-01-13 00:36:381153// generated by the SSL proxy. http://crbug.com/69329
[email protected]bd0b6772011-01-11 19:59:301154int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
1155 DCHECK(request_);
[email protected]102957f2011-09-02 17:10:141156 if (server_ssl_config_.send_client_cert &&
[email protected]a1cb2cd2011-02-05 02:02:081157 (error == ERR_SSL_PROTOCOL_ERROR || IsClientCertificateError(error))) {
[email protected]bd0b6772011-01-11 19:59:301158 session_->ssl_client_auth_cache()->Remove(
1159 GetHostAndPort(request_->url));
1160 }
1161
initial.commit586acc5fe2008-07-26 22:42:521162 switch (error) {
[email protected]bd0b6772011-01-11 19:59:301163 case ERR_SSL_PROTOCOL_ERROR:
1164 case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
1165 case ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
1166 case ERR_SSL_BAD_RECORD_MAC_ALERT:
[email protected]102957f2011-09-02 17:10:141167 if (server_ssl_config_.tls1_enabled) {
[email protected]bd0b6772011-01-11 19:59:301168 // This could be a TLS-intolerant server, an SSL 3.0 server that
1169 // chose a TLS-only cipher suite or a server with buggy DEFLATE
1170 // support. Turn off TLS 1.0, DEFLATE support and retry.
[email protected]2d6728692011-03-12 01:39:551171 session_->http_stream_factory()->AddTLSIntolerantServer(
1172 HostPortPair::FromURL(request_->url));
[email protected]1c773ea12009-04-28 19:58:421173 ResetConnectionAndRequestForResend();
initial.commit586acc5fe2008-07-26 22:42:521174 error = OK;
[email protected]1c773ea12009-04-28 19:58:421175 }
initial.commit586acc5fe2008-07-26 22:42:521176 break;
1177 }
1178 return error;
1179}
1180
[email protected]bd0b6772011-01-11 19:59:301181// This method determines whether it is safe to resend the request after an
1182// IO error. It can only be called in response to request header or body
1183// write errors or response header read errors. It should not be used in
1184// other cases, such as a Connect error.
1185int HttpNetworkTransaction::HandleIOError(int error) {
1186 // SSL errors may happen at any time during the stream and indicate issues
1187 // with the underlying connection. Because the peer may request
1188 // renegotiation at any time, check and handle any possible SSL handshake
1189 // related errors. In addition to renegotiation, TLS False/Snap Start may
[email protected]1c53a1f2011-01-13 00:36:381190 // cause SSL handshake errors to be delayed until the first or second Write
1191 // (Snap Start) or the first Read (False & Snap Start) on the underlying
1192 // connection.
[email protected]bd0b6772011-01-11 19:59:301193 error = HandleSSLHandshakeError(error);
1194
1195 switch (error) {
1196 // If we try to reuse a connection that the server is in the process of
1197 // closing, we may end up successfully writing out our request (or a
1198 // portion of our request) only to find a connection error when we try to
1199 // read from (or finish writing to) the socket.
1200 case ERR_CONNECTION_RESET:
1201 case ERR_CONNECTION_CLOSED:
1202 case ERR_CONNECTION_ABORTED:
[email protected]202965992011-12-07 23:04:511203 // There can be a race between the socket pool checking checking whether a
1204 // socket is still connected, receiving the FIN, and sending/reading data
1205 // on a reused socket. If we receive the FIN between the connectedness
1206 // check and writing/reading from the socket, we may first learn the socket
1207 // is disconnected when we get a ERR_SOCKET_NOT_CONNECTED. This will most
1208 // likely happen when trying to retrieve its IP address.
1209 // See http://crbug.com/105824 for more details.
1210 case ERR_SOCKET_NOT_CONNECTED:
[email protected]bd0b6772011-01-11 19:59:301211 if (ShouldResendRequest(error)) {
[email protected]5a60c8b2011-10-19 20:14:291212 net_log_.AddEvent(
1213 NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR,
1214 make_scoped_refptr(new NetLogIntegerParameter("net_error", error)));
[email protected]bd0b6772011-01-11 19:59:301215 ResetConnectionAndRequestForResend();
1216 error = OK;
1217 }
1218 break;
[email protected]5a60c8b2011-10-19 20:14:291219 case ERR_PIPELINE_EVICTION:
[email protected]5477d892012-03-01 21:31:311220 if (!session_->force_http_pipelining()) {
1221 net_log_.AddEvent(
1222 NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR,
1223 make_scoped_refptr(new NetLogIntegerParameter("net_error", error)));
1224 ResetConnectionAndRequestForResend();
1225 error = OK;
1226 }
1227 break;
[email protected]8753a122011-10-16 08:05:081228 case ERR_SPDY_PING_FAILED:
[email protected]721c0ce2011-10-13 02:41:001229 case ERR_SPDY_SERVER_REFUSED_STREAM:
[email protected]5a60c8b2011-10-19 20:14:291230 net_log_.AddEvent(
1231 NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR,
1232 make_scoped_refptr(new NetLogIntegerParameter("net_error", error)));
[email protected]721c0ce2011-10-13 02:41:001233 ResetConnectionAndRequestForResend();
1234 error = OK;
1235 break;
[email protected]bd0b6772011-01-11 19:59:301236 }
1237 return error;
1238}
1239
[email protected]c3b35c22008-09-27 03:19:421240void HttpNetworkTransaction::ResetStateForRestart() {
[email protected]697ef4c2010-10-14 16:38:581241 ResetStateForAuthRestart();
1242 stream_.reset();
1243}
1244
1245void HttpNetworkTransaction::ResetStateForAuthRestart() {
[email protected]0757e7702009-03-27 04:00:221246 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:421247 read_buf_ = NULL;
1248 read_buf_len_ = 0;
[email protected]0877e3d2009-10-17 22:29:571249 headers_valid_ = false;
[email protected]b94f92d2010-10-27 16:45:201250 request_headers_.Clear();
[email protected]a7e41312009-12-16 23:18:141251 response_ = HttpResponseInfo();
[email protected]8e6441ca2010-08-19 05:56:381252 establishing_tunnel_ = false;
[email protected]0877e3d2009-10-17 22:29:571253}
1254
1255HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const {
[email protected]a7e41312009-12-16 23:18:141256 return response_.headers;
[email protected]c3b35c22008-09-27 03:19:421257}
1258
[email protected]a19f1c602009-08-24 21:35:281259bool HttpNetworkTransaction::ShouldResendRequest(int error) const {
[email protected]8e6441ca2010-08-19 05:56:381260 bool connection_is_proven = stream_->IsConnectionReused();
1261 bool has_received_headers = GetResponseHeaders() != NULL;
[email protected]58cebf8f2010-07-31 19:20:161262
[email protected]2a5c76b2008-09-25 22:15:161263 // NOTE: we resend a request only if we reused a keep-alive connection.
1264 // This automatically prevents an infinite resend loop because we'll run
1265 // out of the cached keep-alive connections eventually.
[email protected]8e6441ca2010-08-19 05:56:381266 if (connection_is_proven && !has_received_headers)
1267 return true;
1268 return false;
[email protected]1c773ea12009-04-28 19:58:421269}
1270
1271void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
[email protected]8e6441ca2010-08-19 05:56:381272 if (stream_.get()) {
1273 stream_->Close(true);
1274 stream_.reset();
[email protected]58cebf8f2010-07-31 19:20:161275 }
1276
[email protected]0877e3d2009-10-17 22:29:571277 // We need to clear request_headers_ because it contains the real request
1278 // headers, but we may need to resend the CONNECT request first to recreate
1279 // the SSL tunnel.
[email protected]b94f92d2010-10-27 16:45:201280 request_headers_.Clear();
[email protected]82918cc2010-08-25 17:24:501281 next_state_ = STATE_CREATE_STREAM; // Resend the request.
[email protected]86ec30d2008-09-29 21:53:541282}
1283
[email protected]1c773ea12009-04-28 19:58:421284bool HttpNetworkTransaction::ShouldApplyProxyAuth() const {
[email protected]2df19bb2010-08-25 20:13:461285 return !is_https_request() &&
1286 (proxy_info_.is_https() || proxy_info_.is_http());
[email protected]1c773ea12009-04-28 19:58:421287}
license.botbf09a502008-08-24 00:55:551288
[email protected]1c773ea12009-04-28 19:58:421289bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
[email protected]8a1f3312010-05-25 19:25:041290 return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA);
[email protected]1c773ea12009-04-28 19:58:421291}
1292
[email protected]e772db3f2010-07-12 18:11:131293int HttpNetworkTransaction::HandleAuthChallenge() {
[email protected]ad8e04a2010-11-01 04:16:271294 scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders());
[email protected]0877e3d2009-10-17 22:29:571295 DCHECK(headers);
[email protected]c3b35c22008-09-27 03:19:421296
[email protected]0877e3d2009-10-17 22:29:571297 int status = headers->response_code();
[email protected]9094b602012-02-27 21:44:581298 if (status != HTTP_UNAUTHORIZED &&
1299 status != HTTP_PROXY_AUTHENTICATION_REQUIRED)
[email protected]c3b35c22008-09-27 03:19:421300 return OK;
[email protected]9094b602012-02-27 21:44:581301 HttpAuth::Target target = status == HTTP_PROXY_AUTHENTICATION_REQUIRED ?
[email protected]2227c692010-05-04 15:36:111302 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER;
[email protected]038e9a32008-10-08 22:40:161303 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
1304 return ERR_UNEXPECTED_PROXY_AUTH;
[email protected]c3b35c22008-09-27 03:19:421305
[email protected]9094b602012-02-27 21:44:581306 // This case can trigger when an HTTPS server responds with a "Proxy
1307 // authentication required" status code through a non-authenticating
1308 // proxy.
[email protected]7a67a8152010-11-05 18:31:101309 if (!auth_controllers_[target].get())
1310 return ERR_UNEXPECTED_PROXY_AUTH;
1311
[email protected]a7ea8832010-07-12 17:54:541312 int rv = auth_controllers_[target]->HandleAuthChallenge(
[email protected]560c0432010-07-13 20:45:311313 headers, (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false,
1314 net_log_);
[email protected]228404f2010-06-24 04:31:411315 if (auth_controllers_[target]->HaveAuthHandler())
1316 pending_auth_target_ = target;
1317
1318 scoped_refptr<AuthChallengeInfo> auth_info =
1319 auth_controllers_[target]->auth_info();
1320 if (auth_info.get())
1321 response_.auth_challenge = auth_info;
1322
[email protected]228404f2010-06-24 04:31:411323 return rv;
[email protected]f9ee6b52008-11-08 06:46:231324}
1325
[email protected]8e6441ca2010-08-19 05:56:381326bool HttpNetworkTransaction::HaveAuth(HttpAuth::Target target) const {
1327 return auth_controllers_[target].get() &&
1328 auth_controllers_[target]->HaveAuth();
1329}
1330
[email protected]228404f2010-06-24 04:31:411331GURL HttpNetworkTransaction::AuthURL(HttpAuth::Target target) const {
1332 switch (target) {
[email protected]2df19bb2010-08-25 20:13:461333 case HttpAuth::AUTH_PROXY: {
[email protected]228404f2010-06-24 04:31:411334 if (!proxy_info_.proxy_server().is_valid() ||
1335 proxy_info_.proxy_server().is_direct()) {
1336 return GURL(); // There is no proxy server.
1337 }
[email protected]2df19bb2010-08-25 20:13:461338 const char* scheme = proxy_info_.is_https() ? "https://" : "http://";
1339 return GURL(scheme +
[email protected]2fbaecf22010-07-22 22:20:351340 proxy_info_.proxy_server().host_port_pair().ToString());
[email protected]2df19bb2010-08-25 20:13:461341 }
[email protected]228404f2010-06-24 04:31:411342 case HttpAuth::AUTH_SERVER:
1343 return request_->url;
1344 default:
1345 return GURL();
1346 }
[email protected]c3b35c22008-09-27 03:19:421347}
1348
[email protected]d8eb84242010-09-25 02:25:061349#define STATE_CASE(s) \
1350 case s: \
1351 description = base::StringPrintf("%s (0x%08X)", #s, s); \
1352 break
[email protected]aef04272010-06-28 18:03:041353
1354std::string HttpNetworkTransaction::DescribeState(State state) {
1355 std::string description;
1356 switch (state) {
[email protected]82918cc2010-08-25 17:24:501357 STATE_CASE(STATE_CREATE_STREAM);
1358 STATE_CASE(STATE_CREATE_STREAM_COMPLETE);
[email protected]4875ba12011-03-30 22:31:511359 STATE_CASE(STATE_BUILD_REQUEST);
1360 STATE_CASE(STATE_BUILD_REQUEST_COMPLETE);
[email protected]aef04272010-06-28 18:03:041361 STATE_CASE(STATE_SEND_REQUEST);
1362 STATE_CASE(STATE_SEND_REQUEST_COMPLETE);
1363 STATE_CASE(STATE_READ_HEADERS);
1364 STATE_CASE(STATE_READ_HEADERS_COMPLETE);
[email protected]aef04272010-06-28 18:03:041365 STATE_CASE(STATE_READ_BODY);
1366 STATE_CASE(STATE_READ_BODY_COMPLETE);
1367 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART);
1368 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE);
[email protected]aef04272010-06-28 18:03:041369 STATE_CASE(STATE_NONE);
1370 default:
[email protected]d8eb84242010-09-25 02:25:061371 description = base::StringPrintf("Unknown state 0x%08X (%u)", state,
1372 state);
[email protected]aef04272010-06-28 18:03:041373 break;
1374 }
1375 return description;
1376}
1377
1378#undef STATE_CASE
1379
[email protected]c3b35c22008-09-27 03:19:421380} // namespace net