blob: 32f85309ad38ad9af4f03eace42e90a7fdebf033 [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]68bf9152008-09-25 19:47:307#include "base/compiler_specific.h"
[email protected]0b48db42009-03-23 02:45:118#include "base/field_trial.h"
[email protected]270c6412010-03-29 22:02:479#include "base/format_macros.h"
[email protected]21983942009-08-18 06:17:5010#include "base/histogram.h"
[email protected]270c6412010-03-29 22:02:4711#include "base/scoped_ptr.h"
[email protected]5e2e6c77d12009-12-24 21:57:1612#include "base/stats_counters.h"
[email protected]aeaca1f2010-04-20 22:05:2113#include "base/stl_util-inl.h"
initial.commit586acc5fe2008-07-26 22:42:5214#include "base/string_util.h"
[email protected]68bf9152008-09-25 19:47:3015#include "build/build_config.h"
[email protected]631f1322010-04-30 17:59:1116#include "googleurl/src/gurl.h"
[email protected]5d0153c512009-01-12 19:08:3617#include "net/base/connection_type_histograms.h"
[email protected]b6a50182010-05-12 22:47:1418#include "net/base/host_mapping_rules.h"
[email protected]74a85ce2009-02-12 00:03:1919#include "net/base/io_buffer.h"
initial.commit586acc5fe2008-07-26 22:42:5220#include "net/base/load_flags.h"
[email protected]597cf6e2009-05-29 09:43:2621#include "net/base/net_errors.h"
[email protected]c3b35c22008-09-27 03:19:4222#include "net/base/net_util.h"
[email protected]0b45559b2009-06-12 21:45:1123#include "net/base/ssl_cert_request_info.h"
[email protected]fc7de492010-07-12 14:49:0424#include "net/base/ssl_connection_status_flags.h"
initial.commit586acc5fe2008-07-26 22:42:5225#include "net/base/upload_data_stream.h"
[email protected]c3b35c22008-09-27 03:19:4226#include "net/http/http_auth.h"
27#include "net/http/http_auth_handler.h"
[email protected]fa82f932010-05-20 11:09:2428#include "net/http/http_auth_handler_factory.h"
[email protected]8d5a34e2009-06-11 21:21:3629#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5230#include "net/http/http_chunked_decoder.h"
[email protected]a7ea8832010-07-12 17:54:5431#include "net/http/http_net_log_params.h"
initial.commit586acc5fe2008-07-26 22:42:5232#include "net/http/http_network_session.h"
[email protected]a7ea8832010-07-12 17:54:5433#include "net/http/http_proxy_client_socket.h"
[email protected]e772db3f2010-07-12 18:11:1334#include "net/http/http_proxy_client_socket_pool.h"
[email protected]270c6412010-03-29 22:02:4735#include "net/http/http_request_headers.h"
initial.commit586acc5fe2008-07-26 22:42:5236#include "net/http/http_request_info.h"
[email protected]319d9e6f2009-02-18 19:47:2137#include "net/http/http_response_headers.h"
[email protected]0877e3d2009-10-17 22:29:5738#include "net/http/http_response_info.h"
initial.commit586acc5fe2008-07-26 22:42:5239#include "net/http/http_util.h"
[email protected]d7f16632010-03-29 18:02:3640#include "net/http/url_security_manager.h"
[email protected]f7984fc62009-06-22 23:26:4441#include "net/socket/client_socket_factory.h"
[email protected]a796bcec2010-03-22 17:17:2642#include "net/socket/socks_client_socket_pool.h"
[email protected]f7984fc62009-06-22 23:26:4443#include "net/socket/ssl_client_socket.h"
[email protected]7fc5b09a2010-02-27 00:07:3844#include "net/socket/tcp_client_socket_pool.h"
[email protected]65d56aa2010-06-14 04:13:4045#include "net/spdy/spdy_http_stream.h"
[email protected]dab9c7d2010-02-06 21:44:3246#include "net/spdy/spdy_session.h"
47#include "net/spdy/spdy_session_pool.h"
initial.commit586acc5fe2008-07-26 22:42:5248
[email protected]e1acf6f2008-10-27 20:43:3349using base::Time;
50
initial.commit586acc5fe2008-07-26 22:42:5251namespace net {
52
[email protected]1c773ea12009-04-28 19:58:4253namespace {
54
[email protected]b6a50182010-05-12 22:47:1455const HostMappingRules* g_host_mapping_rules = NULL;
[email protected]a2cb8122010-03-10 17:22:4256const std::string* g_next_protos = NULL;
[email protected]31e2c69e2010-04-15 18:06:0657bool g_use_alternate_protocols = false;
[email protected]a2cb8122010-03-10 17:22:4258
[email protected]aeaca1f2010-04-20 22:05:2159// A set of host:port strings. These are servers which we have needed to back
60// off to SSLv3 for.
61std::set<std::string>* g_tls_intolerant_servers = NULL;
62
[email protected]1c773ea12009-04-28 19:58:4263void BuildRequestHeaders(const HttpRequestInfo* request_info,
[email protected]270c6412010-03-29 22:02:4764 const HttpRequestHeaders& authorization_headers,
[email protected]1c773ea12009-04-28 19:58:4265 const UploadDataStream* upload_data_stream,
66 bool using_proxy,
[email protected]8c76ae22010-04-20 22:15:4367 std::string* request_line,
[email protected]270c6412010-03-29 22:02:4768 HttpRequestHeaders* request_headers) {
69 const std::string path = using_proxy ?
[email protected]2227c692010-05-04 15:36:1170 HttpUtil::SpecForRequest(request_info->url) :
71 HttpUtil::PathForRequest(request_info->url);
[email protected]8c76ae22010-04-20 22:15:4372 *request_line = StringPrintf(
73 "%s %s HTTP/1.1\r\n", request_info->method.c_str(), path.c_str());
[email protected]270c6412010-03-29 22:02:4774 request_headers->SetHeader(HttpRequestHeaders::kHost,
75 GetHostAndOptionalPort(request_info->url));
76
77 // For compat with HTTP/1.0 servers and proxies:
78 if (using_proxy) {
79 request_headers->SetHeader(HttpRequestHeaders::kProxyConnection,
80 "keep-alive");
81 } else {
82 request_headers->SetHeader(HttpRequestHeaders::kConnection, "keep-alive");
83 }
84
[email protected]270c6412010-03-29 22:02:4785 // Our consumer should have made sure that this is a safe referrer. See for
86 // instance WebCore::FrameLoader::HideReferrer.
87 if (request_info->referrer.is_valid()) {
88 request_headers->SetHeader(HttpRequestHeaders::kReferer,
89 request_info->referrer.spec());
90 }
91
92 // Add a content length header?
93 if (upload_data_stream) {
94 request_headers->SetHeader(
95 HttpRequestHeaders::kContentLength,
96 Uint64ToString(upload_data_stream->size()));
97 } else if (request_info->method == "POST" || request_info->method == "PUT" ||
98 request_info->method == "HEAD") {
99 // An empty POST/PUT request still needs a content length. As for HEAD,
100 // IE and Safari also add a content length header. Presumably it is to
101 // support sending a HEAD request to an URL that only expects to be sent a
102 // POST or some other method that normally would have a message body.
103 request_headers->SetHeader(HttpRequestHeaders::kContentLength, "0");
104 }
105
106 // Honor load flags that impact proxy caches.
107 if (request_info->load_flags & LOAD_BYPASS_CACHE) {
108 request_headers->SetHeader(HttpRequestHeaders::kPragma, "no-cache");
109 request_headers->SetHeader(HttpRequestHeaders::kCacheControl, "no-cache");
110 } else if (request_info->load_flags & LOAD_VALIDATE_CACHE) {
111 request_headers->SetHeader(HttpRequestHeaders::kCacheControl, "max-age=0");
112 }
113
114 request_headers->MergeFrom(authorization_headers);
115
[email protected]860c85d2010-02-10 07:22:40116 // Headers that will be stripped from request_info->extra_headers to prevent,
117 // e.g., plugins from overriding headers that are controlled using other
118 // means. Otherwise a plugin could set a referrer although sending the
119 // referrer is inhibited.
120 // TODO(jochen): check whether also other headers should be stripped.
121 static const char* const kExtraHeadersToBeStripped[] = {
122 "Referer"
123 };
124
[email protected]8c76ae22010-04-20 22:15:43125 HttpRequestHeaders stripped_extra_headers;
126 stripped_extra_headers.CopyFrom(request_info->extra_headers);
[email protected]2227c692010-05-04 15:36:11127 for (size_t i = 0; i < arraysize(kExtraHeadersToBeStripped); ++i)
128 stripped_extra_headers.RemoveHeader(kExtraHeadersToBeStripped[i]);
[email protected]8c76ae22010-04-20 22:15:43129 request_headers->MergeFrom(stripped_extra_headers);
[email protected]1c773ea12009-04-28 19:58:42130}
131
[email protected]564b4912010-03-09 16:30:42132void ProcessAlternateProtocol(const HttpResponseHeaders& headers,
133 const HostPortPair& http_host_port_pair,
134 HttpAlternateProtocols* alternate_protocols) {
[email protected]a2cb8122010-03-10 17:22:42135
[email protected]564b4912010-03-09 16:30:42136 std::string alternate_protocol_str;
137 if (!headers.EnumerateHeader(NULL, HttpAlternateProtocols::kHeader,
138 &alternate_protocol_str)) {
139 // Header is not present.
140 return;
141 }
142
143 std::vector<std::string> port_protocol_vector;
144 SplitString(alternate_protocol_str, ':', &port_protocol_vector);
145 if (port_protocol_vector.size() != 2) {
146 DLOG(WARNING) << HttpAlternateProtocols::kHeader
147 << " header has too many tokens: "
148 << alternate_protocol_str;
149 return;
150 }
151
152 int port;
153 if (!StringToInt(port_protocol_vector[0], &port) ||
154 port <= 0 || port >= 1 << 16) {
155 DLOG(WARNING) << HttpAlternateProtocols::kHeader
156 << " header has unrecognizable port: "
157 << port_protocol_vector[0];
158 return;
159 }
160
[email protected]a2cb8122010-03-10 17:22:42161 if (port_protocol_vector[1] !=
162 HttpAlternateProtocols::kProtocolStrings[
[email protected]2227c692010-05-04 15:36:11163 HttpAlternateProtocols::NPN_SPDY_1]) {
[email protected]a2cb8122010-03-10 17:22:42164 // Currently, we only recognize the npn-spdy protocol.
[email protected]564b4912010-03-09 16:30:42165 DLOG(WARNING) << HttpAlternateProtocols::kHeader
166 << " header has unrecognized protocol: "
167 << port_protocol_vector[1];
168 return;
169 }
170
[email protected]b6a50182010-05-12 22:47:14171 HostPortPair host_port(http_host_port_pair);
172 if (g_host_mapping_rules)
173 g_host_mapping_rules->RewriteHost(&host_port);
174
175 if (alternate_protocols->HasAlternateProtocolFor(host_port)) {
[email protected]564b4912010-03-09 16:30:42176 const HttpAlternateProtocols::PortProtocolPair existing_alternate =
[email protected]b6a50182010-05-12 22:47:14177 alternate_protocols->GetAlternateProtocolFor(host_port);
[email protected]564b4912010-03-09 16:30:42178 // If we think the alternate protocol is broken, don't change it.
179 if (existing_alternate.protocol == HttpAlternateProtocols::BROKEN)
180 return;
181 }
182
[email protected]a2cb8122010-03-10 17:22:42183 alternate_protocols->SetAlternateProtocolFor(
[email protected]b6a50182010-05-12 22:47:14184 host_port, port, HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:42185}
186
[email protected]1c773ea12009-04-28 19:58:42187} // namespace
188
initial.commit586acc5fe2008-07-26 22:42:52189//-----------------------------------------------------------------------------
190
[email protected]3ce7df0f2010-03-03 00:30:50191bool HttpNetworkTransaction::g_ignore_certificate_errors = false;
[email protected]1f14a912009-12-21 20:32:44192
[email protected]5695b8c2009-09-30 21:36:43193HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session)
[email protected]0757e7702009-03-27 04:00:22194 : pending_auth_target_(HttpAuth::AUTH_NONE),
195 ALLOW_THIS_IN_INITIALIZER_LIST(
[email protected]68bf9152008-09-25 19:47:30196 io_callback_(this, &HttpNetworkTransaction::OnIOComplete)),
initial.commit586acc5fe2008-07-26 22:42:52197 user_callback_(NULL),
198 session_(session),
199 request_(NULL),
200 pac_request_(NULL),
[email protected]1f14a912009-12-21 20:32:44201 connection_(new ClientSocketHandle),
initial.commit586acc5fe2008-07-26 22:42:52202 reused_socket_(false),
[email protected]0877e3d2009-10-17 22:29:57203 headers_valid_(false),
[email protected]8e3d2d32010-06-13 18:46:23204 logged_response_time_(false),
initial.commit586acc5fe2008-07-26 22:42:52205 using_ssl_(false),
[email protected]e0993912010-02-22 23:57:11206 using_spdy_(false),
[email protected]bdbda462010-06-28 17:30:37207 spdy_certificate_error_(OK),
[email protected]31e2c69e2010-04-15 18:06:06208 alternate_protocol_mode_(
209 g_use_alternate_protocols ? kUnspecified :
210 kDoNotUseAlternateProtocol),
initial.commit586acc5fe2008-07-26 22:42:52211 read_buf_len_(0),
[email protected]a7ea8832010-07-12 17:54:54212 next_state_(STATE_NONE),
213 establishing_tunnel_(false) {
[email protected]2cd713f2008-10-21 17:54:28214 session->ssl_config_service()->GetSSLConfig(&ssl_config_);
[email protected]1f14a912009-12-21 20:32:44215 if (g_next_protos)
216 ssl_config_.next_protos = *g_next_protos;
[email protected]aeaca1f2010-04-20 22:05:21217 if (!g_tls_intolerant_servers)
218 g_tls_intolerant_servers = new std::set<std::string>;
[email protected]1f14a912009-12-21 20:32:44219}
220
221// static
[email protected]b6a50182010-05-12 22:47:14222void HttpNetworkTransaction::SetHostMappingRules(const std::string& rules) {
223 HostMappingRules* host_mapping_rules = new HostMappingRules();
224 host_mapping_rules->SetRulesFromString(rules);
225 delete g_host_mapping_rules;
226 g_host_mapping_rules = host_mapping_rules;
227}
228
229// static
[email protected]31e2c69e2010-04-15 18:06:06230void HttpNetworkTransaction::SetUseAlternateProtocols(bool value) {
231 g_use_alternate_protocols = value;
232}
233
234// static
[email protected]1f14a912009-12-21 20:32:44235void HttpNetworkTransaction::SetNextProtos(const std::string& next_protos) {
236 delete g_next_protos;
237 g_next_protos = new std::string(next_protos);
initial.commit586acc5fe2008-07-26 22:42:52238}
239
[email protected]3ce7df0f2010-03-03 00:30:50240// static
241void HttpNetworkTransaction::IgnoreCertificateErrors(bool enabled) {
242 g_ignore_certificate_errors = enabled;
243}
244
[email protected]684970b2009-08-14 04:54:46245int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
246 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53247 const BoundNetLog& net_log) {
[email protected]5e2e6c77d12009-12-24 21:57:16248 SIMPLE_STATS_COUNTER("HttpNetworkTransaction.Count");
[email protected]5d0153c512009-01-12 19:08:36249
[email protected]9e743cd2010-03-16 07:03:53250 net_log_ = net_log;
[email protected]96d570e42008-08-05 22:43:04251 request_ = request_info;
[email protected]21b316a2009-03-23 18:25:06252 start_time_ = base::Time::Now();
[email protected]96d570e42008-08-05 22:43:04253
254 next_state_ = STATE_RESOLVE_PROXY;
255 int rv = DoLoop(OK);
256 if (rv == ERR_IO_PENDING)
257 user_callback_ = callback;
258 return rv;
259}
260
261int HttpNetworkTransaction::RestartIgnoringLastError(
262 CompletionCallback* callback) {
[email protected]1f14a912009-12-21 20:32:44263 if (connection_->socket()->IsConnectedAndIdle()) {
[email protected]fab9ca52010-02-19 23:14:48264 // TODO(wtc): Should we update any of the connection histograms that we
265 // update in DoSSLConnectComplete if |result| is OK?
[email protected]e0993912010-02-22 23:57:11266 if (using_spdy_) {
[email protected]044de0642010-06-17 10:42:15267 // TODO(cbentzel): Add auth support to spdy. See http://crbug.com/46620
[email protected]fab9ca52010-02-19 23:14:48268 next_state_ = STATE_SPDY_SEND_REQUEST;
269 } else {
[email protected]044de0642010-06-17 10:42:15270 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
[email protected]fab9ca52010-02-19 23:14:48271 }
[email protected]bacff652009-03-31 17:50:33272 } else {
[email protected]1f14a912009-12-21 20:32:44273 connection_->socket()->Disconnect();
274 connection_->Reset();
[email protected]bacff652009-03-31 17:50:33275 next_state_ = STATE_INIT_CONNECTION;
276 }
[email protected]ccb40e52008-09-17 20:54:40277 int rv = DoLoop(OK);
278 if (rv == ERR_IO_PENDING)
279 user_callback_ = callback;
[email protected]aaead502008-10-15 00:20:11280 return rv;
[email protected]96d570e42008-08-05 22:43:04281}
282
[email protected]0b45559b2009-06-12 21:45:11283int HttpNetworkTransaction::RestartWithCertificate(
284 X509Certificate* client_cert,
285 CompletionCallback* callback) {
286 ssl_config_.client_cert = client_cert;
[email protected]5e363962009-06-19 19:57:01287 if (client_cert) {
288 session_->ssl_client_auth_cache()->Add(GetHostAndPort(request_->url),
289 client_cert);
290 }
[email protected]0b45559b2009-06-12 21:45:11291 ssl_config_.send_client_cert = true;
292 next_state_ = STATE_INIT_CONNECTION;
293 // Reset the other member variables.
294 // Note: this is necessary only with SSL renegotiation.
295 ResetStateForRestart();
296 int rv = DoLoop(OK);
297 if (rv == ERR_IO_PENDING)
298 user_callback_ = callback;
299 return rv;
300}
301
[email protected]96d570e42008-08-05 22:43:04302int HttpNetworkTransaction::RestartWithAuth(
303 const std::wstring& username,
304 const std::wstring& password,
305 CompletionCallback* callback) {
[email protected]0757e7702009-03-27 04:00:22306 HttpAuth::Target target = pending_auth_target_;
307 if (target == HttpAuth::AUTH_NONE) {
308 NOTREACHED();
309 return ERR_UNEXPECTED;
310 }
[email protected]0757e7702009-03-27 04:00:22311 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:42312
[email protected]e772db3f2010-07-12 18:11:13313 auth_controllers_[target]->ResetAuth(username, password);
314
[email protected]a7ea8832010-07-12 17:54:54315 if (target == HttpAuth::AUTH_PROXY && using_ssl_ && proxy_info_.is_http()) {
316 DCHECK(establishing_tunnel_);
317 ResetStateForRestart();
[email protected]a7ea8832010-07-12 17:54:54318 next_state_ = STATE_TUNNEL_RESTART_WITH_AUTH;
319 } else {
[email protected]a7ea8832010-07-12 17:54:54320 PrepareForAuthRestart(target);
321 }
[email protected]c3b35c22008-09-27 03:19:42322
323 DCHECK(user_callback_ == NULL);
324 int rv = DoLoop(OK);
325 if (rv == ERR_IO_PENDING)
326 user_callback_ = callback;
327
328 return rv;
[email protected]96d570e42008-08-05 22:43:04329}
330
[email protected]f9ee6b52008-11-08 06:46:23331void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) {
332 DCHECK(HaveAuth(target));
[email protected]a7ea8832010-07-12 17:54:54333 DCHECK(!establishing_tunnel_);
[email protected]2d2697f92009-02-18 21:00:32334 bool keep_alive = false;
[email protected]0877e3d2009-10-17 22:29:57335 // Even if the server says the connection is keep-alive, we have to be
336 // able to find the end of each response in order to reuse the connection.
337 if (GetResponseHeaders()->IsKeepAlive() &&
338 http_stream_->CanFindEndOfResponse()) {
339 // If the response body hasn't been completely read, we need to drain
340 // it first.
341 if (!http_stream_->IsResponseBodyComplete()) {
[email protected]2d2697f92009-02-18 21:00:32342 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
[email protected]0877e3d2009-10-17 22:29:57343 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket.
[email protected]2d2697f92009-02-18 21:00:32344 read_buf_len_ = kDrainBodyBufferSize;
345 return;
346 }
[email protected]0877e3d2009-10-17 22:29:57347 keep_alive = true;
[email protected]37832c6d2009-06-05 19:44:09348 }
349
[email protected]2d2697f92009-02-18 21:00:32350 // We don't need to drain the response body, so we act as if we had drained
351 // the response body.
352 DidDrainBodyForAuthRestart(keep_alive);
353}
354
355void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
[email protected]a7ea8832010-07-12 17:54:54356 DCHECK(!establishing_tunnel_);
[email protected]1f14a912009-12-21 20:32:44357 if (keep_alive && connection_->socket()->IsConnectedAndIdle()) {
358 // We should call connection_->set_idle_time(), but this doesn't occur
[email protected]11203f012009-11-12 23:02:31359 // often enough to be worth the trouble.
[email protected]a7ea8832010-07-12 17:54:54360 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
[email protected]1f14a912009-12-21 20:32:44361 connection_->set_is_reused(true);
[email protected]2d2697f92009-02-18 21:00:32362 reused_socket_ = true;
363 } else {
364 next_state_ = STATE_INIT_CONNECTION;
[email protected]1f14a912009-12-21 20:32:44365 connection_->socket()->Disconnect();
366 connection_->Reset();
[email protected]2d2697f92009-02-18 21:00:32367 }
[email protected]f9ee6b52008-11-08 06:46:23368
369 // Reset the other member variables.
370 ResetStateForRestart();
371}
372
[email protected]9dea9e1f2009-01-29 00:30:47373int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
[email protected]96d570e42008-08-05 22:43:04374 CompletionCallback* callback) {
[email protected]96d570e42008-08-05 22:43:04375 DCHECK(buf);
[email protected]e0c27be2009-07-15 13:09:35376 DCHECK_LT(0, buf_len);
[email protected]96d570e42008-08-05 22:43:04377
[email protected]1f14a912009-12-21 20:32:44378 State next_state = STATE_NONE;
[email protected]96d570e42008-08-05 22:43:04379
[email protected]1f14a912009-12-21 20:32:44380 // Are we using SPDY or HTTP?
[email protected]e0993912010-02-22 23:57:11381 if (using_spdy_) {
[email protected]1f14a912009-12-21 20:32:44382 DCHECK(!http_stream_.get());
[email protected]9be804c82010-06-24 17:59:46383 DCHECK(spdy_http_stream_->GetResponseInfo()->headers);
[email protected]1f14a912009-12-21 20:32:44384 next_state = STATE_SPDY_READ_BODY;
385 } else {
[email protected]9be804c82010-06-24 17:59:46386 DCHECK(!spdy_http_stream_.get());
[email protected]1f14a912009-12-21 20:32:44387 next_state = STATE_READ_BODY;
388
389 if (!connection_->is_initialized())
390 return 0; // connection_->has been reset. Treat like EOF.
[email protected]8a1f3312010-05-25 19:25:04391 }
[email protected]1f14a912009-12-21 20:32:44392
[email protected]8a1f3312010-05-25 19:25:04393 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
394 DCHECK(headers.get());
[email protected]a7ea8832010-07-12 17:54:54395 if (establishing_tunnel_) {
[email protected]8a1f3312010-05-25 19:25:04396 // We're trying to read the body of the response but we're still trying
397 // to establish an SSL tunnel through the proxy. We can't read these
398 // bytes when establishing a tunnel because they might be controlled by
399 // an active network attacker. We don't worry about this for HTTP
400 // because an active network attacker can already control HTTP sessions.
401 // We reach this case when the user cancels a 407 proxy auth prompt.
402 // See http://crbug.com/8473.
403 DCHECK(proxy_info_.is_http());
[email protected]a7ea8832010-07-12 17:54:54404 DCHECK_EQ(headers->response_code(), 407);
405 LOG(WARNING) << "Blocked proxy response with status "
406 << headers->response_code() << " to CONNECT request for "
407 << GetHostAndPort(request_->url) << ".";
[email protected]8a1f3312010-05-25 19:25:04408 return ERR_TUNNEL_CONNECTION_FAILED;
[email protected]a8e9b162009-03-12 00:06:44409 }
410
[email protected]96d570e42008-08-05 22:43:04411 read_buf_ = buf;
412 read_buf_len_ = buf_len;
413
[email protected]1f14a912009-12-21 20:32:44414 next_state_ = next_state;
[email protected]96d570e42008-08-05 22:43:04415 int rv = DoLoop(OK);
416 if (rv == ERR_IO_PENDING)
417 user_callback_ = callback;
418 return rv;
419}
420
421const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const {
[email protected]a7e41312009-12-16 23:18:14422 return ((headers_valid_ && response_.headers) || response_.ssl_info.cert ||
423 response_.cert_request_info) ? &response_ : NULL;
[email protected]96d570e42008-08-05 22:43:04424}
425
426LoadState HttpNetworkTransaction::GetLoadState() const {
427 // TODO(wtc): Define a new LoadState value for the
428 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request.
429 switch (next_state_) {
430 case STATE_RESOLVE_PROXY_COMPLETE:
431 return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
[email protected]d207a5f2009-06-04 05:28:40432 case STATE_INIT_CONNECTION_COMPLETE:
[email protected]1f14a912009-12-21 20:32:44433 return connection_->GetLoadState();
[email protected]375e3112010-05-27 20:32:06434 case STATE_SSL_CONNECT_COMPLETE:
435 return LOAD_STATE_SSL_HANDSHAKE;
[email protected]044de0642010-06-17 10:42:15436 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
437 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
[email protected]0877e3d2009-10-17 22:29:57438 case STATE_SEND_REQUEST_COMPLETE:
[email protected]375e3112010-05-27 20:32:06439 case STATE_SPDY_SEND_REQUEST_COMPLETE:
[email protected]96d570e42008-08-05 22:43:04440 return LOAD_STATE_SENDING_REQUEST;
441 case STATE_READ_HEADERS_COMPLETE:
[email protected]375e3112010-05-27 20:32:06442 case STATE_SPDY_READ_HEADERS_COMPLETE:
[email protected]96d570e42008-08-05 22:43:04443 return LOAD_STATE_WAITING_FOR_RESPONSE;
444 case STATE_READ_BODY_COMPLETE:
[email protected]375e3112010-05-27 20:32:06445 case STATE_SPDY_READ_BODY_COMPLETE:
[email protected]96d570e42008-08-05 22:43:04446 return LOAD_STATE_READING_RESPONSE;
447 default:
448 return LOAD_STATE_IDLE;
449 }
450}
451
452uint64 HttpNetworkTransaction::GetUploadProgress() const {
[email protected]0877e3d2009-10-17 22:29:57453 if (!http_stream_.get())
[email protected]96d570e42008-08-05 22:43:04454 return 0;
455
[email protected]0877e3d2009-10-17 22:29:57456 return http_stream_->GetUploadProgress();
[email protected]96d570e42008-08-05 22:43:04457}
458
initial.commit586acc5fe2008-07-26 22:42:52459HttpNetworkTransaction::~HttpNetworkTransaction() {
[email protected]92d9cad2009-06-25 23:40:24460 // If we still have an open socket, then make sure to disconnect it so it
[email protected]fc31d6a42010-06-24 18:05:13461 // won't call us back and we don't try to reuse it later on. However,
462 // don't close the socket if we should keep the connection alive.
463 if (connection_.get() && connection_->is_initialized()) {
464 // The STATE_NONE check guarantees there are no pending socket IOs that
465 // could try to call this object back after it is deleted.
466 bool keep_alive = next_state_ == STATE_NONE &&
467 http_stream_.get() &&
468 http_stream_->IsResponseBodyComplete() &&
469 http_stream_->CanFindEndOfResponse() &&
470 GetResponseHeaders()->IsKeepAlive();
471 if (!keep_alive)
472 connection_->socket()->Disconnect();
473 }
initial.commit586acc5fe2008-07-26 22:42:52474
475 if (pac_request_)
476 session_->proxy_service()->CancelPacRequest(pac_request_);
[email protected]1f14a912009-12-21 20:32:44477
[email protected]9be804c82010-06-24 17:59:46478 if (spdy_http_stream_.get())
479 spdy_http_stream_->Cancel();
initial.commit586acc5fe2008-07-26 22:42:52480}
481
initial.commit586acc5fe2008-07-26 22:42:52482void HttpNetworkTransaction::DoCallback(int rv) {
483 DCHECK(rv != ERR_IO_PENDING);
484 DCHECK(user_callback_);
485
[email protected]96d570e42008-08-05 22:43:04486 // Since Run may result in Read being called, clear user_callback_ up front.
initial.commit586acc5fe2008-07-26 22:42:52487 CompletionCallback* c = user_callback_;
488 user_callback_ = NULL;
489 c->Run(rv);
490}
491
492void HttpNetworkTransaction::OnIOComplete(int result) {
493 int rv = DoLoop(result);
494 if (rv != ERR_IO_PENDING)
495 DoCallback(rv);
496}
497
498int HttpNetworkTransaction::DoLoop(int result) {
499 DCHECK(next_state_ != STATE_NONE);
500
501 int rv = result;
502 do {
503 State state = next_state_;
504 next_state_ = STATE_NONE;
505 switch (state) {
506 case STATE_RESOLVE_PROXY:
[email protected]725355a2009-03-25 20:42:55507 DCHECK_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52508 rv = DoResolveProxy();
509 break;
510 case STATE_RESOLVE_PROXY_COMPLETE:
511 rv = DoResolveProxyComplete(rv);
512 break;
513 case STATE_INIT_CONNECTION:
[email protected]725355a2009-03-25 20:42:55514 DCHECK_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52515 rv = DoInitConnection();
516 break;
517 case STATE_INIT_CONNECTION_COMPLETE:
518 rv = DoInitConnectionComplete(rv);
519 break;
[email protected]a7ea8832010-07-12 17:54:54520 case STATE_TUNNEL_RESTART_WITH_AUTH:
[email protected]8a1f3312010-05-25 19:25:04521 DCHECK_EQ(OK, rv);
[email protected]a7ea8832010-07-12 17:54:54522 rv = DoTunnelRestartWithAuth();
[email protected]8a1f3312010-05-25 19:25:04523 break;
[email protected]bacff652009-03-31 17:50:33524 case STATE_SSL_CONNECT:
[email protected]725355a2009-03-25 20:42:55525 DCHECK_EQ(OK, rv);
[email protected]bacff652009-03-31 17:50:33526 rv = DoSSLConnect();
[email protected]c7af8b22008-08-25 20:41:46527 break;
[email protected]bacff652009-03-31 17:50:33528 case STATE_SSL_CONNECT_COMPLETE:
529 rv = DoSSLConnectComplete(rv);
[email protected]c7af8b22008-08-25 20:41:46530 break;
[email protected]044de0642010-06-17 10:42:15531 case STATE_GENERATE_PROXY_AUTH_TOKEN:
532 DCHECK_EQ(OK, rv);
533 rv = DoGenerateProxyAuthToken();
534 break;
535 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
536 rv = DoGenerateProxyAuthTokenComplete(rv);
537 break;
538 case STATE_GENERATE_SERVER_AUTH_TOKEN:
539 DCHECK_EQ(OK, rv);
540 rv = DoGenerateServerAuthToken();
541 break;
542 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
543 rv = DoGenerateServerAuthTokenComplete(rv);
544 break;
[email protected]0877e3d2009-10-17 22:29:57545 case STATE_SEND_REQUEST:
[email protected]725355a2009-03-25 20:42:55546 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09547 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, NULL);
[email protected]0877e3d2009-10-17 22:29:57548 rv = DoSendRequest();
initial.commit586acc5fe2008-07-26 22:42:52549 break;
[email protected]0877e3d2009-10-17 22:29:57550 case STATE_SEND_REQUEST_COMPLETE:
551 rv = DoSendRequestComplete(rv);
[email protected]ec11be62010-04-28 19:28:09552 net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, NULL);
initial.commit586acc5fe2008-07-26 22:42:52553 break;
554 case STATE_READ_HEADERS:
[email protected]725355a2009-03-25 20:42:55555 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09556 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, NULL);
initial.commit586acc5fe2008-07-26 22:42:52557 rv = DoReadHeaders();
558 break;
559 case STATE_READ_HEADERS_COMPLETE:
560 rv = DoReadHeadersComplete(rv);
[email protected]ec11be62010-04-28 19:28:09561 net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, NULL);
initial.commit586acc5fe2008-07-26 22:42:52562 break;
563 case STATE_READ_BODY:
[email protected]725355a2009-03-25 20:42:55564 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09565 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, NULL);
initial.commit586acc5fe2008-07-26 22:42:52566 rv = DoReadBody();
567 break;
568 case STATE_READ_BODY_COMPLETE:
569 rv = DoReadBodyComplete(rv);
[email protected]ec11be62010-04-28 19:28:09570 net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, NULL);
initial.commit586acc5fe2008-07-26 22:42:52571 break;
[email protected]2d2697f92009-02-18 21:00:32572 case STATE_DRAIN_BODY_FOR_AUTH_RESTART:
[email protected]725355a2009-03-25 20:42:55573 DCHECK_EQ(OK, rv);
[email protected]9e743cd2010-03-16 07:03:53574 net_log_.BeginEvent(
[email protected]ec11be62010-04-28 19:28:09575 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, NULL);
[email protected]2d2697f92009-02-18 21:00:32576 rv = DoDrainBodyForAuthRestart();
577 break;
578 case STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE:
579 rv = DoDrainBodyForAuthRestartComplete(rv);
[email protected]9e743cd2010-03-16 07:03:53580 net_log_.EndEvent(
[email protected]ec11be62010-04-28 19:28:09581 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, NULL);
[email protected]2d2697f92009-02-18 21:00:32582 break;
[email protected]1f14a912009-12-21 20:32:44583 case STATE_SPDY_SEND_REQUEST:
584 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09585 net_log_.BeginEvent(NetLog::TYPE_SPDY_TRANSACTION_SEND_REQUEST, NULL);
[email protected]1f14a912009-12-21 20:32:44586 rv = DoSpdySendRequest();
587 break;
588 case STATE_SPDY_SEND_REQUEST_COMPLETE:
589 rv = DoSpdySendRequestComplete(rv);
[email protected]ec11be62010-04-28 19:28:09590 net_log_.EndEvent(NetLog::TYPE_SPDY_TRANSACTION_SEND_REQUEST, NULL);
[email protected]1f14a912009-12-21 20:32:44591 break;
592 case STATE_SPDY_READ_HEADERS:
593 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09594 net_log_.BeginEvent(NetLog::TYPE_SPDY_TRANSACTION_READ_HEADERS, NULL);
[email protected]1f14a912009-12-21 20:32:44595 rv = DoSpdyReadHeaders();
596 break;
597 case STATE_SPDY_READ_HEADERS_COMPLETE:
598 rv = DoSpdyReadHeadersComplete(rv);
[email protected]ec11be62010-04-28 19:28:09599 net_log_.EndEvent(NetLog::TYPE_SPDY_TRANSACTION_READ_HEADERS, NULL);
[email protected]1f14a912009-12-21 20:32:44600 break;
601 case STATE_SPDY_READ_BODY:
602 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09603 net_log_.BeginEvent(NetLog::TYPE_SPDY_TRANSACTION_READ_BODY, NULL);
[email protected]1f14a912009-12-21 20:32:44604 rv = DoSpdyReadBody();
605 break;
606 case STATE_SPDY_READ_BODY_COMPLETE:
607 rv = DoSpdyReadBodyComplete(rv);
[email protected]ec11be62010-04-28 19:28:09608 net_log_.EndEvent(NetLog::TYPE_SPDY_TRANSACTION_READ_BODY, NULL);
[email protected]1f14a912009-12-21 20:32:44609 break;
initial.commit586acc5fe2008-07-26 22:42:52610 default:
611 NOTREACHED() << "bad state";
612 rv = ERR_FAILED;
[email protected]96d570e42008-08-05 22:43:04613 break;
initial.commit586acc5fe2008-07-26 22:42:52614 }
615 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
616
617 return rv;
618}
619
620int HttpNetworkTransaction::DoResolveProxy() {
621 DCHECK(!pac_request_);
622
623 next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
624
[email protected]631f1322010-04-30 17:59:11625 // |endpoint_| indicates the final destination endpoint.
626 endpoint_ = HostPortPair(request_->url.HostNoBrackets(),
627 request_->url.EffectiveIntPort());
628
[email protected]28ed3b42010-05-13 19:39:56629 // Extra URL we might be attempting to resolve to.
630 GURL alternate_endpoint_url;
[email protected]b6a50182010-05-12 22:47:14631
[email protected]28ed3b42010-05-13 19:39:56632 // Tracks whether we are using |request_->url| or |alternate_endpoint_url|.
633 const GURL *curr_endpoint_url = &request_->url;
634
635 if (g_host_mapping_rules && g_host_mapping_rules->RewriteHost(&endpoint_)) {
636 url_canon::Replacements<char> replacements;
637 const std::string port_str = IntToString(endpoint_.port);
638 replacements.SetPort(port_str.c_str(),
639 url_parse::Component(0, port_str.size()));
640 replacements.SetHost(endpoint_.host.c_str(),
641 url_parse::Component(0, endpoint_.host.size()));
642 alternate_endpoint_url = curr_endpoint_url->ReplaceComponents(replacements);
643 curr_endpoint_url = &alternate_endpoint_url;
644 }
[email protected]631f1322010-04-30 17:59:11645
[email protected]193b0b892010-06-26 03:57:57646 const HttpAlternateProtocols& alternate_protocols =
647 session_->alternate_protocols();
648 if (alternate_protocols.HasAlternateProtocolFor(endpoint_)) {
649 response_.was_alternate_protocol_available = true;
650 if (alternate_protocol_mode_ == kUnspecified) {
[email protected]631f1322010-04-30 17:59:11651 HttpAlternateProtocols::PortProtocolPair alternate =
652 alternate_protocols.GetAlternateProtocolFor(endpoint_);
653 if (alternate.protocol != HttpAlternateProtocols::BROKEN) {
654 DCHECK_EQ(HttpAlternateProtocols::NPN_SPDY_1, alternate.protocol);
655 endpoint_.port = alternate.port;
656 alternate_protocol_ = HttpAlternateProtocols::NPN_SPDY_1;
657 alternate_protocol_mode_ = kUsingAlternateProtocol;
658
659 url_canon::Replacements<char> replacements;
660 replacements.SetScheme("https",
661 url_parse::Component(0, strlen("https")));
662 const std::string port_str = IntToString(endpoint_.port);
663 replacements.SetPort(port_str.c_str(),
664 url_parse::Component(0, port_str.size()));
[email protected]28ed3b42010-05-13 19:39:56665 alternate_endpoint_url =
666 curr_endpoint_url->ReplaceComponents(replacements);
667 curr_endpoint_url = &alternate_endpoint_url;
[email protected]631f1322010-04-30 17:59:11668 }
669 }
670 }
671
[email protected]677c90572008-12-10 09:03:15672 if (request_->load_flags & LOAD_BYPASS_PROXY) {
673 proxy_info_.UseDirect();
674 return OK;
675 }
676
initial.commit586acc5fe2008-07-26 22:42:52677 return session_->proxy_service()->ResolveProxy(
[email protected]28ed3b42010-05-13 19:39:56678 *curr_endpoint_url, &proxy_info_, &io_callback_, &pac_request_, net_log_);
initial.commit586acc5fe2008-07-26 22:42:52679}
680
681int HttpNetworkTransaction::DoResolveProxyComplete(int result) {
[email protected]69719062010-01-05 20:09:21682 pac_request_ = NULL;
initial.commit586acc5fe2008-07-26 22:42:52683
[email protected]dded3e22010-02-05 04:08:37684 if (result != OK)
685 return result;
[email protected]59a16012010-01-29 23:45:29686
[email protected]e0c27be2009-07-15 13:09:35687 // Remove unsupported proxies from the list.
[email protected]f6fb2de2009-02-19 08:11:42688 proxy_info_.RemoveProxiesWithoutScheme(
[email protected]3cd17242009-06-23 02:59:02689 ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_HTTP |
[email protected]e0c27be2009-07-15 13:09:35690 ProxyServer::SCHEME_SOCKS4 | ProxyServer::SCHEME_SOCKS5);
[email protected]f6fb2de2009-02-19 08:11:42691
[email protected]69719062010-01-05 20:09:21692 if (proxy_info_.is_empty()) {
[email protected]02cf5a42010-01-12 22:10:25693 // No proxies/direct to choose from. This happens when we don't support any
694 // of the proxies in the returned list.
695 return ERR_NO_SUPPORTED_PROXIES;
[email protected]69719062010-01-05 20:09:21696 }
initial.commit586acc5fe2008-07-26 22:42:52697
[email protected]69719062010-01-05 20:09:21698 next_state_ = STATE_INIT_CONNECTION;
initial.commit586acc5fe2008-07-26 22:42:52699 return OK;
700}
701
702int HttpNetworkTransaction::DoInitConnection() {
[email protected]1f14a912009-12-21 20:32:44703 DCHECK(!connection_->is_initialized());
[email protected]69719062010-01-05 20:09:21704 DCHECK(proxy_info_.proxy_server().is_valid());
initial.commit586acc5fe2008-07-26 22:42:52705
[email protected]228404f2010-06-24 04:31:41706 // Now that the proxy server has been resolved, create the auth_controllers_.
707 for (int i = 0; i < HttpAuth::AUTH_NUM_TARGETS; i++) {
708 HttpAuth::Target target = static_cast<HttpAuth::Target>(i);
709 if (!auth_controllers_[target].get())
[email protected]e772db3f2010-07-12 18:11:13710 auth_controllers_[target] = new HttpAuthController(target,
711 AuthURL(target),
[email protected]560c0432010-07-13 20:45:31712 session_);
[email protected]228404f2010-06-24 04:31:41713 }
714
initial.commit586acc5fe2008-07-26 22:42:52715 next_state_ = STATE_INIT_CONNECTION_COMPLETE;
716
[email protected]631f1322010-04-30 17:59:11717 using_ssl_ = request_->url.SchemeIs("https") ||
718 (alternate_protocol_mode_ == kUsingAlternateProtocol &&
719 alternate_protocol_ == HttpAlternateProtocols::NPN_SPDY_1);
720
[email protected]e0993912010-02-22 23:57:11721 using_spdy_ = false;
[email protected]04e5be32009-06-26 20:00:31722
initial.commit586acc5fe2008-07-26 22:42:52723 // Build the string used to uniquely identify connections of this type.
[email protected]d207a5f2009-06-04 05:28:40724 // Determine the host and port to connect to.
initial.commit586acc5fe2008-07-26 22:42:52725 std::string connection_group;
[email protected]2ff8b312010-04-26 22:20:54726
[email protected]85c0ed82009-12-15 23:14:14727 // Use the fixed testing ports if they've been provided.
728 if (using_ssl_) {
729 if (session_->fixed_https_port() != 0)
[email protected]2d731a32010-04-29 01:04:06730 endpoint_.port = session_->fixed_https_port();
[email protected]85c0ed82009-12-15 23:14:14731 } else if (session_->fixed_http_port() != 0) {
[email protected]2d731a32010-04-29 01:04:06732 endpoint_.port = session_->fixed_http_port();
[email protected]85c0ed82009-12-15 23:14:14733 }
734
[email protected]0b0c0082010-05-21 02:08:35735 response_.was_fetched_via_proxy = !proxy_info_.is_direct();
736
[email protected]7fc5b09a2010-02-27 00:07:38737 // Check first if we have a spdy session for this group. If so, then go
738 // straight to using that.
[email protected]2d731a32010-04-29 01:04:06739 if (session_->spdy_session_pool()->HasSession(endpoint_)) {
[email protected]7fc5b09a2010-02-27 00:07:38740 using_spdy_ = true;
[email protected]8e3d2d32010-06-13 18:46:23741 reused_socket_ = true;
[email protected]7fc5b09a2010-02-27 00:07:38742 return OK;
743 }
744
[email protected]2d731a32010-04-29 01:04:06745 connection_group = endpoint_.ToString();
[email protected]a0ef3762009-12-22 02:09:45746 DCHECK(!connection_group.empty());
[email protected]2884a462009-06-15 05:08:42747
[email protected]0e88ad602010-05-04 23:47:02748 if (using_ssl_)
749 connection_group = StringPrintf("ssl/%s", connection_group.c_str());
750
[email protected]2884a462009-06-15 05:08:42751 // If the user is refreshing the page, bypass the host cache.
[email protected]7fc5b09a2010-02-27 00:07:38752 bool disable_resolver_cache = request_->load_flags & LOAD_BYPASS_CACHE ||
[email protected]685af592010-05-11 19:31:24753 request_->load_flags & LOAD_VALIDATE_CACHE ||
[email protected]2227c692010-05-04 15:36:11754 request_->load_flags & LOAD_DISABLE_CACHE;
[email protected]2884a462009-06-15 05:08:42755
[email protected]a796bcec2010-03-22 17:17:26756 int rv;
[email protected]2d731a32010-04-29 01:04:06757 if (!proxy_info_.is_direct()) {
758 ProxyServer proxy_server = proxy_info_.proxy_server();
759 HostPortPair proxy_host_port_pair(proxy_server.HostNoBrackets(),
760 proxy_server.port());
761
[email protected]df4b4ef2010-07-12 18:25:21762 scoped_refptr<TCPSocketParams> tcp_params =
763 new TCPSocketParams(proxy_host_port_pair, request_->priority,
764 request_->referrer, disable_resolver_cache);
[email protected]2d731a32010-04-29 01:04:06765
766 if (proxy_info_.is_socks()) {
767 const char* socks_version;
768 bool socks_v5;
769 if (proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_SOCKS5) {
770 socks_version = "5";
771 socks_v5 = true;
772 } else {
773 socks_version = "4";
774 socks_v5 = false;
775 }
776
777 connection_group =
778 StringPrintf("socks%s/%s", socks_version, connection_group.c_str());
779
[email protected]df4b4ef2010-07-12 18:25:21780 scoped_refptr<SOCKSSocketParams> socks_params =
781 new SOCKSSocketParams(tcp_params, socks_v5, endpoint_,
782 request_->priority, request_->referrer);
[email protected]2d731a32010-04-29 01:04:06783
784 rv = connection_->Init(
785 connection_group, socks_params, request_->priority,
786 &io_callback_,
787 session_->GetSocketPoolForSOCKSProxy(proxy_host_port_pair), net_log_);
788 } else {
[email protected]e772db3f2010-07-12 18:11:13789 DCHECK(proxy_info_.is_http());
790 scoped_refptr<HttpAuthController> http_proxy_auth;
791 if (using_ssl_) {
792 http_proxy_auth = auth_controllers_[HttpAuth::AUTH_PROXY];
793 establishing_tunnel_ = true;
794 }
795
[email protected]df4b4ef2010-07-12 18:25:21796 scoped_refptr<HttpProxySocketParams> http_proxy_params =
797 new HttpProxySocketParams(tcp_params, request_->url, endpoint_,
798 http_proxy_auth, using_ssl_);
[email protected]e772db3f2010-07-12 18:11:13799
800 rv = connection_->Init(connection_group, http_proxy_params,
801 request_->priority, &io_callback_,
802 session_->GetSocketPoolForHTTPProxy(
803 proxy_host_port_pair),
804 net_log_);
[email protected]2d731a32010-04-29 01:04:06805 }
806 } else {
[email protected]df4b4ef2010-07-12 18:25:21807 scoped_refptr<TCPSocketParams> tcp_params =
808 new TCPSocketParams(endpoint_, request_->priority, request_->referrer,
809 disable_resolver_cache);
[email protected]a796bcec2010-03-22 17:17:26810 rv = connection_->Init(connection_group, tcp_params, request_->priority,
811 &io_callback_, session_->tcp_socket_pool(),
812 net_log_);
[email protected]a796bcec2010-03-22 17:17:26813 }
814
[email protected]d207a5f2009-06-04 05:28:40815 return rv;
initial.commit586acc5fe2008-07-26 22:42:52816}
817
818int HttpNetworkTransaction::DoInitConnectionComplete(int result) {
[email protected]564b4912010-03-09 16:30:42819 if (result < 0) {
[email protected]e772db3f2010-07-12 18:11:13820 if (result == ERR_RETRY_CONNECTION) {
821 DCHECK(establishing_tunnel_);
822 next_state_ = STATE_INIT_CONNECTION;
823 connection_->socket()->Disconnect();
824 connection_->Reset();
825 return OK;
826 }
827
828 if (result == ERR_PROXY_AUTH_REQUESTED) {
829 DCHECK(establishing_tunnel_);
830 HttpProxyClientSocket* tunnel_socket =
831 static_cast<HttpProxyClientSocket*>(connection_->socket());
832 DCHECK(tunnel_socket);
833 DCHECK(!tunnel_socket->IsConnected());
834 const HttpResponseInfo* auth_response = tunnel_socket->GetResponseInfo();
835
836 response_.headers = auth_response->headers;
837 headers_valid_ = true;
838 response_.auth_challenge = auth_response->auth_challenge;
839 pending_auth_target_ = HttpAuth::AUTH_PROXY;
840 return OK;
841 }
842
[email protected]564b4912010-03-09 16:30:42843 if (alternate_protocol_mode_ == kUsingAlternateProtocol) {
844 // Mark the alternate protocol as broken and fallback.
[email protected]a2cb8122010-03-10 17:22:42845 MarkBrokenAlternateProtocolAndFallback();
[email protected]564b4912010-03-09 16:30:42846 return OK;
847 }
848
[email protected]d207a5f2009-06-04 05:28:40849 return ReconsiderProxyAfterError(result);
[email protected]564b4912010-03-09 16:30:42850 }
initial.commit586acc5fe2008-07-26 22:42:52851
[email protected]1f14a912009-12-21 20:32:44852 DCHECK_EQ(OK, result);
[email protected]e772db3f2010-07-12 18:11:13853 if (establishing_tunnel_) {
854 DCHECK(connection_->socket()->IsConnected());
855 establishing_tunnel_ = false;
856 }
initial.commit586acc5fe2008-07-26 22:42:52857
[email protected]e0993912010-02-22 23:57:11858 if (using_spdy_) {
859 DCHECK(!connection_->is_initialized());
[email protected]044de0642010-06-17 10:42:15860 // TODO(cbentzel): Add auth support to spdy. See http://crbug.com/46620
[email protected]1f14a912009-12-21 20:32:44861 next_state_ = STATE_SPDY_SEND_REQUEST;
862 return OK;
863 }
864
[email protected]a796bcec2010-03-22 17:17:26865 LogHttpConnectedMetrics(*connection_);
[email protected]f9d285c2009-08-17 19:54:29866
initial.commit586acc5fe2008-07-26 22:42:52867 // Set the reused_socket_ flag to indicate that we are using a keep-alive
868 // connection. This flag is used to handle errors that occur while we are
869 // trying to reuse a keep-alive connection.
[email protected]1f14a912009-12-21 20:32:44870 reused_socket_ = connection_->is_reused();
[email protected]049d4ee2008-10-23 21:42:07871 if (reused_socket_) {
[email protected]65041fa2010-05-21 06:56:53872 if (using_ssl_) {
873 SSLClientSocket* ssl_socket =
874 reinterpret_cast<SSLClientSocket*>(connection_->socket());
875 response_.was_npn_negotiated = ssl_socket->wasNpnNegotiated();
876 }
[email protected]044de0642010-06-17 10:42:15877 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
initial.commit586acc5fe2008-07-26 22:42:52878 } else {
[email protected]d207a5f2009-06-04 05:28:40879 // Now we have a TCP connected socket. Perform other connection setup as
880 // needed.
[email protected]616925a2010-03-02 19:02:38881 UpdateConnectionTypeHistograms(CONNECTION_HTTP);
[email protected]e772db3f2010-07-12 18:11:13882 if (using_ssl_)
883 next_state_ = STATE_SSL_CONNECT;
884 else
[email protected]044de0642010-06-17 10:42:15885 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
[email protected]c7af8b22008-08-25 20:41:46886 }
[email protected]1f14a912009-12-21 20:32:44887
[email protected]d207a5f2009-06-04 05:28:40888 return OK;
[email protected]c7af8b22008-08-25 20:41:46889}
890
[email protected]a7ea8832010-07-12 17:54:54891int HttpNetworkTransaction::DoTunnelRestartWithAuth() {
[email protected]e772db3f2010-07-12 18:11:13892 next_state_ = STATE_INIT_CONNECTION_COMPLETE;
[email protected]a7ea8832010-07-12 17:54:54893 HttpProxyClientSocket* tunnel_socket =
894 reinterpret_cast<HttpProxyClientSocket*>(connection_->socket());
[email protected]8a1f3312010-05-25 19:25:04895
[email protected]e772db3f2010-07-12 18:11:13896 return tunnel_socket->RestartWithAuth(&io_callback_);
[email protected]8a1f3312010-05-25 19:25:04897}
898
[email protected]bacff652009-03-31 17:50:33899int HttpNetworkTransaction::DoSSLConnect() {
900 next_state_ = STATE_SSL_CONNECT_COMPLETE;
[email protected]c7af8b22008-08-25 20:41:46901
[email protected]aeaca1f2010-04-20 22:05:21902 if (ContainsKey(*g_tls_intolerant_servers, GetHostAndPort(request_->url))) {
903 LOG(WARNING) << "Falling back to SSLv3 because host is TLS intolerant: "
904 << GetHostAndPort(request_->url);
[email protected]fc7de492010-07-12 14:49:04905 ssl_config_.ssl3_fallback = true;
[email protected]aeaca1f2010-04-20 22:05:21906 ssl_config_.tls1_enabled = false;
907 }
908
[email protected]fc7de492010-07-12 14:49:04909 UMA_HISTOGRAM_ENUMERATION("Net.ConnectionUsedSSLv3Fallback",
910 (int) ssl_config_.ssl3_fallback, 2);
911
[email protected]f6555ad2009-06-23 06:35:05912 if (request_->load_flags & LOAD_VERIFY_EV_CERT)
913 ssl_config_.verify_ev_cert = true;
914
[email protected]b7b76782009-09-11 00:31:43915 ssl_connect_start_time_ = base::TimeTicks::Now();
916
[email protected]86ec30d2008-09-29 21:53:54917 // Add a SSL socket on top of our existing transport socket.
[email protected]1f14a912009-12-21 20:32:44918 ClientSocket* s = connection_->release_socket();
[email protected]5695b8c2009-09-30 21:36:43919 s = session_->socket_factory()->CreateSSLClientSocket(
[email protected]facc8262009-05-16 00:01:00920 s, request_->url.HostNoBrackets(), ssl_config_);
[email protected]1f14a912009-12-21 20:32:44921 connection_->set_socket(s);
[email protected]a2006ece2010-04-23 16:44:02922 return connection_->socket()->Connect(&io_callback_);
[email protected]c7af8b22008-08-25 20:41:46923}
924
[email protected]bacff652009-03-31 17:50:33925int HttpNetworkTransaction::DoSSLConnectComplete(int result) {
[email protected]37a67922010-03-05 00:16:02926 SSLClientSocket* ssl_socket =
927 reinterpret_cast<SSLClientSocket*>(connection_->socket());
928
929 SSLClientSocket::NextProtoStatus status =
930 SSLClientSocket::kNextProtoUnsupported;
931 std::string proto;
932 // GetNextProto will fail and and trigger a NOTREACHED if we pass in a socket
933 // that hasn't had SSL_ImportFD called on it. If we get a certificate error
934 // here, then we know that we called SSL_ImportFD.
935 if (result == OK || IsCertificateError(result))
936 status = ssl_socket->GetNextProto(&proto);
[email protected]65041fa2010-05-21 06:56:53937
938 if (status == SSLClientSocket::kNextProtoNegotiated) {
939 ssl_socket->setWasNpnNegotiated(true);
940 response_.was_npn_negotiated = true;
941 if (SSLClientSocket::NextProtoFromString(proto) ==
942 SSLClientSocket::kProtoSPDY1) {
943 using_spdy_ = true;
944 }
945 }
[email protected]37a67922010-03-05 00:16:02946
[email protected]a2cb8122010-03-10 17:22:42947 if (alternate_protocol_mode_ == kUsingAlternateProtocol &&
[email protected]31e2c69e2010-04-15 18:06:06948 alternate_protocol_ == HttpAlternateProtocols::NPN_SPDY_1 &&
[email protected]a2cb8122010-03-10 17:22:42949 !using_spdy_) {
[email protected]31e2c69e2010-04-15 18:06:06950 // We tried using the NPN_SPDY_1 alternate protocol, but failed, so we
[email protected]a2cb8122010-03-10 17:22:42951 // fallback.
952 MarkBrokenAlternateProtocolAndFallback();
953 return OK;
954 }
955
[email protected]1f14a912009-12-21 20:32:44956 if (IsCertificateError(result)) {
[email protected]bdbda462010-06-28 17:30:37957 if (using_spdy_ && request_->url.SchemeIs("http")) {
958 // We ignore certificate errors for http over spdy.
959 spdy_certificate_error_ = result;
960 result = OK;
961 } else {
962 result = HandleCertificateError(result);
963 if (result == OK && !connection_->socket()->IsConnectedAndIdle()) {
964 connection_->socket()->Disconnect();
965 connection_->Reset();
966 next_state_ = STATE_INIT_CONNECTION;
967 return result;
968 }
[email protected]1f14a912009-12-21 20:32:44969 }
970 }
[email protected]771d0c2b2008-09-30 00:26:17971
[email protected]c5949a32008-10-08 17:28:23972 if (result == OK) {
[email protected]b7b76782009-09-11 00:31:43973 DCHECK(ssl_connect_start_time_ != base::TimeTicks());
974 base::TimeDelta connect_duration =
975 base::TimeTicks::Now() - ssl_connect_start_time_;
976
[email protected]e0993912010-02-22 23:57:11977 if (using_spdy_) {
[email protected]6aad1f602010-01-13 23:17:05978 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SpdyConnectionLatency",
[email protected]2227c692010-05-04 15:36:11979 connect_duration,
980 base::TimeDelta::FromMilliseconds(1),
981 base::TimeDelta::FromMinutes(10),
982 100);
[email protected]6aad1f602010-01-13 23:17:05983
[email protected]616925a2010-03-02 19:02:38984 UpdateConnectionTypeHistograms(CONNECTION_SPDY);
[email protected]044de0642010-06-17 10:42:15985 // TODO(cbentzel): Add auth support to spdy. See http://crbug.com/46620
[email protected]1f14a912009-12-21 20:32:44986 next_state_ = STATE_SPDY_SEND_REQUEST;
987 } else {
[email protected]6aad1f602010-01-13 23:17:05988 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency",
[email protected]2227c692010-05-04 15:36:11989 connect_duration,
990 base::TimeDelta::FromMilliseconds(1),
991 base::TimeDelta::FromMinutes(10),
992 100);
[email protected]6aad1f602010-01-13 23:17:05993
[email protected]044de0642010-06-17 10:42:15994 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
[email protected]1f14a912009-12-21 20:32:44995 }
[email protected]0b45559b2009-06-12 21:45:11996 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
[email protected]5e363962009-06-19 19:57:01997 result = HandleCertificateRequest(result);
[email protected]5a179bcc2008-10-13 18:10:59998 } else {
[email protected]c5949a32008-10-08 17:28:23999 result = HandleSSLHandshakeError(result);
1000 }
initial.commit586acc5fe2008-07-26 22:42:521001 return result;
1002}
1003
[email protected]044de0642010-06-17 10:42:151004int HttpNetworkTransaction::DoGenerateProxyAuthToken() {
1005 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE;
1006 if (!ShouldApplyProxyAuth())
1007 return OK;
[email protected]228404f2010-06-24 04:31:411008 return auth_controllers_[HttpAuth::AUTH_PROXY]->MaybeGenerateAuthToken(
[email protected]560c0432010-07-13 20:45:311009 request_, &io_callback_, net_log_);
[email protected]044de0642010-06-17 10:42:151010}
1011
1012int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) {
1013 DCHECK_NE(ERR_IO_PENDING, rv);
1014 if (rv == OK)
1015 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN;
1016 return rv;
1017}
1018
1019int HttpNetworkTransaction::DoGenerateServerAuthToken() {
1020 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE;
1021 if (!ShouldApplyServerAuth())
1022 return OK;
[email protected]228404f2010-06-24 04:31:411023 return auth_controllers_[HttpAuth::AUTH_SERVER]->MaybeGenerateAuthToken(
[email protected]560c0432010-07-13 20:45:311024 request_, &io_callback_, net_log_);
[email protected]044de0642010-06-17 10:42:151025}
1026
1027int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) {
1028 DCHECK_NE(ERR_IO_PENDING, rv);
1029 if (rv == OK)
1030 next_state_ = STATE_SEND_REQUEST;
1031 return rv;
1032}
1033
[email protected]0877e3d2009-10-17 22:29:571034int HttpNetworkTransaction::DoSendRequest() {
1035 next_state_ = STATE_SEND_REQUEST_COMPLETE;
1036
1037 UploadDataStream* request_body = NULL;
[email protected]8a1f3312010-05-25 19:25:041038 if (request_->upload_data) {
[email protected]7a6db4022010-03-24 23:37:501039 int error_code;
1040 request_body = UploadDataStream::Create(request_->upload_data, &error_code);
1041 if (!request_body)
1042 return error_code;
1043 }
initial.commit586acc5fe2008-07-26 22:42:521044
1045 // This is constructed lazily (instead of within our Start method), so that
1046 // we have proxy info available.
[email protected]0877e3d2009-10-17 22:29:571047 if (request_headers_.empty()) {
[email protected]1c773ea12009-04-28 19:58:421048 // Figure out if we can/should add Proxy-Authentication & Authentication
1049 // headers.
[email protected]270c6412010-03-29 22:02:471050 HttpRequestHeaders authorization_headers;
[email protected]044de0642010-06-17 10:42:151051 bool have_proxy_auth = (ShouldApplyProxyAuth() &&
1052 HaveAuth(HttpAuth::AUTH_PROXY));
1053 bool have_server_auth = (ShouldApplyServerAuth() &&
1054 HaveAuth(HttpAuth::AUTH_SERVER));
[email protected]1c773ea12009-04-28 19:58:421055 if (have_proxy_auth)
[email protected]228404f2010-06-24 04:31:411056 auth_controllers_[HttpAuth::AUTH_PROXY]->AddAuthorizationHeader(
1057 &authorization_headers);
[email protected]1c773ea12009-04-28 19:58:421058 if (have_server_auth)
[email protected]228404f2010-06-24 04:31:411059 auth_controllers_[HttpAuth::AUTH_SERVER]->AddAuthorizationHeader(
1060 &authorization_headers);
[email protected]044de0642010-06-17 10:42:151061 std::string request_line;
1062 HttpRequestHeaders request_headers;
[email protected]8a1f3312010-05-25 19:25:041063 BuildRequestHeaders(request_, authorization_headers, request_body,
1064 !using_ssl_ && proxy_info_.is_http(), &request_line,
1065 &request_headers);
[email protected]ac039522010-06-15 16:39:441066
1067 if (session_->network_delegate())
1068 session_->network_delegate()->OnSendHttpRequest(&request_headers);
1069
[email protected]8a1f3312010-05-25 19:25:041070 if (net_log_.HasListener()) {
1071 net_log_.AddEvent(
1072 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]a7ea8832010-07-12 17:54:541073 new NetLogHttpRequestParameter(request_line, request_headers));
[email protected]6b9833e2008-09-10 20:32:251074 }
[email protected]ac039522010-06-15 16:39:441075
[email protected]8c76ae22010-04-20 22:15:431076 request_headers_ = request_line + request_headers.ToString();
[email protected]6b9833e2008-09-10 20:32:251077 }
initial.commit586acc5fe2008-07-26 22:42:521078
[email protected]1f14a912009-12-21 20:32:441079 headers_valid_ = false;
[email protected]9e743cd2010-03-16 07:03:531080 http_stream_.reset(new HttpBasicStream(connection_.get(), net_log_));
[email protected]1f14a912009-12-21 20:32:441081
[email protected]a7e41312009-12-16 23:18:141082 return http_stream_->SendRequest(request_, request_headers_,
1083 request_body, &response_, &io_callback_);
initial.commit586acc5fe2008-07-26 22:42:521084}
1085
[email protected]0877e3d2009-10-17 22:29:571086int HttpNetworkTransaction::DoSendRequestComplete(int result) {
initial.commit586acc5fe2008-07-26 22:42:521087 if (result < 0)
1088 return HandleIOError(result);
[email protected]0877e3d2009-10-17 22:29:571089 next_state_ = STATE_READ_HEADERS;
initial.commit586acc5fe2008-07-26 22:42:521090 return OK;
1091}
1092
1093int HttpNetworkTransaction::DoReadHeaders() {
1094 next_state_ = STATE_READ_HEADERS_COMPLETE;
[email protected]0877e3d2009-10-17 22:29:571095 return http_stream_->ReadResponseHeaders(&io_callback_);
initial.commit586acc5fe2008-07-26 22:42:521096}
1097
[email protected]0e75a732008-10-16 20:36:091098int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() {
[email protected]a7e41312009-12-16 23:18:141099 if (!response_.headers) {
[email protected]0e75a732008-10-16 20:36:091100 // The connection was closed before any data was sent. Likely an error
1101 // rather than empty HTTP/0.9 response.
[email protected]aecfbf22008-10-16 02:02:471102 return ERR_EMPTY_RESPONSE;
1103 }
1104
[email protected]aecfbf22008-10-16 02:02:471105 return OK;
1106}
1107
initial.commit586acc5fe2008-07-26 22:42:521108int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
[email protected]0b45559b2009-06-12 21:45:111109 // We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here
1110 // due to SSL renegotiation.
1111 if (using_ssl_) {
1112 if (IsCertificateError(result)) {
1113 // We don't handle a certificate error during SSL renegotiation, so we
1114 // have to return an error that's not in the certificate error range
1115 // (-2xx).
1116 LOG(ERROR) << "Got a server certificate with error " << result
1117 << " during SSL renegotiation";
1118 result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION;
1119 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
[email protected]5e363962009-06-19 19:57:011120 result = HandleCertificateRequest(result);
1121 if (result == OK)
1122 return result;
[email protected]0ed94682010-05-18 15:09:001123 } else if ((result == ERR_SSL_DECOMPRESSION_FAILURE_ALERT ||
[email protected]65041fa2010-05-21 06:56:531124 result == ERR_SSL_BAD_RECORD_MAC_ALERT) &&
[email protected]d102f542010-06-30 14:51:051125 ssl_config_.tls1_enabled &&
1126 !SSLConfigService::IsKnownStrictTLSServer(request_->url.host())){
[email protected]aeaca1f2010-04-20 22:05:211127 // Some buggy servers select DEFLATE compression when offered and then
1128 // fail to ever decompress anything. They will send a fatal alert telling
1129 // us this. Normally we would pick this up during the handshake because
1130 // our Finished message is compressed and we'll never get the server's
1131 // Finished if it fails to process ours.
1132 //
1133 // However, with False Start, we'll believe that the handshake is
1134 // complete as soon as we've /sent/ our Finished message. In this case,
1135 // we only find out that the server is buggy here, when we try to read
1136 // the initial reply.
1137 g_tls_intolerant_servers->insert(GetHostAndPort(request_->url));
1138 ResetConnectionAndRequestForResend();
1139 return OK;
[email protected]0b45559b2009-06-12 21:45:111140 }
[email protected]2181ea002009-06-09 01:37:271141 }
1142
[email protected]0877e3d2009-10-17 22:29:571143 if (result < 0 && result != ERR_CONNECTION_CLOSED)
initial.commit586acc5fe2008-07-26 22:42:521144 return HandleIOError(result);
1145
[email protected]0877e3d2009-10-17 22:29:571146 if (result == ERR_CONNECTION_CLOSED && ShouldResendRequest(result)) {
[email protected]1c773ea12009-04-28 19:58:421147 ResetConnectionAndRequestForResend();
[email protected]0877e3d2009-10-17 22:29:571148 return OK;
[email protected]1c773ea12009-04-28 19:58:421149 }
[email protected]2a5c76b2008-09-25 22:15:161150
[email protected]0877e3d2009-10-17 22:29:571151 // After we call RestartWithAuth a new response_time will be recorded, and
1152 // we need to be cautious about incorrectly logging the duration across the
1153 // authentication activity.
[email protected]8e3d2d32010-06-13 18:46:231154 LogTransactionConnectedMetrics();
initial.commit586acc5fe2008-07-26 22:42:521155
[email protected]0877e3d2009-10-17 22:29:571156 if (result == ERR_CONNECTION_CLOSED) {
[email protected]02c92c492010-03-08 21:28:141157 // For now, if we get at least some data, we do the best we can to make
[email protected]9492e4a2010-02-24 00:58:461158 // sense of it and send it back up the stack.
[email protected]0e75a732008-10-16 20:36:091159 int rv = HandleConnectionClosedBeforeEndOfHeaders();
[email protected]aecfbf22008-10-16 02:02:471160 if (rv != OK)
1161 return rv;
[email protected]0877e3d2009-10-17 22:29:571162 }
initial.commit586acc5fe2008-07-26 22:42:521163
[email protected]dbb83db2010-05-11 18:13:391164 if (net_log_.HasListener()) {
[email protected]8a1f3312010-05-25 19:25:041165 net_log_.AddEvent(
1166 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
1167 new NetLogHttpResponseParameter(response_.headers));
[email protected]dbb83db2010-05-11 18:13:391168 }
1169
[email protected]a7e41312009-12-16 23:18:141170 if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
[email protected]0877e3d2009-10-17 22:29:571171 // HTTP/0.9 doesn't support the PUT method, so lack of response headers
1172 // indicates a buggy server. See:
1173 // https://bugzilla.mozilla.org/show_bug.cgi?id=193921
1174 if (request_->method == "PUT")
1175 return ERR_METHOD_NOT_SUPPORTED;
1176 }
[email protected]4ddaf2502008-10-23 18:26:191177
[email protected]0877e3d2009-10-17 22:29:571178 // Check for an intermediate 100 Continue response. An origin server is
1179 // allowed to send this response even if we didn't ask for it, so we just
1180 // need to skip over it.
1181 // We treat any other 1xx in this same way (although in practice getting
1182 // a 1xx that isn't a 100 is rare).
[email protected]a7e41312009-12-16 23:18:141183 if (response_.headers->response_code() / 100 == 1) {
[email protected]ee9410e72010-01-07 01:42:381184 response_.headers = new HttpResponseHeaders("");
[email protected]0877e3d2009-10-17 22:29:571185 next_state_ = STATE_READ_HEADERS;
1186 return OK;
1187 }
1188
[email protected]564b4912010-03-09 16:30:421189 ProcessAlternateProtocol(*response_.headers,
[email protected]b6a50182010-05-12 22:47:141190 endpoint_,
[email protected]564b4912010-03-09 16:30:421191 session_->mutable_alternate_protocols());
1192
[email protected]e772db3f2010-07-12 18:11:131193 int rv = HandleAuthChallenge();
[email protected]0877e3d2009-10-17 22:29:571194 if (rv != OK)
1195 return rv;
1196
[email protected]8a1f3312010-05-25 19:25:041197 if (using_ssl_) {
[email protected]0877e3d2009-10-17 22:29:571198 SSLClientSocket* ssl_socket =
[email protected]1f14a912009-12-21 20:32:441199 reinterpret_cast<SSLClientSocket*>(connection_->socket());
[email protected]a7e41312009-12-16 23:18:141200 ssl_socket->GetSSLInfo(&response_.ssl_info);
[email protected]0877e3d2009-10-17 22:29:571201 }
1202
1203 headers_valid_ = true;
1204 return OK;
initial.commit586acc5fe2008-07-26 22:42:521205}
1206
1207int HttpNetworkTransaction::DoReadBody() {
1208 DCHECK(read_buf_);
[email protected]6501bc02009-06-25 20:55:131209 DCHECK_GT(read_buf_len_, 0);
[email protected]1f14a912009-12-21 20:32:441210 DCHECK(connection_->is_initialized());
initial.commit586acc5fe2008-07-26 22:42:521211
1212 next_state_ = STATE_READ_BODY_COMPLETE;
[email protected]0877e3d2009-10-17 22:29:571213 return http_stream_->ReadResponseBody(read_buf_, read_buf_len_,
1214 &io_callback_);
initial.commit586acc5fe2008-07-26 22:42:521215}
1216
1217int HttpNetworkTransaction::DoReadBodyComplete(int result) {
1218 // We are done with the Read call.
initial.commit586acc5fe2008-07-26 22:42:521219 bool done = false, keep_alive = false;
[email protected]02c92c492010-03-08 21:28:141220 if (result <= 0)
initial.commit586acc5fe2008-07-26 22:42:521221 done = true;
[email protected]9492e4a2010-02-24 00:58:461222
1223 if (http_stream_->IsResponseBodyComplete()) {
[email protected]0877e3d2009-10-17 22:29:571224 done = true;
[email protected]9492e4a2010-02-24 00:58:461225 if (http_stream_->CanFindEndOfResponse())
[email protected]02c92c492010-03-08 21:28:141226 keep_alive = GetResponseHeaders()->IsKeepAlive();
initial.commit586acc5fe2008-07-26 22:42:521227 }
1228
[email protected]1f14a912009-12-21 20:32:441229 // Clean up connection_->if we are done.
initial.commit586acc5fe2008-07-26 22:42:521230 if (done) {
[email protected]56300172008-11-06 18:42:551231 LogTransactionMetrics();
initial.commit586acc5fe2008-07-26 22:42:521232 if (!keep_alive)
[email protected]1f14a912009-12-21 20:32:441233 connection_->socket()->Disconnect();
1234 connection_->Reset();
[email protected]96d570e42008-08-05 22:43:041235 // The next Read call will return 0 (EOF).
initial.commit586acc5fe2008-07-26 22:42:521236 }
1237
1238 // Clear these to avoid leaving around old state.
1239 read_buf_ = NULL;
1240 read_buf_len_ = 0;
1241
1242 return result;
1243}
1244
[email protected]2d2697f92009-02-18 21:00:321245int HttpNetworkTransaction::DoDrainBodyForAuthRestart() {
1246 // This method differs from DoReadBody only in the next_state_. So we just
1247 // call DoReadBody and override the next_state_. Perhaps there is a more
1248 // elegant way for these two methods to share code.
1249 int rv = DoReadBody();
1250 DCHECK(next_state_ == STATE_READ_BODY_COMPLETE);
1251 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE;
1252 return rv;
1253}
1254
[email protected]0877e3d2009-10-17 22:29:571255// TODO(wtc): This method and the DoReadBodyComplete method are almost
1256// the same. Figure out a good way for these two methods to share code.
[email protected]2d2697f92009-02-18 21:00:321257int HttpNetworkTransaction::DoDrainBodyForAuthRestartComplete(int result) {
[email protected]68873ba2009-06-04 21:49:231258 // keep_alive defaults to true because the very reason we're draining the
1259 // response body is to reuse the connection for auth restart.
1260 bool done = false, keep_alive = true;
[email protected]2d2697f92009-02-18 21:00:321261 if (result < 0) {
[email protected]0877e3d2009-10-17 22:29:571262 // Error or closed connection while reading the socket.
[email protected]2d2697f92009-02-18 21:00:321263 done = true;
[email protected]68873ba2009-06-04 21:49:231264 keep_alive = false;
[email protected]0877e3d2009-10-17 22:29:571265 } else if (http_stream_->IsResponseBodyComplete()) {
1266 done = true;
[email protected]2d2697f92009-02-18 21:00:321267 }
1268
1269 if (done) {
1270 DidDrainBodyForAuthRestart(keep_alive);
1271 } else {
1272 // Keep draining.
1273 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
1274 }
1275
1276 return OK;
1277}
1278
[email protected]1f14a912009-12-21 20:32:441279int HttpNetworkTransaction::DoSpdySendRequest() {
1280 next_state_ = STATE_SPDY_SEND_REQUEST_COMPLETE;
[email protected]9be804c82010-06-24 17:59:461281 CHECK(!spdy_http_stream_.get());
[email protected]1f14a912009-12-21 20:32:441282
1283 // First we get a SPDY session. Theoretically, we've just negotiated one, but
1284 // if one already exists, then screw it, use the existing one! Otherwise,
1285 // use the existing TCP socket.
1286
[email protected]955fc2e72010-02-08 20:37:301287 const scoped_refptr<SpdySessionPool> spdy_pool =
1288 session_->spdy_session_pool();
1289 scoped_refptr<SpdySession> spdy_session;
[email protected]5e2e6c77d12009-12-24 21:57:161290
[email protected]2d731a32010-04-29 01:04:061291 if (spdy_pool->HasSession(endpoint_)) {
[email protected]635909f2010-05-12 18:19:361292 spdy_session = spdy_pool->Get(endpoint_, session_, net_log_);
[email protected]1f14a912009-12-21 20:32:441293 } else {
[email protected]5fe524e2010-02-20 00:43:221294 // SPDY is negotiated using the TLS next protocol negotiation (NPN)
1295 // extension, so |connection_| must contain an SSLClientSocket.
1296 DCHECK(using_ssl_);
[email protected]2ff8b312010-04-26 22:20:541297 CHECK(connection_->socket());
[email protected]26ef6582010-06-24 02:30:471298 int error = spdy_pool->GetSpdySessionFromSSLSocket(
[email protected]bdbda462010-06-28 17:30:371299 endpoint_, session_, connection_.release(), net_log_,
1300 spdy_certificate_error_, &spdy_session);
[email protected]26ef6582010-06-24 02:30:471301 if (error != OK)
1302 return error;
[email protected]1f14a912009-12-21 20:32:441303 }
1304
1305 CHECK(spdy_session.get());
[email protected]b278eb72010-07-09 20:17:001306 if(spdy_session->IsClosed())
1307 return ERR_CONNECTION_CLOSED;
[email protected]1f14a912009-12-21 20:32:441308
[email protected]7a6db4022010-03-24 23:37:501309 UploadDataStream* upload_data = NULL;
1310 if (request_->upload_data) {
1311 int error_code = OK;
1312 upload_data = UploadDataStream::Create(request_->upload_data, &error_code);
1313 if (!upload_data)
1314 return error_code;
1315 }
[email protected]1f14a912009-12-21 20:32:441316 headers_valid_ = false;
[email protected]9be804c82010-06-24 17:59:461317 scoped_refptr<SpdyStream> spdy_stream;
[email protected]bdbda462010-06-28 17:30:371318 if (request_->method == "GET") {
1319 int error =
1320 spdy_session->GetPushStream(request_->url, &spdy_stream, net_log_);
1321 if (error != OK)
1322 return error;
1323 }
[email protected]9be804c82010-06-24 17:59:461324 if (spdy_stream.get()) {
1325 DCHECK(spdy_stream->pushed());
1326 CHECK(spdy_stream->GetDelegate() == NULL);
1327 spdy_http_stream_.reset(new SpdyHttpStream(spdy_stream));
1328 spdy_http_stream_->InitializeRequest(*request_, base::Time::Now(), NULL);
1329 } else {
[email protected]bdbda462010-06-28 17:30:371330 int error = spdy_session->CreateStream(request_->url,
1331 request_->priority,
1332 &spdy_stream,
1333 net_log_);
1334 if (error != OK)
1335 return error;
[email protected]9be804c82010-06-24 17:59:461336 DCHECK(!spdy_stream->pushed());
1337 CHECK(spdy_stream->GetDelegate() == NULL);
1338 spdy_http_stream_.reset(new SpdyHttpStream(spdy_stream));
1339 spdy_http_stream_->InitializeRequest(
1340 *request_, base::Time::Now(), upload_data);
1341 }
1342 return spdy_http_stream_->SendRequest(&response_, &io_callback_);
[email protected]1f14a912009-12-21 20:32:441343}
1344
1345int HttpNetworkTransaction::DoSpdySendRequestComplete(int result) {
1346 if (result < 0)
1347 return result;
1348
1349 next_state_ = STATE_SPDY_READ_HEADERS;
1350 return OK;
1351}
1352
1353int HttpNetworkTransaction::DoSpdyReadHeaders() {
1354 next_state_ = STATE_SPDY_READ_HEADERS_COMPLETE;
[email protected]9be804c82010-06-24 17:59:461355 return spdy_http_stream_->ReadResponseHeaders(&io_callback_);
[email protected]1f14a912009-12-21 20:32:441356}
1357
1358int HttpNetworkTransaction::DoSpdyReadHeadersComplete(int result) {
1359 // TODO(willchan): Flesh out the support for HTTP authentication here.
1360 if (result == OK)
1361 headers_valid_ = true;
[email protected]8e3d2d32010-06-13 18:46:231362
1363 LogTransactionConnectedMetrics();
1364
[email protected]1f14a912009-12-21 20:32:441365 return result;
1366}
1367
1368int HttpNetworkTransaction::DoSpdyReadBody() {
1369 next_state_ = STATE_SPDY_READ_BODY_COMPLETE;
1370
[email protected]9be804c82010-06-24 17:59:461371 return spdy_http_stream_->ReadResponseBody(
[email protected]1f14a912009-12-21 20:32:441372 read_buf_, read_buf_len_, &io_callback_);
1373}
1374
1375int HttpNetworkTransaction::DoSpdyReadBodyComplete(int result) {
1376 read_buf_ = NULL;
1377 read_buf_len_ = 0;
1378
1379 if (result <= 0)
[email protected]65d34382010-07-01 18:12:261380 spdy_http_stream_.reset();
[email protected]1f14a912009-12-21 20:32:441381
1382 return result;
1383}
1384
[email protected]a796bcec2010-03-22 17:17:261385void HttpNetworkTransaction::LogHttpConnectedMetrics(
[email protected]f9d285c2009-08-17 19:54:291386 const ClientSocketHandle& handle) {
[email protected]a796bcec2010-03-22 17:17:261387 UMA_HISTOGRAM_ENUMERATION("Net.HttpSocketType", handle.reuse_type(),
[email protected]2227c692010-05-04 15:36:111388 ClientSocketHandle::NUM_TYPES);
[email protected]f9d285c2009-08-17 19:54:291389
[email protected]bc3875bbc2009-08-24 19:44:201390 switch (handle.reuse_type()) {
1391 case ClientSocketHandle::UNUSED:
[email protected]a796bcec2010-03-22 17:17:261392 UMA_HISTOGRAM_CUSTOM_TIMES("Net.HttpConnectionLatency",
1393 handle.setup_time(),
1394 base::TimeDelta::FromMilliseconds(1),
1395 base::TimeDelta::FromMinutes(10),
1396 100);
[email protected]bc3875bbc2009-08-24 19:44:201397 break;
1398 case ClientSocketHandle::UNUSED_IDLE:
[email protected]a796bcec2010-03-22 17:17:261399 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SocketIdleTimeBeforeNextUse_UnusedSocket",
1400 handle.idle_time(),
1401 base::TimeDelta::FromMilliseconds(1),
1402 base::TimeDelta::FromMinutes(6),
1403 100);
[email protected]bc3875bbc2009-08-24 19:44:201404 break;
1405 case ClientSocketHandle::REUSED_IDLE:
[email protected]a796bcec2010-03-22 17:17:261406 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SocketIdleTimeBeforeNextUse_ReusedSocket",
1407 handle.idle_time(),
1408 base::TimeDelta::FromMilliseconds(1),
1409 base::TimeDelta::FromMinutes(6),
1410 100);
[email protected]bc3875bbc2009-08-24 19:44:201411 break;
1412 default:
1413 NOTREACHED();
1414 break;
1415 }
[email protected]42afa7c2009-04-17 23:51:241416}
1417
[email protected]f9d285c2009-08-17 19:54:291418void HttpNetworkTransaction::LogIOErrorMetrics(
1419 const ClientSocketHandle& handle) {
[email protected]2753b392009-12-28 06:59:521420 UMA_HISTOGRAM_ENUMERATION("Net.IOError_SocketReuseType",
[email protected]2227c692010-05-04 15:36:111421 handle.reuse_type(), ClientSocketHandle::NUM_TYPES);
[email protected]f9d285c2009-08-17 19:54:291422
[email protected]f9d285c2009-08-17 19:54:291423 switch (handle.reuse_type()) {
1424 case ClientSocketHandle::UNUSED:
1425 break;
1426 case ClientSocketHandle::UNUSED_IDLE:
[email protected]bc3875bbc2009-08-24 19:44:201427 UMA_HISTOGRAM_CUSTOM_TIMES(
1428 "Net.SocketIdleTimeOnIOError2_UnusedSocket",
1429 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1430 base::TimeDelta::FromMinutes(6), 100);
[email protected]f9d285c2009-08-17 19:54:291431 break;
1432 case ClientSocketHandle::REUSED_IDLE:
[email protected]bc3875bbc2009-08-24 19:44:201433 UMA_HISTOGRAM_CUSTOM_TIMES(
1434 "Net.SocketIdleTimeOnIOError2_ReusedSocket",
1435 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1436 base::TimeDelta::FromMinutes(6), 100);
[email protected]f9d285c2009-08-17 19:54:291437 break;
1438 default:
1439 NOTREACHED();
1440 break;
1441 }
1442}
1443
[email protected]8e3d2d32010-06-13 18:46:231444void HttpNetworkTransaction::LogTransactionConnectedMetrics() {
1445 if (logged_response_time_)
1446 return;
1447
1448 logged_response_time_ = true;
1449
[email protected]a7e41312009-12-16 23:18:141450 base::TimeDelta total_duration = response_.response_time - start_time_;
[email protected]9a0a55f2009-04-13 23:23:031451
[email protected]510e854f2009-04-20 18:39:081452 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:581453 "Net.Transaction_Connected_Under_10",
[email protected]510e854f2009-04-20 18:39:081454 total_duration,
[email protected]9a0a55f2009-04-13 23:23:031455 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1456 100);
[email protected]1fa47592009-07-27 22:45:001457
[email protected]0310d432009-08-25 07:49:521458 if (!reused_socket_) {
[email protected]b01998a2009-04-21 01:01:111459 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:581460 "Net.Transaction_Connected_New",
[email protected]b01998a2009-04-21 01:01:111461 total_duration,
1462 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1463 100);
[email protected]d068f7a2010-06-07 15:12:591464
1465 static bool use_conn_impact_histogram(
1466 FieldTrialList::Find("ConnCountImpact") &&
1467 !FieldTrialList::Find("ConnCountImpact")->group_name().empty());
1468 if (use_conn_impact_histogram) {
1469 UMA_HISTOGRAM_CLIPPED_TIMES(
1470 FieldTrial::MakeName("Net.Transaction_Connected_New",
1471 "ConnCountImpact"),
1472 total_duration,
1473 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1474 100);
1475 }
[email protected]0310d432009-08-25 07:49:521476 }
1477
[email protected]8e3d2d32010-06-13 18:46:231478 static bool use_spdy_histogram(FieldTrialList::Find("SpdyImpact") &&
1479 !FieldTrialList::Find("SpdyImpact")->group_name().empty());
1480 if (use_spdy_histogram && response_.was_npn_negotiated) {
1481 UMA_HISTOGRAM_CLIPPED_TIMES(
1482 FieldTrial::MakeName("Net.Transaction_Connected_Under_10", "SpdyImpact"),
1483 total_duration, base::TimeDelta::FromMilliseconds(1),
1484 base::TimeDelta::FromMinutes(10), 100);
1485
1486 if (!reused_socket_) {
1487 UMA_HISTOGRAM_CLIPPED_TIMES(
1488 FieldTrial::MakeName("Net.Transaction_Connected_New", "SpdyImpact"),
1489 total_duration, base::TimeDelta::FromMilliseconds(1),
1490 base::TimeDelta::FromMinutes(10), 100);
1491 }
1492 }
1493
[email protected]510e854f2009-04-20 18:39:081494 // Currently, non-zero priority requests are frame or sub-frame resource
1495 // types. This will change when we also prioritize certain subresources like
1496 // css, js, etc.
1497 if (request_->priority) {
1498 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:581499 "Net.Priority_High_Latency",
[email protected]510e854f2009-04-20 18:39:081500 total_duration,
1501 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1502 100);
1503 } else {
1504 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:581505 "Net.Priority_Low_Latency",
[email protected]510e854f2009-04-20 18:39:081506 total_duration,
1507 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1508 100);
1509 }
[email protected]9a0a55f2009-04-13 23:23:031510}
1511
[email protected]56300172008-11-06 18:42:551512void HttpNetworkTransaction::LogTransactionMetrics() const {
[email protected]0877e3d2009-10-17 22:29:571513 base::TimeDelta duration = base::Time::Now() -
[email protected]2227c692010-05-04 15:36:111514 response_.request_time;
[email protected]56300172008-11-06 18:42:551515 if (60 < duration.InMinutes())
1516 return;
[email protected]0b48db42009-03-23 02:45:111517
[email protected]21b316a2009-03-23 18:25:061518 base::TimeDelta total_duration = base::Time::Now() - start_time_;
1519
[email protected]f929f2f22009-06-12 16:56:581520 UMA_HISTOGRAM_LONG_TIMES("Net.Transaction_Latency", duration);
1521 UMA_HISTOGRAM_CLIPPED_TIMES("Net.Transaction_Latency_Under_10", duration,
[email protected]2227c692010-05-04 15:36:111522 base::TimeDelta::FromMilliseconds(1),
1523 base::TimeDelta::FromMinutes(10),
1524 100);
[email protected]f929f2f22009-06-12 16:56:581525 UMA_HISTOGRAM_CLIPPED_TIMES("Net.Transaction_Latency_Total_Under_10",
[email protected]2227c692010-05-04 15:36:111526 total_duration,
1527 base::TimeDelta::FromMilliseconds(1),
1528 base::TimeDelta::FromMinutes(10), 100);
[email protected]808f6402009-03-30 20:02:071529 if (!reused_socket_) {
[email protected]f929f2f22009-06-12 16:56:581530 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]808f6402009-03-30 20:02:071531 "Net.Transaction_Latency_Total_New_Connection_Under_10",
[email protected]808f6402009-03-30 20:02:071532 total_duration, base::TimeDelta::FromMilliseconds(1),
1533 base::TimeDelta::FromMinutes(10), 100);
1534 }
[email protected]56300172008-11-06 18:42:551535}
1536
[email protected]ccb40e52008-09-17 20:54:401537int HttpNetworkTransaction::HandleCertificateError(int error) {
1538 DCHECK(using_ssl_);
[email protected]d7660f1c62010-02-15 02:57:291539 DCHECK(IsCertificateError(error));
1540
1541 SSLClientSocket* ssl_socket =
[email protected]2227c692010-05-04 15:36:111542 reinterpret_cast<SSLClientSocket*>(connection_->socket());
[email protected]d7660f1c62010-02-15 02:57:291543 ssl_socket->GetSSLInfo(&response_.ssl_info);
1544
1545 // Add the bad certificate to the set of allowed certificates in the
1546 // SSL info object. This data structure will be consulted after calling
1547 // RestartIgnoringLastError(). And the user will be asked interactively
1548 // before RestartIgnoringLastError() is ever called.
1549 SSLConfig::CertAndStatus bad_cert;
1550 bad_cert.cert = response_.ssl_info.cert;
1551 bad_cert.cert_status = response_.ssl_info.cert_status;
1552 ssl_config_.allowed_bad_certs.push_back(bad_cert);
[email protected]ccb40e52008-09-17 20:54:401553
[email protected]37a67922010-03-05 00:16:021554 if (g_ignore_certificate_errors)
1555 return OK;
1556
[email protected]ccb40e52008-09-17 20:54:401557 const int kCertFlags = LOAD_IGNORE_CERT_COMMON_NAME_INVALID |
1558 LOAD_IGNORE_CERT_DATE_INVALID |
1559 LOAD_IGNORE_CERT_AUTHORITY_INVALID |
1560 LOAD_IGNORE_CERT_WRONG_USAGE;
1561 if (request_->load_flags & kCertFlags) {
1562 switch (error) {
1563 case ERR_CERT_COMMON_NAME_INVALID:
1564 if (request_->load_flags & LOAD_IGNORE_CERT_COMMON_NAME_INVALID)
1565 error = OK;
1566 break;
1567 case ERR_CERT_DATE_INVALID:
1568 if (request_->load_flags & LOAD_IGNORE_CERT_DATE_INVALID)
1569 error = OK;
1570 break;
1571 case ERR_CERT_AUTHORITY_INVALID:
1572 if (request_->load_flags & LOAD_IGNORE_CERT_AUTHORITY_INVALID)
1573 error = OK;
1574 break;
1575 }
1576 }
[email protected]ccb40e52008-09-17 20:54:401577 return error;
1578}
1579
[email protected]5e363962009-06-19 19:57:011580int HttpNetworkTransaction::HandleCertificateRequest(int error) {
1581 // Assert that the socket did not send a client certificate.
1582 // Note: If we got a reused socket, it was created with some other
1583 // transaction's ssl_config_, so we need to disable this assertion. We can
1584 // get a certificate request on a reused socket when the server requested
1585 // renegotiation (rehandshake).
1586 // TODO(wtc): add a GetSSLParams method to SSLClientSocket so we can query
1587 // the SSL parameters it was created with and get rid of the reused_socket_
1588 // test.
1589 DCHECK(reused_socket_ || !ssl_config_.send_client_cert);
1590
[email protected]a7e41312009-12-16 23:18:141591 response_.cert_request_info = new SSLCertRequestInfo;
[email protected]0b45559b2009-06-12 21:45:111592 SSLClientSocket* ssl_socket =
[email protected]1f14a912009-12-21 20:32:441593 reinterpret_cast<SSLClientSocket*>(connection_->socket());
[email protected]a7e41312009-12-16 23:18:141594 ssl_socket->GetSSLCertRequestInfo(response_.cert_request_info);
[email protected]0b45559b2009-06-12 21:45:111595
1596 // Close the connection while the user is selecting a certificate to send
1597 // to the server.
[email protected]1f14a912009-12-21 20:32:441598 connection_->socket()->Disconnect();
1599 connection_->Reset();
[email protected]5e363962009-06-19 19:57:011600
1601 // If the user selected one of the certificate in client_certs for this
1602 // server before, use it automatically.
1603 X509Certificate* client_cert = session_->ssl_client_auth_cache()->
[email protected]2227c692010-05-04 15:36:111604 Lookup(GetHostAndPort(request_->url));
[email protected]5e363962009-06-19 19:57:011605 if (client_cert) {
1606 const std::vector<scoped_refptr<X509Certificate> >& client_certs =
[email protected]a7e41312009-12-16 23:18:141607 response_.cert_request_info->client_certs;
[email protected]5e363962009-06-19 19:57:011608 for (size_t i = 0; i < client_certs.size(); ++i) {
[email protected]bd0b7432009-06-23 21:03:421609 if (client_cert->fingerprint().Equals(client_certs[i]->fingerprint())) {
[email protected]5e363962009-06-19 19:57:011610 ssl_config_.client_cert = client_cert;
1611 ssl_config_.send_client_cert = true;
1612 next_state_ = STATE_INIT_CONNECTION;
1613 // Reset the other member variables.
1614 // Note: this is necessary only with SSL renegotiation.
1615 ResetStateForRestart();
1616 return OK;
1617 }
1618 }
1619 }
1620 return error;
[email protected]0b45559b2009-06-12 21:45:111621}
1622
[email protected]c5949a32008-10-08 17:28:231623int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
[email protected]5e363962009-06-19 19:57:011624 if (ssl_config_.send_client_cert &&
[email protected]2227c692010-05-04 15:36:111625 (error == ERR_SSL_PROTOCOL_ERROR ||
1626 error == ERR_BAD_SSL_CLIENT_AUTH_CERT)) {
[email protected]5e363962009-06-19 19:57:011627 session_->ssl_client_auth_cache()->Remove(GetHostAndPort(request_->url));
1628 }
1629
[email protected]5a179bcc2008-10-13 18:10:591630 switch (error) {
1631 case ERR_SSL_PROTOCOL_ERROR:
1632 case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
[email protected]aeaca1f2010-04-20 22:05:211633 case ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
[email protected]0ed94682010-05-18 15:09:001634 case ERR_SSL_BAD_RECORD_MAC_ALERT:
[email protected]d102f542010-06-30 14:51:051635 if (ssl_config_.tls1_enabled &&
1636 !SSLConfigService::IsKnownStrictTLSServer(request_->url.host())) {
[email protected]0ed94682010-05-18 15:09:001637 // This could be a TLS-intolerant server, an SSL 3.0 server that
1638 // chose a TLS-only cipher suite or a server with buggy DEFLATE
1639 // support. Turn off TLS 1.0, DEFLATE support and retry.
[email protected]aeaca1f2010-04-20 22:05:211640 g_tls_intolerant_servers->insert(GetHostAndPort(request_->url));
1641 ResetConnectionAndRequestForResend();
[email protected]5a179bcc2008-10-13 18:10:591642 error = OK;
1643 }
1644 break;
[email protected]c5949a32008-10-08 17:28:231645 }
[email protected]c5949a32008-10-08 17:28:231646 return error;
1647}
1648
[email protected]96d570e42008-08-05 22:43:041649// This method determines whether it is safe to resend the request after an
1650// IO error. It can only be called in response to request header or body
1651// write errors or response header read errors. It should not be used in
1652// other cases, such as a Connect error.
initial.commit586acc5fe2008-07-26 22:42:521653int HttpNetworkTransaction::HandleIOError(int error) {
1654 switch (error) {
1655 // If we try to reuse a connection that the server is in the process of
1656 // closing, we may end up successfully writing out our request (or a
1657 // portion of our request) only to find a connection error when we try to
1658 // read from (or finish writing to) the socket.
1659 case ERR_CONNECTION_RESET:
1660 case ERR_CONNECTION_CLOSED:
1661 case ERR_CONNECTION_ABORTED:
[email protected]1f14a912009-12-21 20:32:441662 LogIOErrorMetrics(*connection_);
[email protected]a19f1c602009-08-24 21:35:281663 if (ShouldResendRequest(error)) {
[email protected]1c773ea12009-04-28 19:58:421664 ResetConnectionAndRequestForResend();
initial.commit586acc5fe2008-07-26 22:42:521665 error = OK;
[email protected]1c773ea12009-04-28 19:58:421666 }
initial.commit586acc5fe2008-07-26 22:42:521667 break;
1668 }
1669 return error;
1670}
1671
[email protected]c3b35c22008-09-27 03:19:421672void HttpNetworkTransaction::ResetStateForRestart() {
[email protected]0757e7702009-03-27 04:00:221673 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:421674 read_buf_ = NULL;
1675 read_buf_len_ = 0;
[email protected]1f14a912009-12-21 20:32:441676 http_stream_.reset();
[email protected]0877e3d2009-10-17 22:29:571677 headers_valid_ = false;
1678 request_headers_.clear();
[email protected]a7e41312009-12-16 23:18:141679 response_ = HttpResponseInfo();
[email protected]0877e3d2009-10-17 22:29:571680}
1681
1682HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const {
[email protected]a7e41312009-12-16 23:18:141683 return response_.headers;
[email protected]c3b35c22008-09-27 03:19:421684}
1685
[email protected]a19f1c602009-08-24 21:35:281686bool HttpNetworkTransaction::ShouldResendRequest(int error) const {
[email protected]2a5c76b2008-09-25 22:15:161687 // NOTE: we resend a request only if we reused a keep-alive connection.
1688 // This automatically prevents an infinite resend loop because we'll run
1689 // out of the cached keep-alive connections eventually.
[email protected]8a1f3312010-05-25 19:25:041690 if (!connection_->ShouldResendFailedRequest(error) ||
[email protected]0877e3d2009-10-17 22:29:571691 GetResponseHeaders()) { // We have received some response headers.
[email protected]2a5c76b2008-09-25 22:15:161692 return false;
1693 }
[email protected]1c773ea12009-04-28 19:58:421694 return true;
1695}
1696
1697void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
[email protected]1f14a912009-12-21 20:32:441698 connection_->socket()->Disconnect();
1699 connection_->Reset();
[email protected]0877e3d2009-10-17 22:29:571700 // We need to clear request_headers_ because it contains the real request
1701 // headers, but we may need to resend the CONNECT request first to recreate
1702 // the SSL tunnel.
1703 request_headers_.clear();
[email protected]2a5c76b2008-09-25 22:15:161704 next_state_ = STATE_INIT_CONNECTION; // Resend the request.
[email protected]2a5c76b2008-09-25 22:15:161705}
1706
[email protected]86ec30d2008-09-29 21:53:541707int HttpNetworkTransaction::ReconsiderProxyAfterError(int error) {
1708 DCHECK(!pac_request_);
1709
1710 // A failure to resolve the hostname or any error related to establishing a
1711 // TCP connection could be grounds for trying a new proxy configuration.
[email protected]7be51312008-09-29 23:21:301712 //
1713 // Why do this when a hostname cannot be resolved? Some URLs only make sense
1714 // to proxy servers. The hostname in those URLs might fail to resolve if we
1715 // are still using a non-proxy config. We need to check if a proxy config
1716 // now exists that corresponds to a proxy server that could load the URL.
1717 //
[email protected]86ec30d2008-09-29 21:53:541718 switch (error) {
1719 case ERR_NAME_NOT_RESOLVED:
1720 case ERR_INTERNET_DISCONNECTED:
1721 case ERR_ADDRESS_UNREACHABLE:
1722 case ERR_CONNECTION_CLOSED:
1723 case ERR_CONNECTION_RESET:
1724 case ERR_CONNECTION_REFUSED:
1725 case ERR_CONNECTION_ABORTED:
1726 case ERR_TIMED_OUT:
1727 case ERR_TUNNEL_CONNECTION_FAILED:
[email protected]d5a309592010-02-05 02:22:521728 case ERR_SOCKS_CONNECTION_FAILED:
[email protected]86ec30d2008-09-29 21:53:541729 break;
[email protected]d5a309592010-02-05 02:22:521730 case ERR_SOCKS_CONNECTION_HOST_UNREACHABLE:
1731 // Remap the SOCKS-specific "host unreachable" error to a more
1732 // generic error code (this way consumers like the link doctor
1733 // know to substitute their error page).
1734 //
1735 // Note that if the host resolving was done by the SOCSK5 proxy, we can't
1736 // differentiate between a proxy-side "host not found" versus a proxy-side
1737 // "address unreachable" error, and will report both of these failures as
1738 // ERR_ADDRESS_UNREACHABLE.
1739 return ERR_ADDRESS_UNREACHABLE;
[email protected]86ec30d2008-09-29 21:53:541740 default:
1741 return error;
1742 }
1743
[email protected]677c90572008-12-10 09:03:151744 if (request_->load_flags & LOAD_BYPASS_PROXY) {
1745 return error;
1746 }
1747
[email protected]86ec30d2008-09-29 21:53:541748 int rv = session_->proxy_service()->ReconsiderProxyAfterError(
[email protected]9e743cd2010-03-16 07:03:531749 request_->url, &proxy_info_, &io_callback_, &pac_request_, net_log_);
[email protected]86ec30d2008-09-29 21:53:541750 if (rv == OK || rv == ERR_IO_PENDING) {
[email protected]9172a982009-06-06 00:30:251751 // If the error was during connection setup, there is no socket to
1752 // disconnect.
[email protected]1f14a912009-12-21 20:32:441753 if (connection_->socket())
1754 connection_->socket()->Disconnect();
1755 connection_->Reset();
[email protected]86ec30d2008-09-29 21:53:541756 next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
1757 } else {
[email protected]69719062010-01-05 20:09:211758 // If ReconsiderProxyAfterError() failed synchronously, it means
1759 // there was nothing left to fall-back to, so fail the transaction
1760 // with the last connection error we got.
1761 // TODO(eroman): This is a confusing contract, make it more obvious.
[email protected]86ec30d2008-09-29 21:53:541762 rv = error;
1763 }
1764
1765 return rv;
1766}
1767
[email protected]1c773ea12009-04-28 19:58:421768bool HttpNetworkTransaction::ShouldApplyProxyAuth() const {
[email protected]8a1f3312010-05-25 19:25:041769 return !using_ssl_ && proxy_info_.is_http();
[email protected]1c773ea12009-04-28 19:58:421770}
license.botbf09a502008-08-24 00:55:551771
[email protected]1c773ea12009-04-28 19:58:421772bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
[email protected]8a1f3312010-05-25 19:25:041773 return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA);
[email protected]1c773ea12009-04-28 19:58:421774}
1775
[email protected]e772db3f2010-07-12 18:11:131776int HttpNetworkTransaction::HandleAuthChallenge() {
[email protected]0877e3d2009-10-17 22:29:571777 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
1778 DCHECK(headers);
[email protected]c3b35c22008-09-27 03:19:421779
[email protected]0877e3d2009-10-17 22:29:571780 int status = headers->response_code();
[email protected]c3b35c22008-09-27 03:19:421781 if (status != 401 && status != 407)
1782 return OK;
1783 HttpAuth::Target target = status == 407 ?
[email protected]2227c692010-05-04 15:36:111784 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER;
[email protected]038e9a32008-10-08 22:40:161785 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
1786 return ERR_UNEXPECTED_PROXY_AUTH;
[email protected]c3b35c22008-09-27 03:19:421787
[email protected]a7ea8832010-07-12 17:54:541788 int rv = auth_controllers_[target]->HandleAuthChallenge(
[email protected]560c0432010-07-13 20:45:311789 headers, (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false,
1790 net_log_);
[email protected]228404f2010-06-24 04:31:411791 if (auth_controllers_[target]->HaveAuthHandler())
1792 pending_auth_target_ = target;
1793
1794 scoped_refptr<AuthChallengeInfo> auth_info =
1795 auth_controllers_[target]->auth_info();
1796 if (auth_info.get())
1797 response_.auth_challenge = auth_info;
1798
[email protected]228404f2010-06-24 04:31:411799 return rv;
[email protected]f9ee6b52008-11-08 06:46:231800}
1801
[email protected]228404f2010-06-24 04:31:411802GURL HttpNetworkTransaction::AuthURL(HttpAuth::Target target) const {
1803 switch (target) {
1804 case HttpAuth::AUTH_PROXY:
1805 if (!proxy_info_.proxy_server().is_valid() ||
1806 proxy_info_.proxy_server().is_direct()) {
1807 return GURL(); // There is no proxy server.
1808 }
1809 return GURL("http://" + proxy_info_.proxy_server().host_and_port());
1810 case HttpAuth::AUTH_SERVER:
1811 return request_->url;
1812 default:
1813 return GURL();
1814 }
[email protected]c3b35c22008-09-27 03:19:421815}
1816
[email protected]a2cb8122010-03-10 17:22:421817void HttpNetworkTransaction::MarkBrokenAlternateProtocolAndFallback() {
[email protected]631f1322010-04-30 17:59:111818 // We have to:
1819 // * Reset the endpoint to be the unmodified URL specified destination.
1820 // * Mark the endpoint as broken so we don't try again.
1821 // * Set the alternate protocol mode to kDoNotUseAlternateProtocol so we
1822 // ignore future Alternate-Protocol headers from the HostPortPair.
1823 // * Reset the connection and go back to STATE_INIT_CONNECTION.
1824
1825 endpoint_ = HostPortPair(request_->url.HostNoBrackets(),
1826 request_->url.EffectiveIntPort());
[email protected]a2cb8122010-03-10 17:22:421827
1828 session_->mutable_alternate_protocols()->MarkBrokenAlternateProtocolFor(
[email protected]631f1322010-04-30 17:59:111829 endpoint_);
[email protected]a2cb8122010-03-10 17:22:421830
1831 alternate_protocol_mode_ = kDoNotUseAlternateProtocol;
1832 if (connection_->socket())
1833 connection_->socket()->Disconnect();
1834 connection_->Reset();
1835 next_state_ = STATE_INIT_CONNECTION;
1836}
1837
[email protected]aef04272010-06-28 18:03:041838#define STATE_CASE(s) case s: \
1839 description = StringPrintf("%s (0x%08X)", #s, s); \
1840 break
1841
1842std::string HttpNetworkTransaction::DescribeState(State state) {
1843 std::string description;
1844 switch (state) {
1845 STATE_CASE(STATE_RESOLVE_PROXY);
1846 STATE_CASE(STATE_RESOLVE_PROXY_COMPLETE);
1847 STATE_CASE(STATE_INIT_CONNECTION);
1848 STATE_CASE(STATE_INIT_CONNECTION_COMPLETE);
[email protected]a7ea8832010-07-12 17:54:541849 STATE_CASE(STATE_TUNNEL_RESTART_WITH_AUTH);
[email protected]aef04272010-06-28 18:03:041850 STATE_CASE(STATE_SSL_CONNECT);
1851 STATE_CASE(STATE_SSL_CONNECT_COMPLETE);
1852 STATE_CASE(STATE_GENERATE_PROXY_AUTH_TOKEN);
1853 STATE_CASE(STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE);
1854 STATE_CASE(STATE_GENERATE_SERVER_AUTH_TOKEN);
1855 STATE_CASE(STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE);
1856 STATE_CASE(STATE_SEND_REQUEST);
1857 STATE_CASE(STATE_SEND_REQUEST_COMPLETE);
1858 STATE_CASE(STATE_READ_HEADERS);
1859 STATE_CASE(STATE_READ_HEADERS_COMPLETE);
[email protected]aef04272010-06-28 18:03:041860 STATE_CASE(STATE_READ_BODY);
1861 STATE_CASE(STATE_READ_BODY_COMPLETE);
1862 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART);
1863 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE);
1864 STATE_CASE(STATE_SPDY_SEND_REQUEST);
1865 STATE_CASE(STATE_SPDY_SEND_REQUEST_COMPLETE);
1866 STATE_CASE(STATE_SPDY_READ_HEADERS);
1867 STATE_CASE(STATE_SPDY_READ_HEADERS_COMPLETE);
1868 STATE_CASE(STATE_SPDY_READ_BODY);
1869 STATE_CASE(STATE_SPDY_READ_BODY_COMPLETE);
1870 STATE_CASE(STATE_NONE);
1871 default:
1872 description = StringPrintf("Unknown state 0x%08X (%u)", state, state);
1873 break;
1874 }
1875 return description;
1876}
1877
1878#undef STATE_CASE
1879
[email protected]c3b35c22008-09-27 03:19:421880} // namespace net