blob: 14c889a69dbb5d77806e6fb4c1f42635c64382d2 [file] [log] [blame]
[email protected]d102f542010-06-30 14:51:051// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// 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]68bf9152008-09-25 19:47:3010#include "base/compiler_specific.h"
[email protected]270c6412010-03-29 22:02:4711#include "base/format_macros.h"
[email protected]835d7c82010-10-14 04:38:3812#include "base/metrics/field_trial.h"
13#include "base/metrics/histogram.h"
14#include "base/metrics/stats_counters.h"
[email protected]270c6412010-03-29 22:02:4715#include "base/scoped_ptr.h"
[email protected]aeaca1f2010-04-20 22:05:2116#include "base/stl_util-inl.h"
[email protected]528c56d2010-07-30 19:28:4417#include "base/string_number_conversions.h"
[email protected]d8eb84242010-09-25 02:25:0618#include "base/string_util.h"
19#include "base/stringprintf.h"
[email protected]68bf9152008-09-25 19:47:3020#include "build/build_config.h"
[email protected]631f1322010-04-30 17:59:1121#include "googleurl/src/gurl.h"
[email protected]277d5942010-08-11 21:02:3522#include "net/base/auth.h"
[email protected]74a85ce2009-02-12 00:03:1923#include "net/base/io_buffer.h"
initial.commit586acc5fe2008-07-26 22:42:5224#include "net/base/load_flags.h"
[email protected]597cf6e2009-05-29 09:43:2625#include "net/base/net_errors.h"
[email protected]c3b35c22008-09-27 03:19:4226#include "net/base/net_util.h"
[email protected]0b45559b2009-06-12 21:45:1127#include "net/base/ssl_cert_request_info.h"
[email protected]fc7de492010-07-12 14:49:0428#include "net/base/ssl_connection_status_flags.h"
initial.commit586acc5fe2008-07-26 22:42:5229#include "net/base/upload_data_stream.h"
[email protected]c3b35c22008-09-27 03:19:4230#include "net/http/http_auth.h"
31#include "net/http/http_auth_handler.h"
[email protected]fa82f932010-05-20 11:09:2432#include "net/http/http_auth_handler_factory.h"
[email protected]8d5a34e2009-06-11 21:21:3633#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5234#include "net/http/http_chunked_decoder.h"
[email protected]a7ea8832010-07-12 17:54:5435#include "net/http/http_net_log_params.h"
initial.commit586acc5fe2008-07-26 22:42:5236#include "net/http/http_network_session.h"
[email protected]a7ea8832010-07-12 17:54:5437#include "net/http/http_proxy_client_socket.h"
[email protected]e772db3f2010-07-12 18:11:1338#include "net/http/http_proxy_client_socket_pool.h"
[email protected]270c6412010-03-29 22:02:4739#include "net/http/http_request_headers.h"
initial.commit586acc5fe2008-07-26 22:42:5240#include "net/http/http_request_info.h"
[email protected]4bb1dc9e2010-09-23 22:36:5241#include "net/http/http_response_body_drainer.h"
[email protected]319d9e6f2009-02-18 19:47:2142#include "net/http/http_response_headers.h"
[email protected]0877e3d2009-10-17 22:29:5743#include "net/http/http_response_info.h"
[email protected]8e6441ca2010-08-19 05:56:3844#include "net/http/http_stream_request.h"
initial.commit586acc5fe2008-07-26 22:42:5245#include "net/http/http_util.h"
[email protected]d7f16632010-03-29 18:02:3646#include "net/http/url_security_manager.h"
[email protected]f7984fc62009-06-22 23:26:4447#include "net/socket/client_socket_factory.h"
[email protected]a796bcec2010-03-22 17:17:2648#include "net/socket/socks_client_socket_pool.h"
[email protected]f7984fc62009-06-22 23:26:4449#include "net/socket/ssl_client_socket.h"
[email protected]e60e47a2010-07-14 03:37:1850#include "net/socket/ssl_client_socket_pool.h"
[email protected]7fc5b09a2010-02-27 00:07:3851#include "net/socket/tcp_client_socket_pool.h"
[email protected]65d56aa2010-06-14 04:13:4052#include "net/spdy/spdy_http_stream.h"
[email protected]dab9c7d2010-02-06 21:44:3253#include "net/spdy/spdy_session.h"
54#include "net/spdy/spdy_session_pool.h"
initial.commit586acc5fe2008-07-26 22:42:5255
[email protected]e1acf6f2008-10-27 20:43:3356using base::Time;
57
initial.commit586acc5fe2008-07-26 22:42:5258namespace net {
59
[email protected]1c773ea12009-04-28 19:58:4260namespace {
61
[email protected]8e6441ca2010-08-19 05:56:3862void ProcessAlternateProtocol(HttpStreamFactory* factory,
63 HttpAlternateProtocols* alternate_protocols,
64 const HttpResponseHeaders& headers,
65 const HostPortPair& http_host_port_pair) {
[email protected]564b4912010-03-09 16:30:4266 std::string alternate_protocol_str;
[email protected]8e6441ca2010-08-19 05:56:3867
[email protected]564b4912010-03-09 16:30:4268 if (!headers.EnumerateHeader(NULL, HttpAlternateProtocols::kHeader,
69 &alternate_protocol_str)) {
70 // Header is not present.
71 return;
72 }
73
[email protected]8e6441ca2010-08-19 05:56:3874 factory->ProcessAlternateProtocol(alternate_protocols,
75 alternate_protocol_str,
76 http_host_port_pair);
[email protected]f45c1ee2010-08-03 00:54:3077}
78
[email protected]1c773ea12009-04-28 19:58:4279} // namespace
80
initial.commit586acc5fe2008-07-26 22:42:5281//-----------------------------------------------------------------------------
82
[email protected]5695b8c2009-09-30 21:36:4383HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session)
[email protected]0757e7702009-03-27 04:00:2284 : pending_auth_target_(HttpAuth::AUTH_NONE),
85 ALLOW_THIS_IN_INITIALIZER_LIST(
[email protected]68bf9152008-09-25 19:47:3086 io_callback_(this, &HttpNetworkTransaction::OnIOComplete)),
initial.commit586acc5fe2008-07-26 22:42:5287 user_callback_(NULL),
88 session_(session),
89 request_(NULL),
[email protected]0877e3d2009-10-17 22:29:5790 headers_valid_(false),
[email protected]8e3d2d32010-06-13 18:46:2391 logged_response_time_(false),
[email protected]b94f92d2010-10-27 16:45:2092 request_headers_(),
initial.commit586acc5fe2008-07-26 22:42:5293 read_buf_len_(0),
[email protected]a7ea8832010-07-12 17:54:5494 next_state_(STATE_NONE),
95 establishing_tunnel_(false) {
[email protected]2cd713f2008-10-21 17:54:2896 session->ssl_config_service()->GetSSLConfig(&ssl_config_);
[email protected]8e6441ca2010-08-19 05:56:3897 if (session->http_stream_factory()->next_protos())
98 ssl_config_.next_protos = *session->http_stream_factory()->next_protos();
[email protected]3ce7df0f2010-03-03 00:30:5099}
100
[email protected]0b0bf032010-09-21 18:08:50101HttpNetworkTransaction::~HttpNetworkTransaction() {
102 if (stream_.get()) {
103 HttpResponseHeaders* headers = GetResponseHeaders();
104 // TODO(mbelshe): The stream_ should be able to compute whether or not the
105 // stream should be kept alive. No reason to compute here
106 // and pass it in.
107 bool try_to_keep_alive =
108 next_state_ == STATE_NONE &&
109 stream_->CanFindEndOfResponse() &&
110 (!headers || headers->IsKeepAlive());
111 if (!try_to_keep_alive) {
112 stream_->Close(true /* not reusable */);
113 } else {
114 if (stream_->IsResponseBodyComplete()) {
115 // If the response body is complete, we can just reuse the socket.
116 stream_->Close(false /* reusable */);
117 } else {
118 // Otherwise, we try to drain the response body.
119 // TODO(willchan): Consider moving this response body draining to the
120 // stream implementation. For SPDY, there's clearly no point. For
121 // HTTP, it can vary depending on whether or not we're pipelining. It's
122 // stream dependent, so the different subtypes should be implementing
123 // their solutions.
[email protected]4bb1dc9e2010-09-23 22:36:52124 HttpResponseBodyDrainer* drainer =
125 new HttpResponseBodyDrainer(stream_.release());
[email protected]9b5e46cb2010-09-28 16:28:44126 drainer->Start(session_);
[email protected]4bb1dc9e2010-09-23 22:36:52127 // |drainer| will delete itself.
[email protected]0b0bf032010-09-21 18:08:50128 }
129 }
130 }
[email protected]0b0bf032010-09-21 18:08:50131}
132
[email protected]684970b2009-08-14 04:54:46133int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
134 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53135 const BoundNetLog& net_log) {
[email protected]5e2e6c77d12009-12-24 21:57:16136 SIMPLE_STATS_COUNTER("HttpNetworkTransaction.Count");
[email protected]5d0153c512009-01-12 19:08:36137
[email protected]9e743cd2010-03-16 07:03:53138 net_log_ = net_log;
[email protected]96d570e42008-08-05 22:43:04139 request_ = request_info;
[email protected]21b316a2009-03-23 18:25:06140 start_time_ = base::Time::Now();
[email protected]96d570e42008-08-05 22:43:04141
[email protected]82918cc2010-08-25 17:24:50142 next_state_ = STATE_CREATE_STREAM;
[email protected]96d570e42008-08-05 22:43:04143 int rv = DoLoop(OK);
144 if (rv == ERR_IO_PENDING)
145 user_callback_ = callback;
146 return rv;
147}
148
149int HttpNetworkTransaction::RestartIgnoringLastError(
150 CompletionCallback* callback) {
[email protected]8e6441ca2010-08-19 05:56:38151 DCHECK(!stream_.get());
152 DCHECK(!stream_request_.get());
153 DCHECK_EQ(STATE_NONE, next_state_);
154
[email protected]82918cc2010-08-25 17:24:50155 next_state_ = STATE_CREATE_STREAM;
[email protected]8e6441ca2010-08-19 05:56:38156
[email protected]ccb40e52008-09-17 20:54:40157 int rv = DoLoop(OK);
158 if (rv == ERR_IO_PENDING)
159 user_callback_ = callback;
[email protected]aaead502008-10-15 00:20:11160 return rv;
[email protected]96d570e42008-08-05 22:43:04161}
162
[email protected]0b45559b2009-06-12 21:45:11163int HttpNetworkTransaction::RestartWithCertificate(
164 X509Certificate* client_cert,
165 CompletionCallback* callback) {
[email protected]8e6441ca2010-08-19 05:56:38166 // In HandleCertificateRequest(), we always tear down existing stream
167 // requests to force a new connection. So we shouldn't have one here.
168 DCHECK(!stream_request_.get());
169 DCHECK(!stream_.get());
170 DCHECK_EQ(STATE_NONE, next_state_);
171
[email protected]0b45559b2009-06-12 21:45:11172 ssl_config_.client_cert = client_cert;
[email protected]ec229bc92010-11-22 09:51:45173 session_->ssl_client_auth_cache()->Add(
174 response_.cert_request_info->host_and_port, client_cert);
[email protected]0b45559b2009-06-12 21:45:11175 ssl_config_.send_client_cert = true;
[email protected]0b45559b2009-06-12 21:45:11176 // Reset the other member variables.
177 // Note: this is necessary only with SSL renegotiation.
178 ResetStateForRestart();
[email protected]82918cc2010-08-25 17:24:50179 next_state_ = STATE_CREATE_STREAM;
[email protected]0b45559b2009-06-12 21:45:11180 int rv = DoLoop(OK);
181 if (rv == ERR_IO_PENDING)
182 user_callback_ = callback;
183 return rv;
184}
185
[email protected]96d570e42008-08-05 22:43:04186int HttpNetworkTransaction::RestartWithAuth(
[email protected]13c8a092010-07-29 06:15:44187 const string16& username,
188 const string16& password,
[email protected]96d570e42008-08-05 22:43:04189 CompletionCallback* callback) {
[email protected]0757e7702009-03-27 04:00:22190 HttpAuth::Target target = pending_auth_target_;
191 if (target == HttpAuth::AUTH_NONE) {
192 NOTREACHED();
193 return ERR_UNEXPECTED;
194 }
[email protected]0757e7702009-03-27 04:00:22195 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:42196
[email protected]e772db3f2010-07-12 18:11:13197 auth_controllers_[target]->ResetAuth(username, password);
198
[email protected]8e6441ca2010-08-19 05:56:38199 DCHECK(user_callback_ == NULL);
200
201 int rv = OK;
202 if (target == HttpAuth::AUTH_PROXY && establishing_tunnel_) {
203 // In this case, we've gathered credentials for use with proxy
204 // authentication of a tunnel.
[email protected]82918cc2010-08-25 17:24:50205 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38206 DCHECK(stream_request_ != NULL);
[email protected]394816e92010-08-03 07:38:59207 auth_controllers_[target] = NULL;
[email protected]a7ea8832010-07-12 17:54:54208 ResetStateForRestart();
[email protected]8e6441ca2010-08-19 05:56:38209 rv = stream_request_->RestartTunnelWithProxyAuth(username, password);
[email protected]a7ea8832010-07-12 17:54:54210 } else {
[email protected]8e6441ca2010-08-19 05:56:38211 // In this case, we've gathered credentials for the server or the proxy
212 // but it is not during the tunneling phase.
213 DCHECK(stream_request_ == NULL);
[email protected]a7ea8832010-07-12 17:54:54214 PrepareForAuthRestart(target);
[email protected]8e6441ca2010-08-19 05:56:38215 rv = DoLoop(OK);
[email protected]a7ea8832010-07-12 17:54:54216 }
[email protected]c3b35c22008-09-27 03:19:42217
[email protected]c3b35c22008-09-27 03:19:42218 if (rv == ERR_IO_PENDING)
219 user_callback_ = callback;
[email protected]c3b35c22008-09-27 03:19:42220 return rv;
[email protected]96d570e42008-08-05 22:43:04221}
222
[email protected]f9ee6b52008-11-08 06:46:23223void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) {
224 DCHECK(HaveAuth(target));
[email protected]8e6441ca2010-08-19 05:56:38225 DCHECK(!stream_request_.get());
226
[email protected]2d2697f92009-02-18 21:00:32227 bool keep_alive = false;
[email protected]0877e3d2009-10-17 22:29:57228 // Even if the server says the connection is keep-alive, we have to be
229 // able to find the end of each response in order to reuse the connection.
230 if (GetResponseHeaders()->IsKeepAlive() &&
[email protected]351ab642010-08-05 16:55:31231 stream_->CanFindEndOfResponse()) {
[email protected]0877e3d2009-10-17 22:29:57232 // If the response body hasn't been completely read, we need to drain
233 // it first.
[email protected]351ab642010-08-05 16:55:31234 if (!stream_->IsResponseBodyComplete()) {
[email protected]2d2697f92009-02-18 21:00:32235 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
[email protected]0877e3d2009-10-17 22:29:57236 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket.
[email protected]2d2697f92009-02-18 21:00:32237 read_buf_len_ = kDrainBodyBufferSize;
238 return;
239 }
[email protected]0877e3d2009-10-17 22:29:57240 keep_alive = true;
[email protected]37832c6d2009-06-05 19:44:09241 }
242
[email protected]2d2697f92009-02-18 21:00:32243 // We don't need to drain the response body, so we act as if we had drained
244 // the response body.
245 DidDrainBodyForAuthRestart(keep_alive);
246}
247
248void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
[email protected]8e6441ca2010-08-19 05:56:38249 DCHECK(!stream_request_.get());
250
251 if (stream_.get()) {
[email protected]697ef4c2010-10-14 16:38:58252 HttpStream* new_stream = NULL;
[email protected]8e6441ca2010-08-19 05:56:38253 if (keep_alive) {
254 // We should call connection_->set_idle_time(), but this doesn't occur
255 // often enough to be worth the trouble.
256 stream_->SetConnectionReused();
[email protected]697ef4c2010-10-14 16:38:58257 new_stream = stream_->RenewStreamForAuth();
[email protected]8e6441ca2010-08-19 05:56:38258 }
[email protected]697ef4c2010-10-14 16:38:58259
260 if (!new_stream) {
261 stream_->Close(!keep_alive);
262 next_state_ = STATE_CREATE_STREAM;
263 } else {
264 next_state_ = STATE_INIT_STREAM;
265 }
266 stream_.reset(new_stream);
[email protected]2d2697f92009-02-18 21:00:32267 }
[email protected]f9ee6b52008-11-08 06:46:23268
269 // Reset the other member variables.
[email protected]697ef4c2010-10-14 16:38:58270 ResetStateForAuthRestart();
[email protected]f9ee6b52008-11-08 06:46:23271}
272
[email protected]8e6441ca2010-08-19 05:56:38273bool HttpNetworkTransaction::IsReadyToRestartForAuth() {
274 return pending_auth_target_ != HttpAuth::AUTH_NONE &&
275 HaveAuth(pending_auth_target_);
276}
277
[email protected]9dea9e1f2009-01-29 00:30:47278int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
[email protected]96d570e42008-08-05 22:43:04279 CompletionCallback* callback) {
[email protected]96d570e42008-08-05 22:43:04280 DCHECK(buf);
[email protected]e0c27be2009-07-15 13:09:35281 DCHECK_LT(0, buf_len);
[email protected]96d570e42008-08-05 22:43:04282
[email protected]1f14a912009-12-21 20:32:44283 State next_state = STATE_NONE;
[email protected]96d570e42008-08-05 22:43:04284
[email protected]ad8e04a2010-11-01 04:16:27285 scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders());
[email protected]8e6441ca2010-08-19 05:56:38286 if (headers_valid_ && headers.get() && stream_request_.get()) {
[email protected]8a1f3312010-05-25 19:25:04287 // We're trying to read the body of the response but we're still trying
[email protected]511f6f52010-12-17 03:58:29288 // to establish an SSL tunnel through an HTTP proxy. We can't read these
[email protected]8a1f3312010-05-25 19:25:04289 // bytes when establishing a tunnel because they might be controlled by
290 // an active network attacker. We don't worry about this for HTTP
291 // because an active network attacker can already control HTTP sessions.
[email protected]511f6f52010-12-17 03:58:29292 // We reach this case when the user cancels a 407 proxy auth prompt. We
293 // also don't worry about this for an HTTPS Proxy, because the
294 // communication with the proxy is secure.
[email protected]8a1f3312010-05-25 19:25:04295 // See http://crbug.com/8473.
[email protected]2df19bb2010-08-25 20:13:46296 DCHECK(proxy_info_.is_http() || proxy_info_.is_https());
[email protected]a7ea8832010-07-12 17:54:54297 DCHECK_EQ(headers->response_code(), 407);
298 LOG(WARNING) << "Blocked proxy response with status "
299 << headers->response_code() << " to CONNECT request for "
300 << GetHostAndPort(request_->url) << ".";
[email protected]8a1f3312010-05-25 19:25:04301 return ERR_TUNNEL_CONNECTION_FAILED;
[email protected]a8e9b162009-03-12 00:06:44302 }
303
[email protected]e60e47a2010-07-14 03:37:18304 // Are we using SPDY or HTTP?
[email protected]351ab642010-08-05 16:55:31305 next_state = STATE_READ_BODY;
[email protected]e60e47a2010-07-14 03:37:18306
[email protected]96d570e42008-08-05 22:43:04307 read_buf_ = buf;
308 read_buf_len_ = buf_len;
309
[email protected]1f14a912009-12-21 20:32:44310 next_state_ = next_state;
[email protected]96d570e42008-08-05 22:43:04311 int rv = DoLoop(OK);
312 if (rv == ERR_IO_PENDING)
313 user_callback_ = callback;
314 return rv;
315}
316
317const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const {
[email protected]a7e41312009-12-16 23:18:14318 return ((headers_valid_ && response_.headers) || response_.ssl_info.cert ||
319 response_.cert_request_info) ? &response_ : NULL;
[email protected]96d570e42008-08-05 22:43:04320}
321
322LoadState HttpNetworkTransaction::GetLoadState() const {
323 // TODO(wtc): Define a new LoadState value for the
324 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request.
325 switch (next_state_) {
[email protected]82918cc2010-08-25 17:24:50326 case STATE_CREATE_STREAM_COMPLETE:
[email protected]8e6441ca2010-08-19 05:56:38327 return stream_request_->GetLoadState();
[email protected]044de0642010-06-17 10:42:15328 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
329 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
[email protected]0877e3d2009-10-17 22:29:57330 case STATE_SEND_REQUEST_COMPLETE:
[email protected]96d570e42008-08-05 22:43:04331 return LOAD_STATE_SENDING_REQUEST;
332 case STATE_READ_HEADERS_COMPLETE:
333 return LOAD_STATE_WAITING_FOR_RESPONSE;
334 case STATE_READ_BODY_COMPLETE:
335 return LOAD_STATE_READING_RESPONSE;
336 default:
337 return LOAD_STATE_IDLE;
338 }
339}
340
341uint64 HttpNetworkTransaction::GetUploadProgress() const {
[email protected]351ab642010-08-05 16:55:31342 if (!stream_.get())
[email protected]96d570e42008-08-05 22:43:04343 return 0;
344
[email protected]351ab642010-08-05 16:55:31345 return stream_->GetUploadProgress();
[email protected]96d570e42008-08-05 22:43:04346}
347
[email protected]4d4a5162010-09-21 22:44:04348void HttpNetworkTransaction::OnStreamReady(HttpStream* stream) {
[email protected]82918cc2010-08-25 17:24:50349 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38350 DCHECK(stream_request_.get());
351
352 stream_.reset(stream);
353 response_.was_alternate_protocol_available =
354 stream_request_->was_alternate_protocol_available();
355 response_.was_npn_negotiated = stream_request_->was_npn_negotiated();
356 response_.was_fetched_via_spdy = stream_request_->using_spdy();
357 response_.was_fetched_via_proxy = !proxy_info_.is_direct();
[email protected]8e6441ca2010-08-19 05:56:38358
359 OnIOComplete(OK);
360}
361
362void HttpNetworkTransaction::OnStreamFailed(int result) {
[email protected]82918cc2010-08-25 17:24:50363 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38364 DCHECK_NE(OK, result);
365 DCHECK(stream_request_.get());
366 DCHECK(!stream_.get());
367
368 OnIOComplete(result);
369}
370
371void HttpNetworkTransaction::OnCertificateError(int result,
372 const SSLInfo& ssl_info) {
[email protected]82918cc2010-08-25 17:24:50373 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38374 DCHECK_NE(OK, result);
375 DCHECK(stream_request_.get());
376 DCHECK(!stream_.get());
377
378 response_.ssl_info = ssl_info;
379
380 // TODO(mbelshe): For now, we're going to pass the error through, and that
381 // will close the stream_request in all cases. This means that we're always
[email protected]82918cc2010-08-25 17:24:50382 // going to restart an entire STATE_CREATE_STREAM, even if the connection is
383 // good and the user chooses to ignore the error. This is not ideal, but not
384 // the end of the world either.
[email protected]8e6441ca2010-08-19 05:56:38385
386 OnIOComplete(result);
387}
388
389void HttpNetworkTransaction::OnNeedsProxyAuth(
[email protected]6dc476da2010-09-01 04:43:50390 const HttpResponseInfo& proxy_response,
391 HttpAuthController* auth_controller) {
[email protected]8e6441ca2010-08-19 05:56:38392 DCHECK(stream_request_.get());
[email protected]82918cc2010-08-25 17:24:50393 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38394
395 establishing_tunnel_ = true;
396 response_.headers = proxy_response.headers;
397 response_.auth_challenge = proxy_response.auth_challenge;
398 headers_valid_ = true;
399
400 auth_controllers_[HttpAuth::AUTH_PROXY] = auth_controller;
401 pending_auth_target_ = HttpAuth::AUTH_PROXY;
402
403 DoCallback(OK);
404}
405
406void HttpNetworkTransaction::OnNeedsClientAuth(
[email protected]6dc476da2010-09-01 04:43:50407 SSLCertRequestInfo* cert_info) {
[email protected]82918cc2010-08-25 17:24:50408 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
[email protected]8e6441ca2010-08-19 05:56:38409
410 response_.cert_request_info = cert_info;
[email protected]65a3b912010-08-21 05:46:58411 OnIOComplete(ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8e6441ca2010-08-19 05:56:38412}
413
[email protected]511f6f52010-12-17 03:58:29414void HttpNetworkTransaction::OnHttpsProxyTunnelResponse(
415 const HttpResponseInfo& response_info,
416 HttpStream* stream) {
417 DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
418
419 headers_valid_ = true;
420 response_ = response_info;
421 stream_.reset(stream);
422 stream_request_.reset(); // we're done with the stream request
423 OnIOComplete(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
424}
425
[email protected]8e6441ca2010-08-19 05:56:38426bool HttpNetworkTransaction::is_https_request() const {
427 return request_->url.SchemeIs("https");
initial.commit586acc5fe2008-07-26 22:42:52428}
429
initial.commit586acc5fe2008-07-26 22:42:52430void HttpNetworkTransaction::DoCallback(int rv) {
[email protected]0b0bf032010-09-21 18:08:50431 DCHECK_NE(rv, ERR_IO_PENDING);
initial.commit586acc5fe2008-07-26 22:42:52432 DCHECK(user_callback_);
433
[email protected]96d570e42008-08-05 22:43:04434 // Since Run may result in Read being called, clear user_callback_ up front.
initial.commit586acc5fe2008-07-26 22:42:52435 CompletionCallback* c = user_callback_;
436 user_callback_ = NULL;
437 c->Run(rv);
438}
439
440void HttpNetworkTransaction::OnIOComplete(int result) {
441 int rv = DoLoop(result);
442 if (rv != ERR_IO_PENDING)
443 DoCallback(rv);
444}
445
446int HttpNetworkTransaction::DoLoop(int result) {
447 DCHECK(next_state_ != STATE_NONE);
448
449 int rv = result;
450 do {
451 State state = next_state_;
452 next_state_ = STATE_NONE;
453 switch (state) {
[email protected]82918cc2010-08-25 17:24:50454 case STATE_CREATE_STREAM:
455 DCHECK_EQ(OK, rv);
456 rv = DoCreateStream();
457 break;
458 case STATE_CREATE_STREAM_COMPLETE:
459 rv = DoCreateStreamComplete(rv);
460 break;
[email protected]351ab642010-08-05 16:55:31461 case STATE_INIT_STREAM:
462 DCHECK_EQ(OK, rv);
463 rv = DoInitStream();
464 break;
465 case STATE_INIT_STREAM_COMPLETE:
466 rv = DoInitStreamComplete(rv);
467 break;
[email protected]044de0642010-06-17 10:42:15468 case STATE_GENERATE_PROXY_AUTH_TOKEN:
469 DCHECK_EQ(OK, rv);
470 rv = DoGenerateProxyAuthToken();
471 break;
472 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
473 rv = DoGenerateProxyAuthTokenComplete(rv);
474 break;
475 case STATE_GENERATE_SERVER_AUTH_TOKEN:
476 DCHECK_EQ(OK, rv);
477 rv = DoGenerateServerAuthToken();
478 break;
479 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
480 rv = DoGenerateServerAuthTokenComplete(rv);
481 break;
[email protected]0877e3d2009-10-17 22:29:57482 case STATE_SEND_REQUEST:
[email protected]725355a2009-03-25 20:42:55483 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09484 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, NULL);
[email protected]0877e3d2009-10-17 22:29:57485 rv = DoSendRequest();
initial.commit586acc5fe2008-07-26 22:42:52486 break;
[email protected]0877e3d2009-10-17 22:29:57487 case STATE_SEND_REQUEST_COMPLETE:
488 rv = DoSendRequestComplete(rv);
[email protected]ec11be62010-04-28 19:28:09489 net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, NULL);
initial.commit586acc5fe2008-07-26 22:42:52490 break;
491 case STATE_READ_HEADERS:
[email protected]725355a2009-03-25 20:42:55492 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09493 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, NULL);
initial.commit586acc5fe2008-07-26 22:42:52494 rv = DoReadHeaders();
495 break;
496 case STATE_READ_HEADERS_COMPLETE:
497 rv = DoReadHeadersComplete(rv);
[email protected]ec11be62010-04-28 19:28:09498 net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, NULL);
initial.commit586acc5fe2008-07-26 22:42:52499 break;
500 case STATE_READ_BODY:
[email protected]725355a2009-03-25 20:42:55501 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09502 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, NULL);
initial.commit586acc5fe2008-07-26 22:42:52503 rv = DoReadBody();
504 break;
505 case STATE_READ_BODY_COMPLETE:
506 rv = DoReadBodyComplete(rv);
[email protected]ec11be62010-04-28 19:28:09507 net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, NULL);
initial.commit586acc5fe2008-07-26 22:42:52508 break;
[email protected]2d2697f92009-02-18 21:00:32509 case STATE_DRAIN_BODY_FOR_AUTH_RESTART:
[email protected]725355a2009-03-25 20:42:55510 DCHECK_EQ(OK, rv);
[email protected]9e743cd2010-03-16 07:03:53511 net_log_.BeginEvent(
[email protected]ec11be62010-04-28 19:28:09512 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, NULL);
[email protected]2d2697f92009-02-18 21:00:32513 rv = DoDrainBodyForAuthRestart();
514 break;
515 case STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE:
516 rv = DoDrainBodyForAuthRestartComplete(rv);
[email protected]9e743cd2010-03-16 07:03:53517 net_log_.EndEvent(
[email protected]ec11be62010-04-28 19:28:09518 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, NULL);
[email protected]2d2697f92009-02-18 21:00:32519 break;
initial.commit586acc5fe2008-07-26 22:42:52520 default:
521 NOTREACHED() << "bad state";
522 rv = ERR_FAILED;
[email protected]96d570e42008-08-05 22:43:04523 break;
initial.commit586acc5fe2008-07-26 22:42:52524 }
525 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
526
527 return rv;
528}
529
[email protected]82918cc2010-08-25 17:24:50530int HttpNetworkTransaction::DoCreateStream() {
531 next_state_ = STATE_CREATE_STREAM_COMPLETE;
[email protected]351ab642010-08-05 16:55:31532
[email protected]26816882010-10-14 18:03:09533 stream_request_.reset(
534 session_->http_stream_factory()->RequestStream(
535 request_,
536 &ssl_config_,
537 &proxy_info_,
538 session_,
539 this,
540 net_log_));
541 DCHECK(stream_request_.get());
[email protected]8e6441ca2010-08-19 05:56:38542 return ERR_IO_PENDING;
[email protected]351ab642010-08-05 16:55:31543}
544
[email protected]82918cc2010-08-25 17:24:50545int HttpNetworkTransaction::DoCreateStreamComplete(int result) {
[email protected]394816e92010-08-03 07:38:59546 if (result == OK) {
[email protected]82918cc2010-08-25 17:24:50547 next_state_ = STATE_INIT_STREAM;
[email protected]8e6441ca2010-08-19 05:56:38548 DCHECK(stream_.get());
[email protected]adb00242010-10-29 03:04:33549 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
550 result = HandleCertificateRequest(result);
[email protected]511f6f52010-12-17 03:58:29551 } else if (result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
552 // Return OK and let the caller read the proxy's error page
553 next_state_ = STATE_NONE;
554 return OK;
[email protected]394816e92010-08-03 07:38:59555 }
556
[email protected]bd0b6772011-01-11 19:59:30557 // Handle possible handshake errors that may have occurred if the stream
558 // used SSL for one or more of the layers.
559 result = HandleSSLHandshakeError(result);
560
[email protected]8e6441ca2010-08-19 05:56:38561 // At this point we are done with the stream_request_.
[email protected]26816882010-10-14 18:03:09562 stream_request_.reset();
[email protected]8e6441ca2010-08-19 05:56:38563 return result;
[email protected]394816e92010-08-03 07:38:59564}
565
[email protected]82918cc2010-08-25 17:24:50566int HttpNetworkTransaction::DoInitStream() {
567 DCHECK(stream_.get());
568 next_state_ = STATE_INIT_STREAM_COMPLETE;
569 return stream_->InitializeStream(request_, net_log_, &io_callback_);
570}
571
572int HttpNetworkTransaction::DoInitStreamComplete(int result) {
573 if (result == OK) {
574 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
[email protected]82918cc2010-08-25 17:24:50575 } else {
[email protected]82918cc2010-08-25 17:24:50576 if (result < 0)
[email protected]044dcc52010-09-17 15:44:26577 result = HandleIOError(result);
578
579 // The stream initialization failed, so this stream will never be useful.
580 stream_.reset();
[email protected]82918cc2010-08-25 17:24:50581 }
582
583 return result;
584}
585
[email protected]044de0642010-06-17 10:42:15586int HttpNetworkTransaction::DoGenerateProxyAuthToken() {
587 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE;
588 if (!ShouldApplyProxyAuth())
589 return OK;
[email protected]394816e92010-08-03 07:38:59590 HttpAuth::Target target = HttpAuth::AUTH_PROXY;
591 if (!auth_controllers_[target].get())
[email protected]3598c6022010-09-17 23:13:09592 auth_controllers_[target] =
593 new HttpAuthController(target,
594 AuthURL(target),
595 session_->auth_cache(),
596 session_->http_auth_handler_factory());
[email protected]394816e92010-08-03 07:38:59597 return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
598 &io_callback_,
599 net_log_);
[email protected]044de0642010-06-17 10:42:15600}
601
602int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) {
603 DCHECK_NE(ERR_IO_PENDING, rv);
604 if (rv == OK)
605 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN;
606 return rv;
607}
608
609int HttpNetworkTransaction::DoGenerateServerAuthToken() {
610 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE;
[email protected]394816e92010-08-03 07:38:59611 HttpAuth::Target target = HttpAuth::AUTH_SERVER;
612 if (!auth_controllers_[target].get())
[email protected]3598c6022010-09-17 23:13:09613 auth_controllers_[target] =
614 new HttpAuthController(target,
615 AuthURL(target),
616 session_->auth_cache(),
617 session_->http_auth_handler_factory());
[email protected]044de0642010-06-17 10:42:15618 if (!ShouldApplyServerAuth())
619 return OK;
[email protected]394816e92010-08-03 07:38:59620 return auth_controllers_[target]->MaybeGenerateAuthToken(request_,
621 &io_callback_,
622 net_log_);
[email protected]044de0642010-06-17 10:42:15623}
624
625int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) {
626 DCHECK_NE(ERR_IO_PENDING, rv);
627 if (rv == OK)
[email protected]8e6441ca2010-08-19 05:56:38628 next_state_ = STATE_SEND_REQUEST;
[email protected]044de0642010-06-17 10:42:15629 return rv;
630}
631
[email protected]0877e3d2009-10-17 22:29:57632int HttpNetworkTransaction::DoSendRequest() {
633 next_state_ = STATE_SEND_REQUEST_COMPLETE;
634
635 UploadDataStream* request_body = NULL;
[email protected]8a1f3312010-05-25 19:25:04636 if (request_->upload_data) {
[email protected]7a6db4022010-03-24 23:37:50637 int error_code;
638 request_body = UploadDataStream::Create(request_->upload_data, &error_code);
639 if (!request_body)
640 return error_code;
641 }
initial.commit586acc5fe2008-07-26 22:42:52642
643 // This is constructed lazily (instead of within our Start method), so that
644 // we have proxy info available.
[email protected]b94f92d2010-10-27 16:45:20645 if (request_headers_.IsEmpty()) {
[email protected]7213e7c2010-10-20 15:33:52646 bool using_proxy = (proxy_info_.is_http()|| proxy_info_.is_https()) &&
647 !is_https_request();
[email protected]7213e7c2010-10-20 15:33:52648 HttpUtil::BuildRequestHeaders(request_, request_body, auth_controllers_,
649 ShouldApplyServerAuth(),
650 ShouldApplyProxyAuth(), using_proxy,
[email protected]b94f92d2010-10-27 16:45:20651 &request_headers_);
[email protected]ac039522010-06-15 16:39:44652
653 if (session_->network_delegate())
[email protected]b94f92d2010-10-27 16:45:20654 session_->network_delegate()->OnSendHttpRequest(&request_headers_);
655 }
initial.commit586acc5fe2008-07-26 22:42:52656
[email protected]1f14a912009-12-21 20:32:44657 headers_valid_ = false;
[email protected]351ab642010-08-05 16:55:31658 return stream_->SendRequest(request_headers_, request_body, &response_,
659 &io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52660}
661
[email protected]0877e3d2009-10-17 22:29:57662int HttpNetworkTransaction::DoSendRequestComplete(int result) {
initial.commit586acc5fe2008-07-26 22:42:52663 if (result < 0)
664 return HandleIOError(result);
[email protected]0877e3d2009-10-17 22:29:57665 next_state_ = STATE_READ_HEADERS;
initial.commit586acc5fe2008-07-26 22:42:52666 return OK;
667}
668
669int HttpNetworkTransaction::DoReadHeaders() {
670 next_state_ = STATE_READ_HEADERS_COMPLETE;
[email protected]351ab642010-08-05 16:55:31671 return stream_->ReadResponseHeaders(&io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52672}
673
[email protected]0e75a732008-10-16 20:36:09674int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() {
[email protected]8e6441ca2010-08-19 05:56:38675 if (!response_.headers && !stream_->IsConnectionReused()) {
[email protected]0e75a732008-10-16 20:36:09676 // The connection was closed before any data was sent. Likely an error
677 // rather than empty HTTP/0.9 response.
[email protected]aecfbf22008-10-16 02:02:47678 return ERR_EMPTY_RESPONSE;
679 }
680
[email protected]aecfbf22008-10-16 02:02:47681 return OK;
682}
683
initial.commit586acc5fe2008-07-26 22:42:52684int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
[email protected]0b45559b2009-06-12 21:45:11685 // We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here
686 // due to SSL renegotiation.
[email protected]8e6441ca2010-08-19 05:56:38687 if (IsCertificateError(result)) {
688 // We don't handle a certificate error during SSL renegotiation, so we
689 // have to return an error that's not in the certificate error range
690 // (-2xx).
691 LOG(ERROR) << "Got a server certificate with error " << result
692 << " during SSL renegotiation";
693 result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION;
694 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
695 // TODO(wtc): Need a test case for this code path!
696 DCHECK(stream_.get());
697 DCHECK(is_https_request());
698 response_.cert_request_info = new SSLCertRequestInfo;
699 stream_->GetSSLCertRequestInfo(response_.cert_request_info);
700 result = HandleCertificateRequest(result);
701 if (result == OK)
702 return result;
[email protected]2181ea002009-06-09 01:37:27703 }
704
[email protected]0877e3d2009-10-17 22:29:57705 if (result < 0 && result != ERR_CONNECTION_CLOSED)
initial.commit586acc5fe2008-07-26 22:42:52706 return HandleIOError(result);
707
[email protected]0877e3d2009-10-17 22:29:57708 if (result == ERR_CONNECTION_CLOSED && ShouldResendRequest(result)) {
[email protected]1c773ea12009-04-28 19:58:42709 ResetConnectionAndRequestForResend();
[email protected]0877e3d2009-10-17 22:29:57710 return OK;
[email protected]1c773ea12009-04-28 19:58:42711 }
[email protected]2a5c76b2008-09-25 22:15:16712
[email protected]0877e3d2009-10-17 22:29:57713 // After we call RestartWithAuth a new response_time will be recorded, and
714 // we need to be cautious about incorrectly logging the duration across the
715 // authentication activity.
[email protected]8e6441ca2010-08-19 05:56:38716 if (result == OK)
717 LogTransactionConnectedMetrics();
initial.commit586acc5fe2008-07-26 22:42:52718
[email protected]0877e3d2009-10-17 22:29:57719 if (result == ERR_CONNECTION_CLOSED) {
[email protected]02c92c492010-03-08 21:28:14720 // For now, if we get at least some data, we do the best we can to make
[email protected]9492e4a2010-02-24 00:58:46721 // sense of it and send it back up the stack.
[email protected]0e75a732008-10-16 20:36:09722 int rv = HandleConnectionClosedBeforeEndOfHeaders();
[email protected]aecfbf22008-10-16 02:02:47723 if (rv != OK)
724 return rv;
[email protected]0877e3d2009-10-17 22:29:57725 }
initial.commit586acc5fe2008-07-26 22:42:52726
[email protected]465aeb942010-10-14 19:58:14727 if (net_log_.IsLoggingAllEvents()) {
[email protected]8a1f3312010-05-25 19:25:04728 net_log_.AddEvent(
729 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
[email protected]00cd9c42010-11-02 20:15:57730 make_scoped_refptr(new NetLogHttpResponseParameter(response_.headers)));
[email protected]dbb83db2010-05-11 18:13:39731 }
732
[email protected]a7e41312009-12-16 23:18:14733 if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
[email protected]0877e3d2009-10-17 22:29:57734 // HTTP/0.9 doesn't support the PUT method, so lack of response headers
735 // indicates a buggy server. See:
736 // https://bugzilla.mozilla.org/show_bug.cgi?id=193921
737 if (request_->method == "PUT")
738 return ERR_METHOD_NOT_SUPPORTED;
739 }
[email protected]4ddaf2502008-10-23 18:26:19740
[email protected]0877e3d2009-10-17 22:29:57741 // Check for an intermediate 100 Continue response. An origin server is
742 // allowed to send this response even if we didn't ask for it, so we just
743 // need to skip over it.
744 // We treat any other 1xx in this same way (although in practice getting
745 // a 1xx that isn't a 100 is rare).
[email protected]a7e41312009-12-16 23:18:14746 if (response_.headers->response_code() / 100 == 1) {
[email protected]ee9410e72010-01-07 01:42:38747 response_.headers = new HttpResponseHeaders("");
[email protected]0877e3d2009-10-17 22:29:57748 next_state_ = STATE_READ_HEADERS;
749 return OK;
750 }
751
[email protected]8e6441ca2010-08-19 05:56:38752 HostPortPair endpoint = HostPortPair(request_->url.HostNoBrackets(),
753 request_->url.EffectiveIntPort());
754 ProcessAlternateProtocol(session_->http_stream_factory(),
755 session_->mutable_alternate_protocols(),
756 *response_.headers,
757 endpoint);
[email protected]564b4912010-03-09 16:30:42758
[email protected]e772db3f2010-07-12 18:11:13759 int rv = HandleAuthChallenge();
[email protected]0877e3d2009-10-17 22:29:57760 if (rv != OK)
761 return rv;
762
[email protected]8536ef52010-09-30 16:18:21763 if (is_https_request())
764 stream_->GetSSLInfo(&response_.ssl_info);
765
[email protected]0877e3d2009-10-17 22:29:57766 headers_valid_ = true;
767 return OK;
initial.commit586acc5fe2008-07-26 22:42:52768}
769
770int HttpNetworkTransaction::DoReadBody() {
771 DCHECK(read_buf_);
[email protected]6501bc02009-06-25 20:55:13772 DCHECK_GT(read_buf_len_, 0);
[email protected]8e6441ca2010-08-19 05:56:38773 DCHECK(stream_ != NULL);
initial.commit586acc5fe2008-07-26 22:42:52774
775 next_state_ = STATE_READ_BODY_COMPLETE;
[email protected]351ab642010-08-05 16:55:31776 return stream_->ReadResponseBody(read_buf_, read_buf_len_, &io_callback_);
initial.commit586acc5fe2008-07-26 22:42:52777}
778
779int HttpNetworkTransaction::DoReadBodyComplete(int result) {
780 // We are done with the Read call.
[email protected]8e6441ca2010-08-19 05:56:38781 bool done = false;
782 if (result <= 0) {
783 DCHECK_NE(ERR_IO_PENDING, result);
initial.commit586acc5fe2008-07-26 22:42:52784 done = true;
[email protected]8e6441ca2010-08-19 05:56:38785 }
[email protected]9492e4a2010-02-24 00:58:46786
[email protected]8e6441ca2010-08-19 05:56:38787 bool keep_alive = false;
[email protected]351ab642010-08-05 16:55:31788 if (stream_->IsResponseBodyComplete()) {
[email protected]8e6441ca2010-08-19 05:56:38789 // Note: Just because IsResponseBodyComplete is true, we're not
790 // necessarily "done". We're only "done" when it is the last
791 // read on this HttpNetworkTransaction, which will be signified
792 // by a zero-length read.
793 // TODO(mbelshe): The keepalive property is really a property of
794 // the stream. No need to compute it here just to pass back
795 // to the stream's Close function.
[email protected]351ab642010-08-05 16:55:31796 if (stream_->CanFindEndOfResponse())
[email protected]02c92c492010-03-08 21:28:14797 keep_alive = GetResponseHeaders()->IsKeepAlive();
initial.commit586acc5fe2008-07-26 22:42:52798 }
799
[email protected]8e6441ca2010-08-19 05:56:38800 // Clean up connection if we are done.
initial.commit586acc5fe2008-07-26 22:42:52801 if (done) {
[email protected]56300172008-11-06 18:42:55802 LogTransactionMetrics();
[email protected]8e6441ca2010-08-19 05:56:38803 stream_->Close(!keep_alive);
[email protected]e2a915a2010-08-19 07:55:01804 // Note: we don't reset the stream here. We've closed it, but we still
805 // need it around so that callers can call methods such as
806 // GetUploadProgress() and have them be meaningful.
807 // TODO(mbelshe): This means we closed the stream here, and we close it
808 // again in ~HttpNetworkTransaction. Clean that up.
809
[email protected]8e6441ca2010-08-19 05:56:38810 // The next Read call will return 0 (EOF).
initial.commit586acc5fe2008-07-26 22:42:52811 }
812
813 // Clear these to avoid leaving around old state.
814 read_buf_ = NULL;
815 read_buf_len_ = 0;
816
817 return result;
818}
819
[email protected]2d2697f92009-02-18 21:00:32820int HttpNetworkTransaction::DoDrainBodyForAuthRestart() {
821 // This method differs from DoReadBody only in the next_state_. So we just
822 // call DoReadBody and override the next_state_. Perhaps there is a more
823 // elegant way for these two methods to share code.
824 int rv = DoReadBody();
825 DCHECK(next_state_ == STATE_READ_BODY_COMPLETE);
826 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE;
827 return rv;
828}
829
[email protected]0877e3d2009-10-17 22:29:57830// TODO(wtc): This method and the DoReadBodyComplete method are almost
831// the same. Figure out a good way for these two methods to share code.
[email protected]2d2697f92009-02-18 21:00:32832int HttpNetworkTransaction::DoDrainBodyForAuthRestartComplete(int result) {
[email protected]68873ba2009-06-04 21:49:23833 // keep_alive defaults to true because the very reason we're draining the
834 // response body is to reuse the connection for auth restart.
835 bool done = false, keep_alive = true;
[email protected]2d2697f92009-02-18 21:00:32836 if (result < 0) {
[email protected]0877e3d2009-10-17 22:29:57837 // Error or closed connection while reading the socket.
[email protected]2d2697f92009-02-18 21:00:32838 done = true;
[email protected]68873ba2009-06-04 21:49:23839 keep_alive = false;
[email protected]351ab642010-08-05 16:55:31840 } else if (stream_->IsResponseBodyComplete()) {
[email protected]0877e3d2009-10-17 22:29:57841 done = true;
[email protected]2d2697f92009-02-18 21:00:32842 }
843
844 if (done) {
845 DidDrainBodyForAuthRestart(keep_alive);
846 } else {
847 // Keep draining.
848 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
849 }
850
851 return OK;
852}
853
[email protected]8e3d2d32010-06-13 18:46:23854void HttpNetworkTransaction::LogTransactionConnectedMetrics() {
855 if (logged_response_time_)
856 return;
857
858 logged_response_time_ = true;
859
[email protected]a7e41312009-12-16 23:18:14860 base::TimeDelta total_duration = response_.response_time - start_time_;
[email protected]9a0a55f2009-04-13 23:23:03861
[email protected]510e854f2009-04-20 18:39:08862 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:58863 "Net.Transaction_Connected_Under_10",
[email protected]510e854f2009-04-20 18:39:08864 total_duration,
[email protected]9a0a55f2009-04-13 23:23:03865 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
866 100);
[email protected]1fa47592009-07-27 22:45:00867
[email protected]c38ec5a2010-08-25 23:32:38868 bool reused_socket = stream_->IsConnectionReused();
869 if (!reused_socket) {
[email protected]b01998a2009-04-21 01:01:11870 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:58871 "Net.Transaction_Connected_New",
[email protected]b01998a2009-04-21 01:01:11872 total_duration,
873 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
874 100);
[email protected]d068f7a2010-06-07 15:12:59875
876 static bool use_conn_impact_histogram(
[email protected]835d7c82010-10-14 04:38:38877 base::FieldTrialList::Find("ConnCountImpact") &&
878 !base::FieldTrialList::Find("ConnCountImpact")->group_name().empty());
[email protected]d068f7a2010-06-07 15:12:59879 if (use_conn_impact_histogram) {
880 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]835d7c82010-10-14 04:38:38881 base::FieldTrial::MakeName("Net.Transaction_Connected_New",
[email protected]d068f7a2010-06-07 15:12:59882 "ConnCountImpact"),
883 total_duration,
884 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
885 100);
886 }
[email protected]0310d432009-08-25 07:49:52887 }
888
[email protected]835d7c82010-10-14 04:38:38889 static bool use_spdy_histogram(base::FieldTrialList::Find("SpdyImpact") &&
890 !base::FieldTrialList::Find("SpdyImpact")->group_name().empty());
[email protected]8e3d2d32010-06-13 18:46:23891 if (use_spdy_histogram && response_.was_npn_negotiated) {
892 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]835d7c82010-10-14 04:38:38893 base::FieldTrial::MakeName("Net.Transaction_Connected_Under_10",
894 "SpdyImpact"),
[email protected]8e3d2d32010-06-13 18:46:23895 total_duration, base::TimeDelta::FromMilliseconds(1),
896 base::TimeDelta::FromMinutes(10), 100);
897
[email protected]c38ec5a2010-08-25 23:32:38898 if (!reused_socket) {
[email protected]8e3d2d32010-06-13 18:46:23899 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]835d7c82010-10-14 04:38:38900 base::FieldTrial::MakeName("Net.Transaction_Connected_New",
901 "SpdyImpact"),
[email protected]8e3d2d32010-06-13 18:46:23902 total_duration, base::TimeDelta::FromMilliseconds(1),
903 base::TimeDelta::FromMinutes(10), 100);
904 }
905 }
906
[email protected]510e854f2009-04-20 18:39:08907 // Currently, non-zero priority requests are frame or sub-frame resource
908 // types. This will change when we also prioritize certain subresources like
909 // css, js, etc.
910 if (request_->priority) {
911 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:58912 "Net.Priority_High_Latency",
[email protected]510e854f2009-04-20 18:39:08913 total_duration,
914 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
915 100);
916 } else {
917 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:58918 "Net.Priority_Low_Latency",
[email protected]510e854f2009-04-20 18:39:08919 total_duration,
920 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
921 100);
922 }
[email protected]9a0a55f2009-04-13 23:23:03923}
924
[email protected]56300172008-11-06 18:42:55925void HttpNetworkTransaction::LogTransactionMetrics() const {
[email protected]0877e3d2009-10-17 22:29:57926 base::TimeDelta duration = base::Time::Now() -
[email protected]2227c692010-05-04 15:36:11927 response_.request_time;
[email protected]56300172008-11-06 18:42:55928 if (60 < duration.InMinutes())
929 return;
[email protected]0b48db42009-03-23 02:45:11930
[email protected]21b316a2009-03-23 18:25:06931 base::TimeDelta total_duration = base::Time::Now() - start_time_;
932
[email protected]f929f2f22009-06-12 16:56:58933 UMA_HISTOGRAM_LONG_TIMES("Net.Transaction_Latency", duration);
934 UMA_HISTOGRAM_CLIPPED_TIMES("Net.Transaction_Latency_Under_10", duration,
[email protected]2227c692010-05-04 15:36:11935 base::TimeDelta::FromMilliseconds(1),
936 base::TimeDelta::FromMinutes(10),
937 100);
[email protected]f929f2f22009-06-12 16:56:58938 UMA_HISTOGRAM_CLIPPED_TIMES("Net.Transaction_Latency_Total_Under_10",
[email protected]2227c692010-05-04 15:36:11939 total_duration,
940 base::TimeDelta::FromMilliseconds(1),
941 base::TimeDelta::FromMinutes(10), 100);
[email protected]c38ec5a2010-08-25 23:32:38942 if (!stream_->IsConnectionReused()) {
[email protected]f929f2f22009-06-12 16:56:58943 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]808f6402009-03-30 20:02:07944 "Net.Transaction_Latency_Total_New_Connection_Under_10",
[email protected]808f6402009-03-30 20:02:07945 total_duration, base::TimeDelta::FromMilliseconds(1),
946 base::TimeDelta::FromMinutes(10), 100);
947 }
[email protected]56300172008-11-06 18:42:55948}
949
[email protected]5e363962009-06-19 19:57:01950int HttpNetworkTransaction::HandleCertificateRequest(int error) {
[email protected]8e6441ca2010-08-19 05:56:38951 // There are two paths through which the server can request a certificate
952 // from us. The first is during the initial handshake, the second is
953 // during SSL renegotiation.
954 //
955 // In both cases, we want to close the connection before proceeding.
956 // We do this for two reasons:
957 // First, we don't want to keep the connection to the server hung for a
958 // long time while the user selects a certificate.
959 // Second, even if we did keep the connection open, NSS has a bug where
960 // restarting the handshake for ClientAuth is currently broken.
[email protected]65a3b912010-08-21 05:46:58961 DCHECK_EQ(error, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8e6441ca2010-08-19 05:56:38962
963 if (stream_.get()) {
964 // Since we already have a stream, we're being called as part of SSL
965 // renegotiation.
966 DCHECK(!stream_request_.get());
967 stream_->Close(true);
968 stream_.reset();
969 }
970
[email protected]26816882010-10-14 18:03:09971 // The server is asking for a client certificate during the initial
972 // handshake.
973 stream_request_.reset();
[email protected]5e363962009-06-19 19:57:01974
[email protected]ec229bc92010-11-22 09:51:45975 // If the user selected one of the certificates in client_certs or declined
976 // to provide one for this server before, use the past decision
977 // automatically.
978 scoped_refptr<X509Certificate> client_cert;
979 bool found_cached_cert = session_->ssl_client_auth_cache()->Lookup(
980 response_.cert_request_info->host_and_port, &client_cert);
981 if (!found_cached_cert)
982 return error;
983
984 // Check that the certificate selected is still a certificate the server
985 // is likely to accept, based on the criteria supplied in the
986 // CertificateRequest message.
[email protected]5e363962009-06-19 19:57:01987 if (client_cert) {
988 const std::vector<scoped_refptr<X509Certificate> >& client_certs =
[email protected]a7e41312009-12-16 23:18:14989 response_.cert_request_info->client_certs;
[email protected]ec229bc92010-11-22 09:51:45990 bool cert_still_valid = false;
[email protected]5e363962009-06-19 19:57:01991 for (size_t i = 0; i < client_certs.size(); ++i) {
[email protected]ec229bc92010-11-22 09:51:45992 if (client_cert->Equals(client_certs[i])) {
993 cert_still_valid = true;
994 break;
[email protected]5e363962009-06-19 19:57:01995 }
996 }
[email protected]ec229bc92010-11-22 09:51:45997
998 if (!cert_still_valid)
999 return error;
[email protected]5e363962009-06-19 19:57:011000 }
[email protected]ec229bc92010-11-22 09:51:451001
1002 // TODO(davidben): Add a unit test which covers this path; we need to be
1003 // able to send a legitimate certificate and also bypass/clear the
1004 // SSL session cache.
1005 ssl_config_.client_cert = client_cert;
1006 ssl_config_.send_client_cert = true;
1007 next_state_ = STATE_CREATE_STREAM;
1008 // Reset the other member variables.
1009 // Note: this is necessary only with SSL renegotiation.
1010 ResetStateForRestart();
1011 return OK;
[email protected]0b45559b2009-06-12 21:45:111012}
1013
[email protected]bd0b6772011-01-11 19:59:301014// TODO(rch): This does not correctly handle errors when an SSL proxy is
1015// being used, as all of the errors are handled as if they were generated
1016// by the endpoint host, request_->url, rather than considering if they were
[email protected]1c53a1f2011-01-13 00:36:381017// generated by the SSL proxy. http://crbug.com/69329
[email protected]bd0b6772011-01-11 19:59:301018int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
1019 DCHECK(request_);
1020 if (ssl_config_.send_client_cert &&
1021 (error == ERR_SSL_PROTOCOL_ERROR ||
1022 error == ERR_BAD_SSL_CLIENT_AUTH_CERT)) {
1023 session_->ssl_client_auth_cache()->Remove(
1024 GetHostAndPort(request_->url));
1025 }
1026
initial.commit586acc5fe2008-07-26 22:42:521027 switch (error) {
[email protected]bd0b6772011-01-11 19:59:301028 case ERR_SSL_PROTOCOL_ERROR:
1029 case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
1030 case ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
1031 case ERR_SSL_BAD_RECORD_MAC_ALERT:
1032 if (ssl_config_.tls1_enabled &&
1033 !SSLConfigService::IsKnownStrictTLSServer(request_->url.host())) {
1034 // This could be a TLS-intolerant server, an SSL 3.0 server that
1035 // chose a TLS-only cipher suite or a server with buggy DEFLATE
1036 // support. Turn off TLS 1.0, DEFLATE support and retry.
1037 session_->http_stream_factory()->AddTLSIntolerantServer(request_->url);
[email protected]1c773ea12009-04-28 19:58:421038 ResetConnectionAndRequestForResend();
initial.commit586acc5fe2008-07-26 22:42:521039 error = OK;
[email protected]1c773ea12009-04-28 19:58:421040 }
initial.commit586acc5fe2008-07-26 22:42:521041 break;
[email protected]73b8dd222010-11-11 19:55:241042 case ERR_SSL_SNAP_START_NPN_MISPREDICTION:
1043 // This means that we tried to Snap Start a connection, but we
1044 // mispredicted the NPN result. This isn't a problem from the point of
1045 // view of the SSL layer because the server will ignore the application
1046 // data in the Snap Start extension. However, at the HTTP layer, we have
1047 // already decided that it's a HTTP or SPDY connection and it's easier to
1048 // abort and start again.
1049 ResetConnectionAndRequestForResend();
1050 error = OK;
1051 break;
initial.commit586acc5fe2008-07-26 22:42:521052 }
1053 return error;
1054}
1055
[email protected]bd0b6772011-01-11 19:59:301056// This method determines whether it is safe to resend the request after an
1057// IO error. It can only be called in response to request header or body
1058// write errors or response header read errors. It should not be used in
1059// other cases, such as a Connect error.
1060int HttpNetworkTransaction::HandleIOError(int error) {
1061 // SSL errors may happen at any time during the stream and indicate issues
1062 // with the underlying connection. Because the peer may request
1063 // renegotiation at any time, check and handle any possible SSL handshake
1064 // related errors. In addition to renegotiation, TLS False/Snap Start may
[email protected]1c53a1f2011-01-13 00:36:381065 // cause SSL handshake errors to be delayed until the first or second Write
1066 // (Snap Start) or the first Read (False & Snap Start) on the underlying
1067 // connection.
[email protected]bd0b6772011-01-11 19:59:301068 error = HandleSSLHandshakeError(error);
1069
1070 switch (error) {
1071 // If we try to reuse a connection that the server is in the process of
1072 // closing, we may end up successfully writing out our request (or a
1073 // portion of our request) only to find a connection error when we try to
1074 // read from (or finish writing to) the socket.
1075 case ERR_CONNECTION_RESET:
1076 case ERR_CONNECTION_CLOSED:
1077 case ERR_CONNECTION_ABORTED:
1078 if (ShouldResendRequest(error)) {
1079 ResetConnectionAndRequestForResend();
1080 error = OK;
1081 }
1082 break;
1083 }
1084 return error;
1085}
1086
[email protected]c3b35c22008-09-27 03:19:421087void HttpNetworkTransaction::ResetStateForRestart() {
[email protected]697ef4c2010-10-14 16:38:581088 ResetStateForAuthRestart();
1089 stream_.reset();
1090}
1091
1092void HttpNetworkTransaction::ResetStateForAuthRestart() {
[email protected]0757e7702009-03-27 04:00:221093 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:421094 read_buf_ = NULL;
1095 read_buf_len_ = 0;
[email protected]0877e3d2009-10-17 22:29:571096 headers_valid_ = false;
[email protected]b94f92d2010-10-27 16:45:201097 request_headers_.Clear();
[email protected]a7e41312009-12-16 23:18:141098 response_ = HttpResponseInfo();
[email protected]8e6441ca2010-08-19 05:56:381099 establishing_tunnel_ = false;
[email protected]0877e3d2009-10-17 22:29:571100}
1101
1102HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const {
[email protected]a7e41312009-12-16 23:18:141103 return response_.headers;
[email protected]c3b35c22008-09-27 03:19:421104}
1105
[email protected]a19f1c602009-08-24 21:35:281106bool HttpNetworkTransaction::ShouldResendRequest(int error) const {
[email protected]8e6441ca2010-08-19 05:56:381107 bool connection_is_proven = stream_->IsConnectionReused();
1108 bool has_received_headers = GetResponseHeaders() != NULL;
[email protected]58cebf8f2010-07-31 19:20:161109
[email protected]2a5c76b2008-09-25 22:15:161110 // NOTE: we resend a request only if we reused a keep-alive connection.
1111 // This automatically prevents an infinite resend loop because we'll run
1112 // out of the cached keep-alive connections eventually.
[email protected]8e6441ca2010-08-19 05:56:381113 if (connection_is_proven && !has_received_headers)
1114 return true;
1115 return false;
[email protected]1c773ea12009-04-28 19:58:421116}
1117
1118void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
[email protected]8e6441ca2010-08-19 05:56:381119 if (stream_.get()) {
1120 stream_->Close(true);
1121 stream_.reset();
[email protected]58cebf8f2010-07-31 19:20:161122 }
1123
[email protected]0877e3d2009-10-17 22:29:571124 // We need to clear request_headers_ because it contains the real request
1125 // headers, but we may need to resend the CONNECT request first to recreate
1126 // the SSL tunnel.
[email protected]b94f92d2010-10-27 16:45:201127 request_headers_.Clear();
[email protected]82918cc2010-08-25 17:24:501128 next_state_ = STATE_CREATE_STREAM; // Resend the request.
[email protected]86ec30d2008-09-29 21:53:541129}
1130
[email protected]1c773ea12009-04-28 19:58:421131bool HttpNetworkTransaction::ShouldApplyProxyAuth() const {
[email protected]2df19bb2010-08-25 20:13:461132 return !is_https_request() &&
1133 (proxy_info_.is_https() || proxy_info_.is_http());
[email protected]1c773ea12009-04-28 19:58:421134}
license.botbf09a502008-08-24 00:55:551135
[email protected]1c773ea12009-04-28 19:58:421136bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
[email protected]8a1f3312010-05-25 19:25:041137 return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA);
[email protected]1c773ea12009-04-28 19:58:421138}
1139
[email protected]e772db3f2010-07-12 18:11:131140int HttpNetworkTransaction::HandleAuthChallenge() {
[email protected]ad8e04a2010-11-01 04:16:271141 scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders());
[email protected]0877e3d2009-10-17 22:29:571142 DCHECK(headers);
[email protected]c3b35c22008-09-27 03:19:421143
[email protected]0877e3d2009-10-17 22:29:571144 int status = headers->response_code();
[email protected]c3b35c22008-09-27 03:19:421145 if (status != 401 && status != 407)
1146 return OK;
1147 HttpAuth::Target target = status == 407 ?
[email protected]2227c692010-05-04 15:36:111148 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER;
[email protected]038e9a32008-10-08 22:40:161149 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
1150 return ERR_UNEXPECTED_PROXY_AUTH;
[email protected]c3b35c22008-09-27 03:19:421151
[email protected]7a67a8152010-11-05 18:31:101152 // This case can trigger when an HTTPS server responds with a 407 status
1153 // code through a non-authenticating proxy.
1154 if (!auth_controllers_[target].get())
1155 return ERR_UNEXPECTED_PROXY_AUTH;
1156
[email protected]a7ea8832010-07-12 17:54:541157 int rv = auth_controllers_[target]->HandleAuthChallenge(
[email protected]560c0432010-07-13 20:45:311158 headers, (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false,
1159 net_log_);
[email protected]228404f2010-06-24 04:31:411160 if (auth_controllers_[target]->HaveAuthHandler())
1161 pending_auth_target_ = target;
1162
1163 scoped_refptr<AuthChallengeInfo> auth_info =
1164 auth_controllers_[target]->auth_info();
1165 if (auth_info.get())
1166 response_.auth_challenge = auth_info;
1167
[email protected]228404f2010-06-24 04:31:411168 return rv;
[email protected]f9ee6b52008-11-08 06:46:231169}
1170
[email protected]8e6441ca2010-08-19 05:56:381171bool HttpNetworkTransaction::HaveAuth(HttpAuth::Target target) const {
1172 return auth_controllers_[target].get() &&
1173 auth_controllers_[target]->HaveAuth();
1174}
1175
1176
[email protected]228404f2010-06-24 04:31:411177GURL HttpNetworkTransaction::AuthURL(HttpAuth::Target target) const {
1178 switch (target) {
[email protected]2df19bb2010-08-25 20:13:461179 case HttpAuth::AUTH_PROXY: {
[email protected]228404f2010-06-24 04:31:411180 if (!proxy_info_.proxy_server().is_valid() ||
1181 proxy_info_.proxy_server().is_direct()) {
1182 return GURL(); // There is no proxy server.
1183 }
[email protected]2df19bb2010-08-25 20:13:461184 const char* scheme = proxy_info_.is_https() ? "https://" : "http://";
1185 return GURL(scheme +
[email protected]2fbaecf22010-07-22 22:20:351186 proxy_info_.proxy_server().host_port_pair().ToString());
[email protected]2df19bb2010-08-25 20:13:461187 }
[email protected]228404f2010-06-24 04:31:411188 case HttpAuth::AUTH_SERVER:
1189 return request_->url;
1190 default:
1191 return GURL();
1192 }
[email protected]c3b35c22008-09-27 03:19:421193}
1194
[email protected]d8eb84242010-09-25 02:25:061195#define STATE_CASE(s) \
1196 case s: \
1197 description = base::StringPrintf("%s (0x%08X)", #s, s); \
1198 break
[email protected]aef04272010-06-28 18:03:041199
1200std::string HttpNetworkTransaction::DescribeState(State state) {
1201 std::string description;
1202 switch (state) {
[email protected]82918cc2010-08-25 17:24:501203 STATE_CASE(STATE_CREATE_STREAM);
1204 STATE_CASE(STATE_CREATE_STREAM_COMPLETE);
[email protected]aef04272010-06-28 18:03:041205 STATE_CASE(STATE_SEND_REQUEST);
1206 STATE_CASE(STATE_SEND_REQUEST_COMPLETE);
1207 STATE_CASE(STATE_READ_HEADERS);
1208 STATE_CASE(STATE_READ_HEADERS_COMPLETE);
[email protected]aef04272010-06-28 18:03:041209 STATE_CASE(STATE_READ_BODY);
1210 STATE_CASE(STATE_READ_BODY_COMPLETE);
1211 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART);
1212 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE);
[email protected]aef04272010-06-28 18:03:041213 STATE_CASE(STATE_NONE);
1214 default:
[email protected]d8eb84242010-09-25 02:25:061215 description = base::StringPrintf("Unknown state 0x%08X (%u)", state,
1216 state);
[email protected]aef04272010-06-28 18:03:041217 break;
1218 }
1219 return description;
1220}
1221
[email protected]c9c6f5c2010-07-31 01:30:031222// TODO(gavinp): re-adjust this once SPDY v3 has three priority bits,
1223// eliminating the need for this folding.
1224int ConvertRequestPriorityToSpdyPriority(const RequestPriority priority) {
1225 DCHECK(HIGHEST <= priority && priority < NUM_PRIORITIES);
1226 switch (priority) {
1227 case LOWEST:
1228 return SPDY_PRIORITY_LOWEST-1;
1229 case IDLE:
1230 return SPDY_PRIORITY_LOWEST;
1231 default:
1232 return priority;
1233 }
1234}
1235
1236
1237
[email protected]aef04272010-06-28 18:03:041238#undef STATE_CASE
1239
[email protected]c3b35c22008-09-27 03:19:421240} // namespace net