blob: fb5f8012376032785c0f97db3adac0f961778b42 [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]e60e47a2010-07-14 03:37:1844#include "net/socket/ssl_client_socket_pool.h"
[email protected]7fc5b09a2010-02-27 00:07:3845#include "net/socket/tcp_client_socket_pool.h"
[email protected]65d56aa2010-06-14 04:13:4046#include "net/spdy/spdy_http_stream.h"
[email protected]dab9c7d2010-02-06 21:44:3247#include "net/spdy/spdy_session.h"
48#include "net/spdy/spdy_session_pool.h"
initial.commit586acc5fe2008-07-26 22:42:5249
[email protected]e1acf6f2008-10-27 20:43:3350using base::Time;
51
initial.commit586acc5fe2008-07-26 22:42:5252namespace net {
53
[email protected]1c773ea12009-04-28 19:58:4254namespace {
55
[email protected]b6a50182010-05-12 22:47:1456const HostMappingRules* g_host_mapping_rules = NULL;
[email protected]a2cb8122010-03-10 17:22:4257const std::string* g_next_protos = NULL;
[email protected]31e2c69e2010-04-15 18:06:0658bool g_use_alternate_protocols = false;
[email protected]a2cb8122010-03-10 17:22:4259
[email protected]aeaca1f2010-04-20 22:05:2160// A set of host:port strings. These are servers which we have needed to back
61// off to SSLv3 for.
62std::set<std::string>* g_tls_intolerant_servers = NULL;
63
[email protected]1c773ea12009-04-28 19:58:4264void BuildRequestHeaders(const HttpRequestInfo* request_info,
[email protected]270c6412010-03-29 22:02:4765 const HttpRequestHeaders& authorization_headers,
[email protected]1c773ea12009-04-28 19:58:4266 const UploadDataStream* upload_data_stream,
67 bool using_proxy,
[email protected]8c76ae22010-04-20 22:15:4368 std::string* request_line,
[email protected]270c6412010-03-29 22:02:4769 HttpRequestHeaders* request_headers) {
70 const std::string path = using_proxy ?
[email protected]2227c692010-05-04 15:36:1171 HttpUtil::SpecForRequest(request_info->url) :
72 HttpUtil::PathForRequest(request_info->url);
[email protected]8c76ae22010-04-20 22:15:4373 *request_line = StringPrintf(
74 "%s %s HTTP/1.1\r\n", request_info->method.c_str(), path.c_str());
[email protected]270c6412010-03-29 22:02:4775 request_headers->SetHeader(HttpRequestHeaders::kHost,
76 GetHostAndOptionalPort(request_info->url));
77
78 // For compat with HTTP/1.0 servers and proxies:
79 if (using_proxy) {
80 request_headers->SetHeader(HttpRequestHeaders::kProxyConnection,
81 "keep-alive");
82 } else {
83 request_headers->SetHeader(HttpRequestHeaders::kConnection, "keep-alive");
84 }
85
[email protected]270c6412010-03-29 22:02:4786 // Our consumer should have made sure that this is a safe referrer. See for
87 // instance WebCore::FrameLoader::HideReferrer.
88 if (request_info->referrer.is_valid()) {
89 request_headers->SetHeader(HttpRequestHeaders::kReferer,
90 request_info->referrer.spec());
91 }
92
93 // Add a content length header?
94 if (upload_data_stream) {
95 request_headers->SetHeader(
96 HttpRequestHeaders::kContentLength,
97 Uint64ToString(upload_data_stream->size()));
98 } else if (request_info->method == "POST" || request_info->method == "PUT" ||
99 request_info->method == "HEAD") {
100 // An empty POST/PUT request still needs a content length. As for HEAD,
101 // IE and Safari also add a content length header. Presumably it is to
102 // support sending a HEAD request to an URL that only expects to be sent a
103 // POST or some other method that normally would have a message body.
104 request_headers->SetHeader(HttpRequestHeaders::kContentLength, "0");
105 }
106
107 // Honor load flags that impact proxy caches.
108 if (request_info->load_flags & LOAD_BYPASS_CACHE) {
109 request_headers->SetHeader(HttpRequestHeaders::kPragma, "no-cache");
110 request_headers->SetHeader(HttpRequestHeaders::kCacheControl, "no-cache");
111 } else if (request_info->load_flags & LOAD_VALIDATE_CACHE) {
112 request_headers->SetHeader(HttpRequestHeaders::kCacheControl, "max-age=0");
113 }
114
115 request_headers->MergeFrom(authorization_headers);
116
[email protected]860c85d2010-02-10 07:22:40117 // Headers that will be stripped from request_info->extra_headers to prevent,
118 // e.g., plugins from overriding headers that are controlled using other
119 // means. Otherwise a plugin could set a referrer although sending the
120 // referrer is inhibited.
121 // TODO(jochen): check whether also other headers should be stripped.
122 static const char* const kExtraHeadersToBeStripped[] = {
123 "Referer"
124 };
125
[email protected]8c76ae22010-04-20 22:15:43126 HttpRequestHeaders stripped_extra_headers;
127 stripped_extra_headers.CopyFrom(request_info->extra_headers);
[email protected]2227c692010-05-04 15:36:11128 for (size_t i = 0; i < arraysize(kExtraHeadersToBeStripped); ++i)
129 stripped_extra_headers.RemoveHeader(kExtraHeadersToBeStripped[i]);
[email protected]8c76ae22010-04-20 22:15:43130 request_headers->MergeFrom(stripped_extra_headers);
[email protected]1c773ea12009-04-28 19:58:42131}
132
[email protected]564b4912010-03-09 16:30:42133void ProcessAlternateProtocol(const HttpResponseHeaders& headers,
134 const HostPortPair& http_host_port_pair,
135 HttpAlternateProtocols* alternate_protocols) {
[email protected]a2cb8122010-03-10 17:22:42136
[email protected]564b4912010-03-09 16:30:42137 std::string alternate_protocol_str;
138 if (!headers.EnumerateHeader(NULL, HttpAlternateProtocols::kHeader,
139 &alternate_protocol_str)) {
140 // Header is not present.
141 return;
142 }
143
144 std::vector<std::string> port_protocol_vector;
145 SplitString(alternate_protocol_str, ':', &port_protocol_vector);
146 if (port_protocol_vector.size() != 2) {
147 DLOG(WARNING) << HttpAlternateProtocols::kHeader
148 << " header has too many tokens: "
149 << alternate_protocol_str;
150 return;
151 }
152
153 int port;
154 if (!StringToInt(port_protocol_vector[0], &port) ||
155 port <= 0 || port >= 1 << 16) {
156 DLOG(WARNING) << HttpAlternateProtocols::kHeader
157 << " header has unrecognizable port: "
158 << port_protocol_vector[0];
159 return;
160 }
161
[email protected]a2cb8122010-03-10 17:22:42162 if (port_protocol_vector[1] !=
163 HttpAlternateProtocols::kProtocolStrings[
[email protected]2227c692010-05-04 15:36:11164 HttpAlternateProtocols::NPN_SPDY_1]) {
[email protected]a2cb8122010-03-10 17:22:42165 // Currently, we only recognize the npn-spdy protocol.
[email protected]564b4912010-03-09 16:30:42166 DLOG(WARNING) << HttpAlternateProtocols::kHeader
167 << " header has unrecognized protocol: "
168 << port_protocol_vector[1];
169 return;
170 }
171
[email protected]b6a50182010-05-12 22:47:14172 HostPortPair host_port(http_host_port_pair);
173 if (g_host_mapping_rules)
174 g_host_mapping_rules->RewriteHost(&host_port);
175
176 if (alternate_protocols->HasAlternateProtocolFor(host_port)) {
[email protected]564b4912010-03-09 16:30:42177 const HttpAlternateProtocols::PortProtocolPair existing_alternate =
[email protected]b6a50182010-05-12 22:47:14178 alternate_protocols->GetAlternateProtocolFor(host_port);
[email protected]564b4912010-03-09 16:30:42179 // If we think the alternate protocol is broken, don't change it.
180 if (existing_alternate.protocol == HttpAlternateProtocols::BROKEN)
181 return;
182 }
183
[email protected]a2cb8122010-03-10 17:22:42184 alternate_protocols->SetAlternateProtocolFor(
[email protected]b6a50182010-05-12 22:47:14185 host_port, port, HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:42186}
187
[email protected]1c773ea12009-04-28 19:58:42188} // namespace
189
initial.commit586acc5fe2008-07-26 22:42:52190//-----------------------------------------------------------------------------
191
[email protected]3ce7df0f2010-03-03 00:30:50192bool HttpNetworkTransaction::g_ignore_certificate_errors = false;
[email protected]1f14a912009-12-21 20:32:44193
[email protected]5695b8c2009-09-30 21:36:43194HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session)
[email protected]0757e7702009-03-27 04:00:22195 : pending_auth_target_(HttpAuth::AUTH_NONE),
196 ALLOW_THIS_IN_INITIALIZER_LIST(
[email protected]68bf9152008-09-25 19:47:30197 io_callback_(this, &HttpNetworkTransaction::OnIOComplete)),
initial.commit586acc5fe2008-07-26 22:42:52198 user_callback_(NULL),
199 session_(session),
200 request_(NULL),
201 pac_request_(NULL),
[email protected]1f14a912009-12-21 20:32:44202 connection_(new ClientSocketHandle),
initial.commit586acc5fe2008-07-26 22:42:52203 reused_socket_(false),
[email protected]0877e3d2009-10-17 22:29:57204 headers_valid_(false),
[email protected]8e3d2d32010-06-13 18:46:23205 logged_response_time_(false),
initial.commit586acc5fe2008-07-26 22:42:52206 using_ssl_(false),
[email protected]e0993912010-02-22 23:57:11207 using_spdy_(false),
[email protected]bdbda462010-06-28 17:30:37208 spdy_certificate_error_(OK),
[email protected]31e2c69e2010-04-15 18:06:06209 alternate_protocol_mode_(
210 g_use_alternate_protocols ? kUnspecified :
211 kDoNotUseAlternateProtocol),
initial.commit586acc5fe2008-07-26 22:42:52212 read_buf_len_(0),
[email protected]a7ea8832010-07-12 17:54:54213 next_state_(STATE_NONE),
214 establishing_tunnel_(false) {
[email protected]2cd713f2008-10-21 17:54:28215 session->ssl_config_service()->GetSSLConfig(&ssl_config_);
[email protected]1f14a912009-12-21 20:32:44216 if (g_next_protos)
217 ssl_config_.next_protos = *g_next_protos;
[email protected]aeaca1f2010-04-20 22:05:21218 if (!g_tls_intolerant_servers)
219 g_tls_intolerant_servers = new std::set<std::string>;
[email protected]1f14a912009-12-21 20:32:44220}
221
222// static
[email protected]b6a50182010-05-12 22:47:14223void HttpNetworkTransaction::SetHostMappingRules(const std::string& rules) {
224 HostMappingRules* host_mapping_rules = new HostMappingRules();
225 host_mapping_rules->SetRulesFromString(rules);
226 delete g_host_mapping_rules;
227 g_host_mapping_rules = host_mapping_rules;
228}
229
230// static
[email protected]31e2c69e2010-04-15 18:06:06231void HttpNetworkTransaction::SetUseAlternateProtocols(bool value) {
232 g_use_alternate_protocols = value;
233}
234
235// static
[email protected]1f14a912009-12-21 20:32:44236void HttpNetworkTransaction::SetNextProtos(const std::string& next_protos) {
237 delete g_next_protos;
238 g_next_protos = new std::string(next_protos);
initial.commit586acc5fe2008-07-26 22:42:52239}
240
[email protected]3ce7df0f2010-03-03 00:30:50241// static
242void HttpNetworkTransaction::IgnoreCertificateErrors(bool enabled) {
243 g_ignore_certificate_errors = enabled;
244}
245
[email protected]684970b2009-08-14 04:54:46246int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
247 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53248 const BoundNetLog& net_log) {
[email protected]5e2e6c77d12009-12-24 21:57:16249 SIMPLE_STATS_COUNTER("HttpNetworkTransaction.Count");
[email protected]5d0153c512009-01-12 19:08:36250
[email protected]9e743cd2010-03-16 07:03:53251 net_log_ = net_log;
[email protected]96d570e42008-08-05 22:43:04252 request_ = request_info;
[email protected]21b316a2009-03-23 18:25:06253 start_time_ = base::Time::Now();
[email protected]96d570e42008-08-05 22:43:04254
255 next_state_ = STATE_RESOLVE_PROXY;
256 int rv = DoLoop(OK);
257 if (rv == ERR_IO_PENDING)
258 user_callback_ = callback;
259 return rv;
260}
261
262int HttpNetworkTransaction::RestartIgnoringLastError(
263 CompletionCallback* callback) {
[email protected]e60e47a2010-07-14 03:37:18264 if (connection_->socket() && connection_->socket()->IsConnectedAndIdle()) {
[email protected]fab9ca52010-02-19 23:14:48265 // TODO(wtc): Should we update any of the connection histograms that we
266 // update in DoSSLConnectComplete if |result| is OK?
[email protected]e0993912010-02-22 23:57:11267 if (using_spdy_) {
[email protected]044de0642010-06-17 10:42:15268 // TODO(cbentzel): Add auth support to spdy. See http://crbug.com/46620
[email protected]fab9ca52010-02-19 23:14:48269 next_state_ = STATE_SPDY_SEND_REQUEST;
270 } else {
[email protected]044de0642010-06-17 10:42:15271 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
[email protected]fab9ca52010-02-19 23:14:48272 }
[email protected]bacff652009-03-31 17:50:33273 } else {
[email protected]e60e47a2010-07-14 03:37:18274 if (connection_->socket())
275 connection_->socket()->Disconnect();
[email protected]1f14a912009-12-21 20:32:44276 connection_->Reset();
[email protected]bacff652009-03-31 17:50:33277 next_state_ = STATE_INIT_CONNECTION;
278 }
[email protected]ccb40e52008-09-17 20:54:40279 int rv = DoLoop(OK);
280 if (rv == ERR_IO_PENDING)
281 user_callback_ = callback;
[email protected]aaead502008-10-15 00:20:11282 return rv;
[email protected]96d570e42008-08-05 22:43:04283}
284
[email protected]0b45559b2009-06-12 21:45:11285int HttpNetworkTransaction::RestartWithCertificate(
286 X509Certificate* client_cert,
287 CompletionCallback* callback) {
288 ssl_config_.client_cert = client_cert;
[email protected]5e363962009-06-19 19:57:01289 if (client_cert) {
290 session_->ssl_client_auth_cache()->Add(GetHostAndPort(request_->url),
291 client_cert);
292 }
[email protected]0b45559b2009-06-12 21:45:11293 ssl_config_.send_client_cert = true;
294 next_state_ = STATE_INIT_CONNECTION;
295 // Reset the other member variables.
296 // Note: this is necessary only with SSL renegotiation.
297 ResetStateForRestart();
298 int rv = DoLoop(OK);
299 if (rv == ERR_IO_PENDING)
300 user_callback_ = callback;
301 return rv;
302}
303
[email protected]96d570e42008-08-05 22:43:04304int HttpNetworkTransaction::RestartWithAuth(
305 const std::wstring& username,
306 const std::wstring& password,
307 CompletionCallback* callback) {
[email protected]0757e7702009-03-27 04:00:22308 HttpAuth::Target target = pending_auth_target_;
309 if (target == HttpAuth::AUTH_NONE) {
310 NOTREACHED();
311 return ERR_UNEXPECTED;
312 }
[email protected]0757e7702009-03-27 04:00:22313 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:42314
[email protected]e772db3f2010-07-12 18:11:13315 auth_controllers_[target]->ResetAuth(username, password);
316
[email protected]a7ea8832010-07-12 17:54:54317 if (target == HttpAuth::AUTH_PROXY && using_ssl_ && proxy_info_.is_http()) {
318 DCHECK(establishing_tunnel_);
[email protected]e60e47a2010-07-14 03:37:18319 next_state_ = STATE_INIT_CONNECTION;
[email protected]a7ea8832010-07-12 17:54:54320 ResetStateForRestart();
[email protected]a7ea8832010-07-12 17:54:54321 } else {
[email protected]a7ea8832010-07-12 17:54:54322 PrepareForAuthRestart(target);
323 }
[email protected]c3b35c22008-09-27 03:19:42324
325 DCHECK(user_callback_ == NULL);
326 int rv = DoLoop(OK);
327 if (rv == ERR_IO_PENDING)
328 user_callback_ = callback;
329
330 return rv;
[email protected]96d570e42008-08-05 22:43:04331}
332
[email protected]f9ee6b52008-11-08 06:46:23333void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) {
334 DCHECK(HaveAuth(target));
[email protected]a7ea8832010-07-12 17:54:54335 DCHECK(!establishing_tunnel_);
[email protected]2d2697f92009-02-18 21:00:32336 bool keep_alive = false;
[email protected]0877e3d2009-10-17 22:29:57337 // Even if the server says the connection is keep-alive, we have to be
338 // able to find the end of each response in order to reuse the connection.
339 if (GetResponseHeaders()->IsKeepAlive() &&
340 http_stream_->CanFindEndOfResponse()) {
341 // If the response body hasn't been completely read, we need to drain
342 // it first.
343 if (!http_stream_->IsResponseBodyComplete()) {
[email protected]2d2697f92009-02-18 21:00:32344 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
[email protected]0877e3d2009-10-17 22:29:57345 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket.
[email protected]2d2697f92009-02-18 21:00:32346 read_buf_len_ = kDrainBodyBufferSize;
347 return;
348 }
[email protected]0877e3d2009-10-17 22:29:57349 keep_alive = true;
[email protected]37832c6d2009-06-05 19:44:09350 }
351
[email protected]2d2697f92009-02-18 21:00:32352 // We don't need to drain the response body, so we act as if we had drained
353 // the response body.
354 DidDrainBodyForAuthRestart(keep_alive);
355}
356
357void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) {
[email protected]a7ea8832010-07-12 17:54:54358 DCHECK(!establishing_tunnel_);
[email protected]1f14a912009-12-21 20:32:44359 if (keep_alive && connection_->socket()->IsConnectedAndIdle()) {
360 // We should call connection_->set_idle_time(), but this doesn't occur
[email protected]11203f012009-11-12 23:02:31361 // often enough to be worth the trouble.
[email protected]a7ea8832010-07-12 17:54:54362 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
[email protected]1f14a912009-12-21 20:32:44363 connection_->set_is_reused(true);
[email protected]2d2697f92009-02-18 21:00:32364 reused_socket_ = true;
365 } else {
366 next_state_ = STATE_INIT_CONNECTION;
[email protected]1f14a912009-12-21 20:32:44367 connection_->socket()->Disconnect();
368 connection_->Reset();
[email protected]2d2697f92009-02-18 21:00:32369 }
[email protected]f9ee6b52008-11-08 06:46:23370
371 // Reset the other member variables.
372 ResetStateForRestart();
373}
374
[email protected]9dea9e1f2009-01-29 00:30:47375int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
[email protected]96d570e42008-08-05 22:43:04376 CompletionCallback* callback) {
[email protected]96d570e42008-08-05 22:43:04377 DCHECK(buf);
[email protected]e0c27be2009-07-15 13:09:35378 DCHECK_LT(0, buf_len);
[email protected]96d570e42008-08-05 22:43:04379
[email protected]1f14a912009-12-21 20:32:44380 State next_state = STATE_NONE;
[email protected]96d570e42008-08-05 22:43:04381
[email protected]8a1f3312010-05-25 19:25:04382 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
[email protected]e60e47a2010-07-14 03:37:18383 if (headers_valid_ && headers.get() && establishing_tunnel_) {
[email protected]8a1f3312010-05-25 19:25:04384 // We're trying to read the body of the response but we're still trying
385 // to establish an SSL tunnel through the proxy. We can't read these
386 // bytes when establishing a tunnel because they might be controlled by
387 // an active network attacker. We don't worry about this for HTTP
388 // because an active network attacker can already control HTTP sessions.
389 // We reach this case when the user cancels a 407 proxy auth prompt.
390 // See http://crbug.com/8473.
391 DCHECK(proxy_info_.is_http());
[email protected]a7ea8832010-07-12 17:54:54392 DCHECK_EQ(headers->response_code(), 407);
393 LOG(WARNING) << "Blocked proxy response with status "
394 << headers->response_code() << " to CONNECT request for "
395 << GetHostAndPort(request_->url) << ".";
[email protected]8a1f3312010-05-25 19:25:04396 return ERR_TUNNEL_CONNECTION_FAILED;
[email protected]a8e9b162009-03-12 00:06:44397 }
398
[email protected]e60e47a2010-07-14 03:37:18399 // Are we using SPDY or HTTP?
400 if (using_spdy_) {
401 DCHECK(!http_stream_.get());
402 DCHECK(spdy_http_stream_->GetResponseInfo()->headers);
403 next_state = STATE_SPDY_READ_BODY;
404 } else {
405 DCHECK(!spdy_http_stream_.get());
406 next_state = STATE_READ_BODY;
407
408 if (!connection_->is_initialized())
409 return 0; // |*connection_| has been reset. Treat like EOF.
410 }
411
[email protected]96d570e42008-08-05 22:43:04412 read_buf_ = buf;
413 read_buf_len_ = buf_len;
414
[email protected]1f14a912009-12-21 20:32:44415 next_state_ = next_state;
[email protected]96d570e42008-08-05 22:43:04416 int rv = DoLoop(OK);
417 if (rv == ERR_IO_PENDING)
418 user_callback_ = callback;
419 return rv;
420}
421
422const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const {
[email protected]a7e41312009-12-16 23:18:14423 return ((headers_valid_ && response_.headers) || response_.ssl_info.cert ||
424 response_.cert_request_info) ? &response_ : NULL;
[email protected]96d570e42008-08-05 22:43:04425}
426
427LoadState HttpNetworkTransaction::GetLoadState() const {
428 // TODO(wtc): Define a new LoadState value for the
429 // STATE_INIT_CONNECTION_COMPLETE state, which delays the HTTP request.
430 switch (next_state_) {
431 case STATE_RESOLVE_PROXY_COMPLETE:
432 return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
[email protected]d207a5f2009-06-04 05:28:40433 case STATE_INIT_CONNECTION_COMPLETE:
[email protected]1f14a912009-12-21 20:32:44434 return connection_->GetLoadState();
[email protected]375e3112010-05-27 20:32:06435 case STATE_SSL_CONNECT_COMPLETE:
436 return LOAD_STATE_SSL_HANDSHAKE;
[email protected]044de0642010-06-17 10:42:15437 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
438 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
[email protected]0877e3d2009-10-17 22:29:57439 case STATE_SEND_REQUEST_COMPLETE:
[email protected]375e3112010-05-27 20:32:06440 case STATE_SPDY_SEND_REQUEST_COMPLETE:
[email protected]96d570e42008-08-05 22:43:04441 return LOAD_STATE_SENDING_REQUEST;
442 case STATE_READ_HEADERS_COMPLETE:
[email protected]375e3112010-05-27 20:32:06443 case STATE_SPDY_READ_HEADERS_COMPLETE:
[email protected]96d570e42008-08-05 22:43:04444 return LOAD_STATE_WAITING_FOR_RESPONSE;
445 case STATE_READ_BODY_COMPLETE:
[email protected]375e3112010-05-27 20:32:06446 case STATE_SPDY_READ_BODY_COMPLETE:
[email protected]96d570e42008-08-05 22:43:04447 return LOAD_STATE_READING_RESPONSE;
448 default:
449 return LOAD_STATE_IDLE;
450 }
451}
452
453uint64 HttpNetworkTransaction::GetUploadProgress() const {
[email protected]0877e3d2009-10-17 22:29:57454 if (!http_stream_.get())
[email protected]96d570e42008-08-05 22:43:04455 return 0;
456
[email protected]0877e3d2009-10-17 22:29:57457 return http_stream_->GetUploadProgress();
[email protected]96d570e42008-08-05 22:43:04458}
459
initial.commit586acc5fe2008-07-26 22:42:52460HttpNetworkTransaction::~HttpNetworkTransaction() {
[email protected]92d9cad2009-06-25 23:40:24461 // If we still have an open socket, then make sure to disconnect it so it
[email protected]fc31d6a42010-06-24 18:05:13462 // won't call us back and we don't try to reuse it later on. However,
463 // don't close the socket if we should keep the connection alive.
464 if (connection_.get() && connection_->is_initialized()) {
465 // The STATE_NONE check guarantees there are no pending socket IOs that
466 // could try to call this object back after it is deleted.
467 bool keep_alive = next_state_ == STATE_NONE &&
468 http_stream_.get() &&
469 http_stream_->IsResponseBodyComplete() &&
470 http_stream_->CanFindEndOfResponse() &&
471 GetResponseHeaders()->IsKeepAlive();
472 if (!keep_alive)
473 connection_->socket()->Disconnect();
474 }
initial.commit586acc5fe2008-07-26 22:42:52475
476 if (pac_request_)
477 session_->proxy_service()->CancelPacRequest(pac_request_);
[email protected]1f14a912009-12-21 20:32:44478
[email protected]9be804c82010-06-24 17:59:46479 if (spdy_http_stream_.get())
480 spdy_http_stream_->Cancel();
initial.commit586acc5fe2008-07-26 22:42:52481}
482
initial.commit586acc5fe2008-07-26 22:42:52483void HttpNetworkTransaction::DoCallback(int rv) {
484 DCHECK(rv != ERR_IO_PENDING);
485 DCHECK(user_callback_);
486
[email protected]96d570e42008-08-05 22:43:04487 // Since Run may result in Read being called, clear user_callback_ up front.
initial.commit586acc5fe2008-07-26 22:42:52488 CompletionCallback* c = user_callback_;
489 user_callback_ = NULL;
490 c->Run(rv);
491}
492
493void HttpNetworkTransaction::OnIOComplete(int result) {
494 int rv = DoLoop(result);
495 if (rv != ERR_IO_PENDING)
496 DoCallback(rv);
497}
498
499int HttpNetworkTransaction::DoLoop(int result) {
500 DCHECK(next_state_ != STATE_NONE);
501
502 int rv = result;
503 do {
504 State state = next_state_;
505 next_state_ = STATE_NONE;
506 switch (state) {
507 case STATE_RESOLVE_PROXY:
[email protected]725355a2009-03-25 20:42:55508 DCHECK_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52509 rv = DoResolveProxy();
510 break;
511 case STATE_RESOLVE_PROXY_COMPLETE:
512 rv = DoResolveProxyComplete(rv);
513 break;
514 case STATE_INIT_CONNECTION:
[email protected]725355a2009-03-25 20:42:55515 DCHECK_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52516 rv = DoInitConnection();
517 break;
518 case STATE_INIT_CONNECTION_COMPLETE:
519 rv = DoInitConnectionComplete(rv);
520 break;
[email protected]044de0642010-06-17 10:42:15521 case STATE_GENERATE_PROXY_AUTH_TOKEN:
522 DCHECK_EQ(OK, rv);
523 rv = DoGenerateProxyAuthToken();
524 break;
525 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
526 rv = DoGenerateProxyAuthTokenComplete(rv);
527 break;
528 case STATE_GENERATE_SERVER_AUTH_TOKEN:
529 DCHECK_EQ(OK, rv);
530 rv = DoGenerateServerAuthToken();
531 break;
532 case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
533 rv = DoGenerateServerAuthTokenComplete(rv);
534 break;
[email protected]0877e3d2009-10-17 22:29:57535 case STATE_SEND_REQUEST:
[email protected]725355a2009-03-25 20:42:55536 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09537 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, NULL);
[email protected]0877e3d2009-10-17 22:29:57538 rv = DoSendRequest();
initial.commit586acc5fe2008-07-26 22:42:52539 break;
[email protected]0877e3d2009-10-17 22:29:57540 case STATE_SEND_REQUEST_COMPLETE:
541 rv = DoSendRequestComplete(rv);
[email protected]ec11be62010-04-28 19:28:09542 net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, NULL);
initial.commit586acc5fe2008-07-26 22:42:52543 break;
544 case STATE_READ_HEADERS:
[email protected]725355a2009-03-25 20:42:55545 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09546 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, NULL);
initial.commit586acc5fe2008-07-26 22:42:52547 rv = DoReadHeaders();
548 break;
549 case STATE_READ_HEADERS_COMPLETE:
550 rv = DoReadHeadersComplete(rv);
[email protected]ec11be62010-04-28 19:28:09551 net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, NULL);
initial.commit586acc5fe2008-07-26 22:42:52552 break;
553 case STATE_READ_BODY:
[email protected]725355a2009-03-25 20:42:55554 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09555 net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, NULL);
initial.commit586acc5fe2008-07-26 22:42:52556 rv = DoReadBody();
557 break;
558 case STATE_READ_BODY_COMPLETE:
559 rv = DoReadBodyComplete(rv);
[email protected]ec11be62010-04-28 19:28:09560 net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, NULL);
initial.commit586acc5fe2008-07-26 22:42:52561 break;
[email protected]2d2697f92009-02-18 21:00:32562 case STATE_DRAIN_BODY_FOR_AUTH_RESTART:
[email protected]725355a2009-03-25 20:42:55563 DCHECK_EQ(OK, rv);
[email protected]9e743cd2010-03-16 07:03:53564 net_log_.BeginEvent(
[email protected]ec11be62010-04-28 19:28:09565 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, NULL);
[email protected]2d2697f92009-02-18 21:00:32566 rv = DoDrainBodyForAuthRestart();
567 break;
568 case STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE:
569 rv = DoDrainBodyForAuthRestartComplete(rv);
[email protected]9e743cd2010-03-16 07:03:53570 net_log_.EndEvent(
[email protected]ec11be62010-04-28 19:28:09571 NetLog::TYPE_HTTP_TRANSACTION_DRAIN_BODY_FOR_AUTH_RESTART, NULL);
[email protected]2d2697f92009-02-18 21:00:32572 break;
[email protected]1f14a912009-12-21 20:32:44573 case STATE_SPDY_SEND_REQUEST:
574 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09575 net_log_.BeginEvent(NetLog::TYPE_SPDY_TRANSACTION_SEND_REQUEST, NULL);
[email protected]1f14a912009-12-21 20:32:44576 rv = DoSpdySendRequest();
577 break;
578 case STATE_SPDY_SEND_REQUEST_COMPLETE:
579 rv = DoSpdySendRequestComplete(rv);
[email protected]ec11be62010-04-28 19:28:09580 net_log_.EndEvent(NetLog::TYPE_SPDY_TRANSACTION_SEND_REQUEST, NULL);
[email protected]1f14a912009-12-21 20:32:44581 break;
582 case STATE_SPDY_READ_HEADERS:
583 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09584 net_log_.BeginEvent(NetLog::TYPE_SPDY_TRANSACTION_READ_HEADERS, NULL);
[email protected]1f14a912009-12-21 20:32:44585 rv = DoSpdyReadHeaders();
586 break;
587 case STATE_SPDY_READ_HEADERS_COMPLETE:
588 rv = DoSpdyReadHeadersComplete(rv);
[email protected]ec11be62010-04-28 19:28:09589 net_log_.EndEvent(NetLog::TYPE_SPDY_TRANSACTION_READ_HEADERS, NULL);
[email protected]1f14a912009-12-21 20:32:44590 break;
591 case STATE_SPDY_READ_BODY:
592 DCHECK_EQ(OK, rv);
[email protected]ec11be62010-04-28 19:28:09593 net_log_.BeginEvent(NetLog::TYPE_SPDY_TRANSACTION_READ_BODY, NULL);
[email protected]1f14a912009-12-21 20:32:44594 rv = DoSpdyReadBody();
595 break;
596 case STATE_SPDY_READ_BODY_COMPLETE:
597 rv = DoSpdyReadBodyComplete(rv);
[email protected]ec11be62010-04-28 19:28:09598 net_log_.EndEvent(NetLog::TYPE_SPDY_TRANSACTION_READ_BODY, NULL);
[email protected]1f14a912009-12-21 20:32:44599 break;
initial.commit586acc5fe2008-07-26 22:42:52600 default:
601 NOTREACHED() << "bad state";
602 rv = ERR_FAILED;
[email protected]96d570e42008-08-05 22:43:04603 break;
initial.commit586acc5fe2008-07-26 22:42:52604 }
605 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
606
607 return rv;
608}
609
610int HttpNetworkTransaction::DoResolveProxy() {
611 DCHECK(!pac_request_);
612
613 next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
614
[email protected]631f1322010-04-30 17:59:11615 // |endpoint_| indicates the final destination endpoint.
616 endpoint_ = HostPortPair(request_->url.HostNoBrackets(),
617 request_->url.EffectiveIntPort());
618
[email protected]28ed3b42010-05-13 19:39:56619 // Extra URL we might be attempting to resolve to.
620 GURL alternate_endpoint_url;
[email protected]b6a50182010-05-12 22:47:14621
[email protected]28ed3b42010-05-13 19:39:56622 // Tracks whether we are using |request_->url| or |alternate_endpoint_url|.
623 const GURL *curr_endpoint_url = &request_->url;
624
625 if (g_host_mapping_rules && g_host_mapping_rules->RewriteHost(&endpoint_)) {
626 url_canon::Replacements<char> replacements;
627 const std::string port_str = IntToString(endpoint_.port);
628 replacements.SetPort(port_str.c_str(),
629 url_parse::Component(0, port_str.size()));
630 replacements.SetHost(endpoint_.host.c_str(),
631 url_parse::Component(0, endpoint_.host.size()));
632 alternate_endpoint_url = curr_endpoint_url->ReplaceComponents(replacements);
633 curr_endpoint_url = &alternate_endpoint_url;
634 }
[email protected]631f1322010-04-30 17:59:11635
[email protected]193b0b892010-06-26 03:57:57636 const HttpAlternateProtocols& alternate_protocols =
637 session_->alternate_protocols();
638 if (alternate_protocols.HasAlternateProtocolFor(endpoint_)) {
639 response_.was_alternate_protocol_available = true;
640 if (alternate_protocol_mode_ == kUnspecified) {
[email protected]631f1322010-04-30 17:59:11641 HttpAlternateProtocols::PortProtocolPair alternate =
642 alternate_protocols.GetAlternateProtocolFor(endpoint_);
643 if (alternate.protocol != HttpAlternateProtocols::BROKEN) {
644 DCHECK_EQ(HttpAlternateProtocols::NPN_SPDY_1, alternate.protocol);
645 endpoint_.port = alternate.port;
646 alternate_protocol_ = HttpAlternateProtocols::NPN_SPDY_1;
647 alternate_protocol_mode_ = kUsingAlternateProtocol;
648
649 url_canon::Replacements<char> replacements;
650 replacements.SetScheme("https",
651 url_parse::Component(0, strlen("https")));
652 const std::string port_str = IntToString(endpoint_.port);
653 replacements.SetPort(port_str.c_str(),
654 url_parse::Component(0, port_str.size()));
[email protected]28ed3b42010-05-13 19:39:56655 alternate_endpoint_url =
656 curr_endpoint_url->ReplaceComponents(replacements);
657 curr_endpoint_url = &alternate_endpoint_url;
[email protected]631f1322010-04-30 17:59:11658 }
659 }
660 }
661
[email protected]677c90572008-12-10 09:03:15662 if (request_->load_flags & LOAD_BYPASS_PROXY) {
663 proxy_info_.UseDirect();
664 return OK;
665 }
666
initial.commit586acc5fe2008-07-26 22:42:52667 return session_->proxy_service()->ResolveProxy(
[email protected]28ed3b42010-05-13 19:39:56668 *curr_endpoint_url, &proxy_info_, &io_callback_, &pac_request_, net_log_);
initial.commit586acc5fe2008-07-26 22:42:52669}
670
671int HttpNetworkTransaction::DoResolveProxyComplete(int result) {
[email protected]69719062010-01-05 20:09:21672 pac_request_ = NULL;
initial.commit586acc5fe2008-07-26 22:42:52673
[email protected]dded3e22010-02-05 04:08:37674 if (result != OK)
675 return result;
[email protected]59a16012010-01-29 23:45:29676
[email protected]e0c27be2009-07-15 13:09:35677 // Remove unsupported proxies from the list.
[email protected]f6fb2de2009-02-19 08:11:42678 proxy_info_.RemoveProxiesWithoutScheme(
[email protected]3cd17242009-06-23 02:59:02679 ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_HTTP |
[email protected]e0c27be2009-07-15 13:09:35680 ProxyServer::SCHEME_SOCKS4 | ProxyServer::SCHEME_SOCKS5);
[email protected]f6fb2de2009-02-19 08:11:42681
[email protected]69719062010-01-05 20:09:21682 if (proxy_info_.is_empty()) {
[email protected]02cf5a42010-01-12 22:10:25683 // No proxies/direct to choose from. This happens when we don't support any
684 // of the proxies in the returned list.
685 return ERR_NO_SUPPORTED_PROXIES;
[email protected]69719062010-01-05 20:09:21686 }
initial.commit586acc5fe2008-07-26 22:42:52687
[email protected]69719062010-01-05 20:09:21688 next_state_ = STATE_INIT_CONNECTION;
initial.commit586acc5fe2008-07-26 22:42:52689 return OK;
690}
691
692int HttpNetworkTransaction::DoInitConnection() {
[email protected]1f14a912009-12-21 20:32:44693 DCHECK(!connection_->is_initialized());
[email protected]69719062010-01-05 20:09:21694 DCHECK(proxy_info_.proxy_server().is_valid());
[email protected]e60e47a2010-07-14 03:37:18695 next_state_ = STATE_INIT_CONNECTION_COMPLETE;
initial.commit586acc5fe2008-07-26 22:42:52696
[email protected]228404f2010-06-24 04:31:41697 // Now that the proxy server has been resolved, create the auth_controllers_.
698 for (int i = 0; i < HttpAuth::AUTH_NUM_TARGETS; i++) {
699 HttpAuth::Target target = static_cast<HttpAuth::Target>(i);
700 if (!auth_controllers_[target].get())
[email protected]e772db3f2010-07-12 18:11:13701 auth_controllers_[target] = new HttpAuthController(target,
702 AuthURL(target),
[email protected]560c0432010-07-13 20:45:31703 session_);
[email protected]228404f2010-06-24 04:31:41704 }
705
[email protected]e60e47a2010-07-14 03:37:18706 bool want_spdy = alternate_protocol_mode_ == kUsingAlternateProtocol
707 && alternate_protocol_ == HttpAlternateProtocols::NPN_SPDY_1;
708 using_ssl_ = request_->url.SchemeIs("https") || want_spdy;
[email protected]e0993912010-02-22 23:57:11709 using_spdy_ = false;
[email protected]e60e47a2010-07-14 03:37:18710 response_.was_fetched_via_proxy = !proxy_info_.is_direct();
[email protected]2ff8b312010-04-26 22:20:54711
[email protected]85c0ed82009-12-15 23:14:14712 // Use the fixed testing ports if they've been provided.
713 if (using_ssl_) {
714 if (session_->fixed_https_port() != 0)
[email protected]2d731a32010-04-29 01:04:06715 endpoint_.port = session_->fixed_https_port();
[email protected]85c0ed82009-12-15 23:14:14716 } else if (session_->fixed_http_port() != 0) {
[email protected]2d731a32010-04-29 01:04:06717 endpoint_.port = session_->fixed_http_port();
[email protected]85c0ed82009-12-15 23:14:14718 }
719
[email protected]7fc5b09a2010-02-27 00:07:38720 // Check first if we have a spdy session for this group. If so, then go
721 // straight to using that.
[email protected]2d731a32010-04-29 01:04:06722 if (session_->spdy_session_pool()->HasSession(endpoint_)) {
[email protected]7fc5b09a2010-02-27 00:07:38723 using_spdy_ = true;
[email protected]8e3d2d32010-06-13 18:46:23724 reused_socket_ = true;
[email protected]e60e47a2010-07-14 03:37:18725 next_state_ = STATE_SPDY_SEND_REQUEST;
[email protected]7fc5b09a2010-02-27 00:07:38726 return OK;
727 }
728
[email protected]e60e47a2010-07-14 03:37:18729 // Build the string used to uniquely identify connections of this type.
730 // Determine the host and port to connect to.
731 std::string connection_group = endpoint_.ToString();
[email protected]a0ef3762009-12-22 02:09:45732 DCHECK(!connection_group.empty());
[email protected]2884a462009-06-15 05:08:42733
[email protected]0e88ad602010-05-04 23:47:02734 if (using_ssl_)
735 connection_group = StringPrintf("ssl/%s", connection_group.c_str());
736
[email protected]2884a462009-06-15 05:08:42737 // If the user is refreshing the page, bypass the host cache.
[email protected]7fc5b09a2010-02-27 00:07:38738 bool disable_resolver_cache = request_->load_flags & LOAD_BYPASS_CACHE ||
[email protected]685af592010-05-11 19:31:24739 request_->load_flags & LOAD_VALIDATE_CACHE ||
[email protected]2227c692010-05-04 15:36:11740 request_->load_flags & LOAD_DISABLE_CACHE;
[email protected]2884a462009-06-15 05:08:42741
[email protected]e60e47a2010-07-14 03:37:18742 // Build up the connection parameters.
743 scoped_refptr<TCPSocketParams> tcp_params;
744 scoped_refptr<HttpProxySocketParams> http_proxy_params;
745 scoped_refptr<SOCKSSocketParams> socks_params;
746 scoped_ptr<HostPortPair> proxy_host_port;
[email protected]2d731a32010-04-29 01:04:06747
[email protected]e60e47a2010-07-14 03:37:18748 if (proxy_info_.is_direct()) {
749 tcp_params = new TCPSocketParams(endpoint_, request_->priority,
750 request_->referrer,
751 disable_resolver_cache);
752 } else {
753 ProxyServer proxy_server = proxy_info_.proxy_server();
754 proxy_host_port.reset(new HostPortPair(proxy_server.HostNoBrackets(),
755 proxy_server.port()));
756 scoped_refptr<TCPSocketParams> proxy_tcp_params =
757 new TCPSocketParams(*proxy_host_port, request_->priority,
[email protected]df4b4ef2010-07-12 18:25:21758 request_->referrer, disable_resolver_cache);
[email protected]2d731a32010-04-29 01:04:06759
[email protected]e60e47a2010-07-14 03:37:18760 if (proxy_info_.is_http()) {
[email protected]e772db3f2010-07-12 18:11:13761 scoped_refptr<HttpAuthController> http_proxy_auth;
762 if (using_ssl_) {
763 http_proxy_auth = auth_controllers_[HttpAuth::AUTH_PROXY];
764 establishing_tunnel_ = true;
765 }
[email protected]e60e47a2010-07-14 03:37:18766 http_proxy_params = new HttpProxySocketParams(proxy_tcp_params,
767 request_->url, endpoint_,
768 http_proxy_auth,
769 using_ssl_);
770 } else {
771 DCHECK(proxy_info_.is_socks());
772 char socks_version;
773 if (proxy_server.scheme() == ProxyServer::SCHEME_SOCKS5)
774 socks_version = '5';
775 else
776 socks_version = '4';
777 connection_group =
778 StringPrintf("socks%c/%s", socks_version, connection_group.c_str());
[email protected]e772db3f2010-07-12 18:11:13779
[email protected]e60e47a2010-07-14 03:37:18780 socks_params = new SOCKSSocketParams(proxy_tcp_params,
781 socks_version == '5',
782 endpoint_,
783 request_->priority,
784 request_->referrer);
[email protected]2d731a32010-04-29 01:04:06785 }
[email protected]a796bcec2010-03-22 17:17:26786 }
787
[email protected]e60e47a2010-07-14 03:37:18788 // Deal with SSL - which layers on top of any given proxy.
789 if (using_ssl_) {
790 if (ContainsKey(*g_tls_intolerant_servers, GetHostAndPort(request_->url))) {
791 LOG(WARNING) << "Falling back to SSLv3 because host is TLS intolerant: "
792 << GetHostAndPort(request_->url);
793 ssl_config_.ssl3_fallback = true;
794 ssl_config_.tls1_enabled = false;
795 }
796
797 UMA_HISTOGRAM_ENUMERATION("Net.ConnectionUsedSSLv3Fallback",
798 (int) ssl_config_.ssl3_fallback, 2);
799
800 int load_flags = request_->load_flags;
801 if (g_ignore_certificate_errors)
802 load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS;
803 if (request_->load_flags & LOAD_VERIFY_EV_CERT)
804 ssl_config_.verify_ev_cert = true;
805
806 scoped_refptr<SSLSocketParams> ssl_params =
807 new SSLSocketParams(tcp_params, http_proxy_params, socks_params,
808 proxy_info_.proxy_server().scheme(),
809 request_->url.HostNoBrackets(), ssl_config_,
810 load_flags, want_spdy);
811
812 scoped_refptr<SSLClientSocketPool> ssl_pool;
813 if (proxy_info_.is_direct())
814 ssl_pool = session_->ssl_socket_pool();
815 else
816 ssl_pool = session_->GetSocketPoolForSSLWithProxy(*proxy_host_port);
817
818 return connection_->Init(connection_group, ssl_params, request_->priority,
819 &io_callback_, ssl_pool, net_log_);
820 }
821
822 // Finally, get the connection started.
823 if (proxy_info_.is_http()) {
824 return connection_->Init(
825 connection_group, http_proxy_params, request_->priority, &io_callback_,
826 session_->GetSocketPoolForHTTPProxy(*proxy_host_port), net_log_);
827 }
828
829 if (proxy_info_.is_socks()) {
830 return connection_->Init(
831 connection_group, socks_params, request_->priority, &io_callback_,
832 session_->GetSocketPoolForSOCKSProxy(*proxy_host_port), net_log_);
833 }
834
835 DCHECK(proxy_info_.is_direct());
836 return connection_->Init(connection_group, tcp_params, request_->priority,
837 &io_callback_, session_->tcp_socket_pool(),
838 net_log_);
initial.commit586acc5fe2008-07-26 22:42:52839}
840
841int HttpNetworkTransaction::DoInitConnectionComplete(int result) {
[email protected]e60e47a2010-07-14 03:37:18842 // |result| may be the result of any of the stacked pools. The following
843 // logic is used when determining how to interpret an error.
844 // If |result| < 0:
845 // and connection_->socket() != NULL, then the SSL handshake ran and it
846 // is a potentially recoverable error.
847 // and connection_->socket == NULL and connection_->is_ssl_error() is true,
848 // then the SSL handshake ran with an unrecoverable error.
849 // otherwise, the error came from one of the other pools.
850 bool ssl_started = using_ssl_ && (result == OK || connection_->socket() ||
851 connection_->is_ssl_error());
852
853 if (ssl_started && (result == OK || IsCertificateError(result))) {
854 SSLClientSocket* ssl_socket =
855 static_cast<SSLClientSocket*>(connection_->socket());
856 if (ssl_socket->wasNpnNegotiated()) {
857 response_.was_npn_negotiated = true;
858 std::string proto;
859 ssl_socket->GetNextProto(&proto);
860 if (SSLClientSocket::NextProtoFromString(proto) ==
861 SSLClientSocket::kProtoSPDY1)
862 using_spdy_ = true;
[email protected]e772db3f2010-07-12 18:11:13863 }
[email protected]564b4912010-03-09 16:30:42864 }
initial.commit586acc5fe2008-07-26 22:42:52865
[email protected]e60e47a2010-07-14 03:37:18866 if (result == ERR_PROXY_AUTH_REQUESTED) {
867 DCHECK(!ssl_started);
868 const HttpResponseInfo& tunnel_auth_response =
[email protected]8b498692010-07-16 17:11:43869 connection_->ssl_error_response_info();
initial.commit586acc5fe2008-07-26 22:42:52870
[email protected]e60e47a2010-07-14 03:37:18871 response_.headers = tunnel_auth_response.headers;
872 response_.auth_challenge = tunnel_auth_response.auth_challenge;
873 headers_valid_ = true;
874 pending_auth_target_ = HttpAuth::AUTH_PROXY;
[email protected]1f14a912009-12-21 20:32:44875 return OK;
876 }
877
[email protected]e60e47a2010-07-14 03:37:18878 if ((!ssl_started && result < 0 &&
879 alternate_protocol_mode_ == kUsingAlternateProtocol) ||
880 result == ERR_NPN_NEGOTIATION_FAILED) {
881 // Mark the alternate protocol as broken and fallback.
[email protected]a2cb8122010-03-10 17:22:42882 MarkBrokenAlternateProtocolAndFallback();
883 return OK;
884 }
885
[email protected]e60e47a2010-07-14 03:37:18886 if (result < 0 && !ssl_started)
887 return ReconsiderProxyAfterError(result);
888 establishing_tunnel_ = false;
889
890 if (connection_->socket()) {
891 LogHttpConnectedMetrics(*connection_);
892
893 // Set the reused_socket_ flag to indicate that we are using a keep-alive
894 // connection. This flag is used to handle errors that occur while we are
895 // trying to reuse a keep-alive connection.
896 reused_socket_ = connection_->is_reused();
897 // TODO(vandebo) should we exclude SPDY in the following if?
898 if (!reused_socket_)
899 UpdateConnectionTypeHistograms(CONNECTION_HTTP);
900
901 if (!using_ssl_) {
902 DCHECK_EQ(OK, result);
903 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
904 return result;
905 }
906 }
907
908 // Handle SSL errors below.
909 DCHECK(using_ssl_);
910 DCHECK(ssl_started);
[email protected]1f14a912009-12-21 20:32:44911 if (IsCertificateError(result)) {
[email protected]bdbda462010-06-28 17:30:37912 if (using_spdy_ && request_->url.SchemeIs("http")) {
913 // We ignore certificate errors for http over spdy.
914 spdy_certificate_error_ = result;
915 result = OK;
916 } else {
917 result = HandleCertificateError(result);
918 if (result == OK && !connection_->socket()->IsConnectedAndIdle()) {
919 connection_->socket()->Disconnect();
920 connection_->Reset();
921 next_state_ = STATE_INIT_CONNECTION;
922 return result;
923 }
[email protected]1f14a912009-12-21 20:32:44924 }
925 }
[email protected]771d0c2b2008-09-30 00:26:17926
[email protected]8b498692010-07-16 17:11:43927 if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
928 response_.cert_request_info =
929 connection_->ssl_error_response_info().cert_request_info;
[email protected]e60e47a2010-07-14 03:37:18930 return HandleCertificateRequest(result);
[email protected]8b498692010-07-16 17:11:43931 }
[email protected]e60e47a2010-07-14 03:37:18932 if (result < 0)
933 return HandleSSLHandshakeError(result);
[email protected]b7b76782009-09-11 00:31:43934
[email protected]e60e47a2010-07-14 03:37:18935 if (using_spdy_) {
936 UpdateConnectionTypeHistograms(CONNECTION_SPDY);
937 // TODO(cbentzel): Add auth support to spdy. See http://crbug.com/46620
938 next_state_ = STATE_SPDY_SEND_REQUEST;
[email protected]5a179bcc2008-10-13 18:10:59939 } else {
[email protected]e60e47a2010-07-14 03:37:18940 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
[email protected]c5949a32008-10-08 17:28:23941 }
[email protected]e60e47a2010-07-14 03:37:18942 return OK;
initial.commit586acc5fe2008-07-26 22:42:52943}
944
[email protected]044de0642010-06-17 10:42:15945int HttpNetworkTransaction::DoGenerateProxyAuthToken() {
946 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE;
947 if (!ShouldApplyProxyAuth())
948 return OK;
[email protected]228404f2010-06-24 04:31:41949 return auth_controllers_[HttpAuth::AUTH_PROXY]->MaybeGenerateAuthToken(
[email protected]560c0432010-07-13 20:45:31950 request_, &io_callback_, net_log_);
[email protected]044de0642010-06-17 10:42:15951}
952
953int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) {
954 DCHECK_NE(ERR_IO_PENDING, rv);
955 if (rv == OK)
956 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN;
957 return rv;
958}
959
960int HttpNetworkTransaction::DoGenerateServerAuthToken() {
961 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE;
962 if (!ShouldApplyServerAuth())
963 return OK;
[email protected]228404f2010-06-24 04:31:41964 return auth_controllers_[HttpAuth::AUTH_SERVER]->MaybeGenerateAuthToken(
[email protected]560c0432010-07-13 20:45:31965 request_, &io_callback_, net_log_);
[email protected]044de0642010-06-17 10:42:15966}
967
968int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) {
969 DCHECK_NE(ERR_IO_PENDING, rv);
970 if (rv == OK)
971 next_state_ = STATE_SEND_REQUEST;
972 return rv;
973}
974
[email protected]0877e3d2009-10-17 22:29:57975int HttpNetworkTransaction::DoSendRequest() {
976 next_state_ = STATE_SEND_REQUEST_COMPLETE;
977
978 UploadDataStream* request_body = NULL;
[email protected]8a1f3312010-05-25 19:25:04979 if (request_->upload_data) {
[email protected]7a6db4022010-03-24 23:37:50980 int error_code;
981 request_body = UploadDataStream::Create(request_->upload_data, &error_code);
982 if (!request_body)
983 return error_code;
984 }
initial.commit586acc5fe2008-07-26 22:42:52985
986 // This is constructed lazily (instead of within our Start method), so that
987 // we have proxy info available.
[email protected]0877e3d2009-10-17 22:29:57988 if (request_headers_.empty()) {
[email protected]1c773ea12009-04-28 19:58:42989 // Figure out if we can/should add Proxy-Authentication & Authentication
990 // headers.
[email protected]270c6412010-03-29 22:02:47991 HttpRequestHeaders authorization_headers;
[email protected]044de0642010-06-17 10:42:15992 bool have_proxy_auth = (ShouldApplyProxyAuth() &&
993 HaveAuth(HttpAuth::AUTH_PROXY));
994 bool have_server_auth = (ShouldApplyServerAuth() &&
995 HaveAuth(HttpAuth::AUTH_SERVER));
[email protected]1c773ea12009-04-28 19:58:42996 if (have_proxy_auth)
[email protected]228404f2010-06-24 04:31:41997 auth_controllers_[HttpAuth::AUTH_PROXY]->AddAuthorizationHeader(
998 &authorization_headers);
[email protected]1c773ea12009-04-28 19:58:42999 if (have_server_auth)
[email protected]228404f2010-06-24 04:31:411000 auth_controllers_[HttpAuth::AUTH_SERVER]->AddAuthorizationHeader(
1001 &authorization_headers);
[email protected]044de0642010-06-17 10:42:151002 std::string request_line;
1003 HttpRequestHeaders request_headers;
[email protected]8a1f3312010-05-25 19:25:041004 BuildRequestHeaders(request_, authorization_headers, request_body,
1005 !using_ssl_ && proxy_info_.is_http(), &request_line,
1006 &request_headers);
[email protected]ac039522010-06-15 16:39:441007
1008 if (session_->network_delegate())
1009 session_->network_delegate()->OnSendHttpRequest(&request_headers);
1010
[email protected]8a1f3312010-05-25 19:25:041011 if (net_log_.HasListener()) {
1012 net_log_.AddEvent(
1013 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]a7ea8832010-07-12 17:54:541014 new NetLogHttpRequestParameter(request_line, request_headers));
[email protected]6b9833e2008-09-10 20:32:251015 }
[email protected]ac039522010-06-15 16:39:441016
[email protected]8c76ae22010-04-20 22:15:431017 request_headers_ = request_line + request_headers.ToString();
[email protected]6b9833e2008-09-10 20:32:251018 }
initial.commit586acc5fe2008-07-26 22:42:521019
[email protected]1f14a912009-12-21 20:32:441020 headers_valid_ = false;
[email protected]9e743cd2010-03-16 07:03:531021 http_stream_.reset(new HttpBasicStream(connection_.get(), net_log_));
[email protected]1f14a912009-12-21 20:32:441022
[email protected]a7e41312009-12-16 23:18:141023 return http_stream_->SendRequest(request_, request_headers_,
1024 request_body, &response_, &io_callback_);
initial.commit586acc5fe2008-07-26 22:42:521025}
1026
[email protected]0877e3d2009-10-17 22:29:571027int HttpNetworkTransaction::DoSendRequestComplete(int result) {
initial.commit586acc5fe2008-07-26 22:42:521028 if (result < 0)
1029 return HandleIOError(result);
[email protected]0877e3d2009-10-17 22:29:571030 next_state_ = STATE_READ_HEADERS;
initial.commit586acc5fe2008-07-26 22:42:521031 return OK;
1032}
1033
1034int HttpNetworkTransaction::DoReadHeaders() {
1035 next_state_ = STATE_READ_HEADERS_COMPLETE;
[email protected]0877e3d2009-10-17 22:29:571036 return http_stream_->ReadResponseHeaders(&io_callback_);
initial.commit586acc5fe2008-07-26 22:42:521037}
1038
[email protected]0e75a732008-10-16 20:36:091039int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() {
[email protected]a7e41312009-12-16 23:18:141040 if (!response_.headers) {
[email protected]0e75a732008-10-16 20:36:091041 // The connection was closed before any data was sent. Likely an error
1042 // rather than empty HTTP/0.9 response.
[email protected]aecfbf22008-10-16 02:02:471043 return ERR_EMPTY_RESPONSE;
1044 }
1045
[email protected]aecfbf22008-10-16 02:02:471046 return OK;
1047}
1048
initial.commit586acc5fe2008-07-26 22:42:521049int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
[email protected]0b45559b2009-06-12 21:45:111050 // We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here
1051 // due to SSL renegotiation.
1052 if (using_ssl_) {
1053 if (IsCertificateError(result)) {
1054 // We don't handle a certificate error during SSL renegotiation, so we
1055 // have to return an error that's not in the certificate error range
1056 // (-2xx).
1057 LOG(ERROR) << "Got a server certificate with error " << result
1058 << " during SSL renegotiation";
1059 result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION;
1060 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
[email protected]8b498692010-07-16 17:11:431061 response_.cert_request_info = new SSLCertRequestInfo;
1062 SSLClientSocket* ssl_socket =
1063 static_cast<SSLClientSocket*>(connection_->socket());
1064 ssl_socket->GetSSLCertRequestInfo(response_.cert_request_info);
[email protected]5e363962009-06-19 19:57:011065 result = HandleCertificateRequest(result);
1066 if (result == OK)
1067 return result;
[email protected]0ed94682010-05-18 15:09:001068 } else if ((result == ERR_SSL_DECOMPRESSION_FAILURE_ALERT ||
[email protected]65041fa2010-05-21 06:56:531069 result == ERR_SSL_BAD_RECORD_MAC_ALERT) &&
[email protected]d102f542010-06-30 14:51:051070 ssl_config_.tls1_enabled &&
1071 !SSLConfigService::IsKnownStrictTLSServer(request_->url.host())){
[email protected]aeaca1f2010-04-20 22:05:211072 // Some buggy servers select DEFLATE compression when offered and then
1073 // fail to ever decompress anything. They will send a fatal alert telling
1074 // us this. Normally we would pick this up during the handshake because
1075 // our Finished message is compressed and we'll never get the server's
1076 // Finished if it fails to process ours.
1077 //
1078 // However, with False Start, we'll believe that the handshake is
1079 // complete as soon as we've /sent/ our Finished message. In this case,
1080 // we only find out that the server is buggy here, when we try to read
1081 // the initial reply.
1082 g_tls_intolerant_servers->insert(GetHostAndPort(request_->url));
1083 ResetConnectionAndRequestForResend();
1084 return OK;
[email protected]0b45559b2009-06-12 21:45:111085 }
[email protected]2181ea002009-06-09 01:37:271086 }
1087
[email protected]0877e3d2009-10-17 22:29:571088 if (result < 0 && result != ERR_CONNECTION_CLOSED)
initial.commit586acc5fe2008-07-26 22:42:521089 return HandleIOError(result);
1090
[email protected]0877e3d2009-10-17 22:29:571091 if (result == ERR_CONNECTION_CLOSED && ShouldResendRequest(result)) {
[email protected]1c773ea12009-04-28 19:58:421092 ResetConnectionAndRequestForResend();
[email protected]0877e3d2009-10-17 22:29:571093 return OK;
[email protected]1c773ea12009-04-28 19:58:421094 }
[email protected]2a5c76b2008-09-25 22:15:161095
[email protected]0877e3d2009-10-17 22:29:571096 // After we call RestartWithAuth a new response_time will be recorded, and
1097 // we need to be cautious about incorrectly logging the duration across the
1098 // authentication activity.
[email protected]8e3d2d32010-06-13 18:46:231099 LogTransactionConnectedMetrics();
initial.commit586acc5fe2008-07-26 22:42:521100
[email protected]0877e3d2009-10-17 22:29:571101 if (result == ERR_CONNECTION_CLOSED) {
[email protected]02c92c492010-03-08 21:28:141102 // For now, if we get at least some data, we do the best we can to make
[email protected]9492e4a2010-02-24 00:58:461103 // sense of it and send it back up the stack.
[email protected]0e75a732008-10-16 20:36:091104 int rv = HandleConnectionClosedBeforeEndOfHeaders();
[email protected]aecfbf22008-10-16 02:02:471105 if (rv != OK)
1106 return rv;
[email protected]0877e3d2009-10-17 22:29:571107 }
initial.commit586acc5fe2008-07-26 22:42:521108
[email protected]dbb83db2010-05-11 18:13:391109 if (net_log_.HasListener()) {
[email protected]8a1f3312010-05-25 19:25:041110 net_log_.AddEvent(
1111 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
1112 new NetLogHttpResponseParameter(response_.headers));
[email protected]dbb83db2010-05-11 18:13:391113 }
1114
[email protected]a7e41312009-12-16 23:18:141115 if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
[email protected]0877e3d2009-10-17 22:29:571116 // HTTP/0.9 doesn't support the PUT method, so lack of response headers
1117 // indicates a buggy server. See:
1118 // https://bugzilla.mozilla.org/show_bug.cgi?id=193921
1119 if (request_->method == "PUT")
1120 return ERR_METHOD_NOT_SUPPORTED;
1121 }
[email protected]4ddaf2502008-10-23 18:26:191122
[email protected]0877e3d2009-10-17 22:29:571123 // Check for an intermediate 100 Continue response. An origin server is
1124 // allowed to send this response even if we didn't ask for it, so we just
1125 // need to skip over it.
1126 // We treat any other 1xx in this same way (although in practice getting
1127 // a 1xx that isn't a 100 is rare).
[email protected]a7e41312009-12-16 23:18:141128 if (response_.headers->response_code() / 100 == 1) {
[email protected]ee9410e72010-01-07 01:42:381129 response_.headers = new HttpResponseHeaders("");
[email protected]0877e3d2009-10-17 22:29:571130 next_state_ = STATE_READ_HEADERS;
1131 return OK;
1132 }
1133
[email protected]564b4912010-03-09 16:30:421134 ProcessAlternateProtocol(*response_.headers,
[email protected]b6a50182010-05-12 22:47:141135 endpoint_,
[email protected]564b4912010-03-09 16:30:421136 session_->mutable_alternate_protocols());
1137
[email protected]e772db3f2010-07-12 18:11:131138 int rv = HandleAuthChallenge();
[email protected]0877e3d2009-10-17 22:29:571139 if (rv != OK)
1140 return rv;
1141
[email protected]8a1f3312010-05-25 19:25:041142 if (using_ssl_) {
[email protected]0877e3d2009-10-17 22:29:571143 SSLClientSocket* ssl_socket =
[email protected]e60e47a2010-07-14 03:37:181144 static_cast<SSLClientSocket*>(connection_->socket());
[email protected]a7e41312009-12-16 23:18:141145 ssl_socket->GetSSLInfo(&response_.ssl_info);
[email protected]0877e3d2009-10-17 22:29:571146 }
1147
1148 headers_valid_ = true;
1149 return OK;
initial.commit586acc5fe2008-07-26 22:42:521150}
1151
1152int HttpNetworkTransaction::DoReadBody() {
1153 DCHECK(read_buf_);
[email protected]6501bc02009-06-25 20:55:131154 DCHECK_GT(read_buf_len_, 0);
[email protected]1f14a912009-12-21 20:32:441155 DCHECK(connection_->is_initialized());
initial.commit586acc5fe2008-07-26 22:42:521156
1157 next_state_ = STATE_READ_BODY_COMPLETE;
[email protected]0877e3d2009-10-17 22:29:571158 return http_stream_->ReadResponseBody(read_buf_, read_buf_len_,
1159 &io_callback_);
initial.commit586acc5fe2008-07-26 22:42:521160}
1161
1162int HttpNetworkTransaction::DoReadBodyComplete(int result) {
1163 // We are done with the Read call.
initial.commit586acc5fe2008-07-26 22:42:521164 bool done = false, keep_alive = false;
[email protected]02c92c492010-03-08 21:28:141165 if (result <= 0)
initial.commit586acc5fe2008-07-26 22:42:521166 done = true;
[email protected]9492e4a2010-02-24 00:58:461167
1168 if (http_stream_->IsResponseBodyComplete()) {
[email protected]0877e3d2009-10-17 22:29:571169 done = true;
[email protected]9492e4a2010-02-24 00:58:461170 if (http_stream_->CanFindEndOfResponse())
[email protected]02c92c492010-03-08 21:28:141171 keep_alive = GetResponseHeaders()->IsKeepAlive();
initial.commit586acc5fe2008-07-26 22:42:521172 }
1173
[email protected]1f14a912009-12-21 20:32:441174 // Clean up connection_->if we are done.
initial.commit586acc5fe2008-07-26 22:42:521175 if (done) {
[email protected]56300172008-11-06 18:42:551176 LogTransactionMetrics();
initial.commit586acc5fe2008-07-26 22:42:521177 if (!keep_alive)
[email protected]1f14a912009-12-21 20:32:441178 connection_->socket()->Disconnect();
1179 connection_->Reset();
[email protected]96d570e42008-08-05 22:43:041180 // The next Read call will return 0 (EOF).
initial.commit586acc5fe2008-07-26 22:42:521181 }
1182
1183 // Clear these to avoid leaving around old state.
1184 read_buf_ = NULL;
1185 read_buf_len_ = 0;
1186
1187 return result;
1188}
1189
[email protected]2d2697f92009-02-18 21:00:321190int HttpNetworkTransaction::DoDrainBodyForAuthRestart() {
1191 // This method differs from DoReadBody only in the next_state_. So we just
1192 // call DoReadBody and override the next_state_. Perhaps there is a more
1193 // elegant way for these two methods to share code.
1194 int rv = DoReadBody();
1195 DCHECK(next_state_ == STATE_READ_BODY_COMPLETE);
1196 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE;
1197 return rv;
1198}
1199
[email protected]0877e3d2009-10-17 22:29:571200// TODO(wtc): This method and the DoReadBodyComplete method are almost
1201// the same. Figure out a good way for these two methods to share code.
[email protected]2d2697f92009-02-18 21:00:321202int HttpNetworkTransaction::DoDrainBodyForAuthRestartComplete(int result) {
[email protected]68873ba2009-06-04 21:49:231203 // keep_alive defaults to true because the very reason we're draining the
1204 // response body is to reuse the connection for auth restart.
1205 bool done = false, keep_alive = true;
[email protected]2d2697f92009-02-18 21:00:321206 if (result < 0) {
[email protected]0877e3d2009-10-17 22:29:571207 // Error or closed connection while reading the socket.
[email protected]2d2697f92009-02-18 21:00:321208 done = true;
[email protected]68873ba2009-06-04 21:49:231209 keep_alive = false;
[email protected]0877e3d2009-10-17 22:29:571210 } else if (http_stream_->IsResponseBodyComplete()) {
1211 done = true;
[email protected]2d2697f92009-02-18 21:00:321212 }
1213
1214 if (done) {
1215 DidDrainBodyForAuthRestart(keep_alive);
1216 } else {
1217 // Keep draining.
1218 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
1219 }
1220
1221 return OK;
1222}
1223
[email protected]1f14a912009-12-21 20:32:441224int HttpNetworkTransaction::DoSpdySendRequest() {
1225 next_state_ = STATE_SPDY_SEND_REQUEST_COMPLETE;
[email protected]9be804c82010-06-24 17:59:461226 CHECK(!spdy_http_stream_.get());
[email protected]1f14a912009-12-21 20:32:441227
1228 // First we get a SPDY session. Theoretically, we've just negotiated one, but
1229 // if one already exists, then screw it, use the existing one! Otherwise,
1230 // use the existing TCP socket.
1231
[email protected]955fc2e72010-02-08 20:37:301232 const scoped_refptr<SpdySessionPool> spdy_pool =
1233 session_->spdy_session_pool();
1234 scoped_refptr<SpdySession> spdy_session;
[email protected]5e2e6c77d12009-12-24 21:57:161235
[email protected]2d731a32010-04-29 01:04:061236 if (spdy_pool->HasSession(endpoint_)) {
[email protected]635909f2010-05-12 18:19:361237 spdy_session = spdy_pool->Get(endpoint_, session_, net_log_);
[email protected]1f14a912009-12-21 20:32:441238 } else {
[email protected]5fe524e2010-02-20 00:43:221239 // SPDY is negotiated using the TLS next protocol negotiation (NPN)
1240 // extension, so |connection_| must contain an SSLClientSocket.
1241 DCHECK(using_ssl_);
[email protected]2ff8b312010-04-26 22:20:541242 CHECK(connection_->socket());
[email protected]26ef6582010-06-24 02:30:471243 int error = spdy_pool->GetSpdySessionFromSSLSocket(
[email protected]bdbda462010-06-28 17:30:371244 endpoint_, session_, connection_.release(), net_log_,
1245 spdy_certificate_error_, &spdy_session);
[email protected]26ef6582010-06-24 02:30:471246 if (error != OK)
1247 return error;
[email protected]1f14a912009-12-21 20:32:441248 }
1249
1250 CHECK(spdy_session.get());
[email protected]b278eb72010-07-09 20:17:001251 if(spdy_session->IsClosed())
1252 return ERR_CONNECTION_CLOSED;
[email protected]1f14a912009-12-21 20:32:441253
[email protected]7a6db4022010-03-24 23:37:501254 UploadDataStream* upload_data = NULL;
1255 if (request_->upload_data) {
1256 int error_code = OK;
1257 upload_data = UploadDataStream::Create(request_->upload_data, &error_code);
1258 if (!upload_data)
1259 return error_code;
1260 }
[email protected]1f14a912009-12-21 20:32:441261 headers_valid_ = false;
[email protected]9be804c82010-06-24 17:59:461262 scoped_refptr<SpdyStream> spdy_stream;
[email protected]bdbda462010-06-28 17:30:371263 if (request_->method == "GET") {
1264 int error =
1265 spdy_session->GetPushStream(request_->url, &spdy_stream, net_log_);
1266 if (error != OK)
1267 return error;
1268 }
[email protected]9be804c82010-06-24 17:59:461269 if (spdy_stream.get()) {
1270 DCHECK(spdy_stream->pushed());
1271 CHECK(spdy_stream->GetDelegate() == NULL);
1272 spdy_http_stream_.reset(new SpdyHttpStream(spdy_stream));
1273 spdy_http_stream_->InitializeRequest(*request_, base::Time::Now(), NULL);
1274 } else {
[email protected]bdbda462010-06-28 17:30:371275 int error = spdy_session->CreateStream(request_->url,
1276 request_->priority,
1277 &spdy_stream,
1278 net_log_);
1279 if (error != OK)
1280 return error;
[email protected]9be804c82010-06-24 17:59:461281 DCHECK(!spdy_stream->pushed());
1282 CHECK(spdy_stream->GetDelegate() == NULL);
1283 spdy_http_stream_.reset(new SpdyHttpStream(spdy_stream));
1284 spdy_http_stream_->InitializeRequest(
1285 *request_, base::Time::Now(), upload_data);
1286 }
1287 return spdy_http_stream_->SendRequest(&response_, &io_callback_);
[email protected]1f14a912009-12-21 20:32:441288}
1289
1290int HttpNetworkTransaction::DoSpdySendRequestComplete(int result) {
1291 if (result < 0)
1292 return result;
1293
1294 next_state_ = STATE_SPDY_READ_HEADERS;
1295 return OK;
1296}
1297
1298int HttpNetworkTransaction::DoSpdyReadHeaders() {
1299 next_state_ = STATE_SPDY_READ_HEADERS_COMPLETE;
[email protected]9be804c82010-06-24 17:59:461300 return spdy_http_stream_->ReadResponseHeaders(&io_callback_);
[email protected]1f14a912009-12-21 20:32:441301}
1302
1303int HttpNetworkTransaction::DoSpdyReadHeadersComplete(int result) {
1304 // TODO(willchan): Flesh out the support for HTTP authentication here.
1305 if (result == OK)
1306 headers_valid_ = true;
[email protected]8e3d2d32010-06-13 18:46:231307
1308 LogTransactionConnectedMetrics();
1309
[email protected]1f14a912009-12-21 20:32:441310 return result;
1311}
1312
1313int HttpNetworkTransaction::DoSpdyReadBody() {
1314 next_state_ = STATE_SPDY_READ_BODY_COMPLETE;
1315
[email protected]9be804c82010-06-24 17:59:461316 return spdy_http_stream_->ReadResponseBody(
[email protected]1f14a912009-12-21 20:32:441317 read_buf_, read_buf_len_, &io_callback_);
1318}
1319
1320int HttpNetworkTransaction::DoSpdyReadBodyComplete(int result) {
1321 read_buf_ = NULL;
1322 read_buf_len_ = 0;
1323
1324 if (result <= 0)
[email protected]65d34382010-07-01 18:12:261325 spdy_http_stream_.reset();
[email protected]1f14a912009-12-21 20:32:441326
1327 return result;
1328}
1329
[email protected]a796bcec2010-03-22 17:17:261330void HttpNetworkTransaction::LogHttpConnectedMetrics(
[email protected]f9d285c2009-08-17 19:54:291331 const ClientSocketHandle& handle) {
[email protected]a796bcec2010-03-22 17:17:261332 UMA_HISTOGRAM_ENUMERATION("Net.HttpSocketType", handle.reuse_type(),
[email protected]2227c692010-05-04 15:36:111333 ClientSocketHandle::NUM_TYPES);
[email protected]f9d285c2009-08-17 19:54:291334
[email protected]bc3875bbc2009-08-24 19:44:201335 switch (handle.reuse_type()) {
1336 case ClientSocketHandle::UNUSED:
[email protected]a796bcec2010-03-22 17:17:261337 UMA_HISTOGRAM_CUSTOM_TIMES("Net.HttpConnectionLatency",
1338 handle.setup_time(),
1339 base::TimeDelta::FromMilliseconds(1),
1340 base::TimeDelta::FromMinutes(10),
1341 100);
[email protected]bc3875bbc2009-08-24 19:44:201342 break;
1343 case ClientSocketHandle::UNUSED_IDLE:
[email protected]a796bcec2010-03-22 17:17:261344 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SocketIdleTimeBeforeNextUse_UnusedSocket",
1345 handle.idle_time(),
1346 base::TimeDelta::FromMilliseconds(1),
1347 base::TimeDelta::FromMinutes(6),
1348 100);
[email protected]bc3875bbc2009-08-24 19:44:201349 break;
1350 case ClientSocketHandle::REUSED_IDLE:
[email protected]a796bcec2010-03-22 17:17:261351 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SocketIdleTimeBeforeNextUse_ReusedSocket",
1352 handle.idle_time(),
1353 base::TimeDelta::FromMilliseconds(1),
1354 base::TimeDelta::FromMinutes(6),
1355 100);
[email protected]bc3875bbc2009-08-24 19:44:201356 break;
1357 default:
1358 NOTREACHED();
1359 break;
1360 }
[email protected]42afa7c2009-04-17 23:51:241361}
1362
[email protected]f9d285c2009-08-17 19:54:291363void HttpNetworkTransaction::LogIOErrorMetrics(
1364 const ClientSocketHandle& handle) {
[email protected]2753b392009-12-28 06:59:521365 UMA_HISTOGRAM_ENUMERATION("Net.IOError_SocketReuseType",
[email protected]2227c692010-05-04 15:36:111366 handle.reuse_type(), ClientSocketHandle::NUM_TYPES);
[email protected]f9d285c2009-08-17 19:54:291367
[email protected]f9d285c2009-08-17 19:54:291368 switch (handle.reuse_type()) {
1369 case ClientSocketHandle::UNUSED:
1370 break;
1371 case ClientSocketHandle::UNUSED_IDLE:
[email protected]bc3875bbc2009-08-24 19:44:201372 UMA_HISTOGRAM_CUSTOM_TIMES(
1373 "Net.SocketIdleTimeOnIOError2_UnusedSocket",
1374 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1375 base::TimeDelta::FromMinutes(6), 100);
[email protected]f9d285c2009-08-17 19:54:291376 break;
1377 case ClientSocketHandle::REUSED_IDLE:
[email protected]bc3875bbc2009-08-24 19:44:201378 UMA_HISTOGRAM_CUSTOM_TIMES(
1379 "Net.SocketIdleTimeOnIOError2_ReusedSocket",
1380 handle.idle_time(), base::TimeDelta::FromMilliseconds(1),
1381 base::TimeDelta::FromMinutes(6), 100);
[email protected]f9d285c2009-08-17 19:54:291382 break;
1383 default:
1384 NOTREACHED();
1385 break;
1386 }
1387}
1388
[email protected]8e3d2d32010-06-13 18:46:231389void HttpNetworkTransaction::LogTransactionConnectedMetrics() {
1390 if (logged_response_time_)
1391 return;
1392
1393 logged_response_time_ = true;
1394
[email protected]a7e41312009-12-16 23:18:141395 base::TimeDelta total_duration = response_.response_time - start_time_;
[email protected]9a0a55f2009-04-13 23:23:031396
[email protected]510e854f2009-04-20 18:39:081397 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:581398 "Net.Transaction_Connected_Under_10",
[email protected]510e854f2009-04-20 18:39:081399 total_duration,
[email protected]9a0a55f2009-04-13 23:23:031400 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1401 100);
[email protected]1fa47592009-07-27 22:45:001402
[email protected]0310d432009-08-25 07:49:521403 if (!reused_socket_) {
[email protected]b01998a2009-04-21 01:01:111404 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:581405 "Net.Transaction_Connected_New",
[email protected]b01998a2009-04-21 01:01:111406 total_duration,
1407 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1408 100);
[email protected]d068f7a2010-06-07 15:12:591409
1410 static bool use_conn_impact_histogram(
1411 FieldTrialList::Find("ConnCountImpact") &&
1412 !FieldTrialList::Find("ConnCountImpact")->group_name().empty());
1413 if (use_conn_impact_histogram) {
1414 UMA_HISTOGRAM_CLIPPED_TIMES(
1415 FieldTrial::MakeName("Net.Transaction_Connected_New",
1416 "ConnCountImpact"),
1417 total_duration,
1418 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1419 100);
1420 }
[email protected]0310d432009-08-25 07:49:521421 }
1422
[email protected]8e3d2d32010-06-13 18:46:231423 static bool use_spdy_histogram(FieldTrialList::Find("SpdyImpact") &&
1424 !FieldTrialList::Find("SpdyImpact")->group_name().empty());
1425 if (use_spdy_histogram && response_.was_npn_negotiated) {
1426 UMA_HISTOGRAM_CLIPPED_TIMES(
1427 FieldTrial::MakeName("Net.Transaction_Connected_Under_10", "SpdyImpact"),
1428 total_duration, base::TimeDelta::FromMilliseconds(1),
1429 base::TimeDelta::FromMinutes(10), 100);
1430
1431 if (!reused_socket_) {
1432 UMA_HISTOGRAM_CLIPPED_TIMES(
1433 FieldTrial::MakeName("Net.Transaction_Connected_New", "SpdyImpact"),
1434 total_duration, base::TimeDelta::FromMilliseconds(1),
1435 base::TimeDelta::FromMinutes(10), 100);
1436 }
1437 }
1438
[email protected]510e854f2009-04-20 18:39:081439 // Currently, non-zero priority requests are frame or sub-frame resource
1440 // types. This will change when we also prioritize certain subresources like
1441 // css, js, etc.
1442 if (request_->priority) {
1443 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:581444 "Net.Priority_High_Latency",
[email protected]510e854f2009-04-20 18:39:081445 total_duration,
1446 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1447 100);
1448 } else {
1449 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]f929f2f22009-06-12 16:56:581450 "Net.Priority_Low_Latency",
[email protected]510e854f2009-04-20 18:39:081451 total_duration,
1452 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10),
1453 100);
1454 }
[email protected]9a0a55f2009-04-13 23:23:031455}
1456
[email protected]56300172008-11-06 18:42:551457void HttpNetworkTransaction::LogTransactionMetrics() const {
[email protected]0877e3d2009-10-17 22:29:571458 base::TimeDelta duration = base::Time::Now() -
[email protected]2227c692010-05-04 15:36:111459 response_.request_time;
[email protected]56300172008-11-06 18:42:551460 if (60 < duration.InMinutes())
1461 return;
[email protected]0b48db42009-03-23 02:45:111462
[email protected]21b316a2009-03-23 18:25:061463 base::TimeDelta total_duration = base::Time::Now() - start_time_;
1464
[email protected]f929f2f22009-06-12 16:56:581465 UMA_HISTOGRAM_LONG_TIMES("Net.Transaction_Latency", duration);
1466 UMA_HISTOGRAM_CLIPPED_TIMES("Net.Transaction_Latency_Under_10", duration,
[email protected]2227c692010-05-04 15:36:111467 base::TimeDelta::FromMilliseconds(1),
1468 base::TimeDelta::FromMinutes(10),
1469 100);
[email protected]f929f2f22009-06-12 16:56:581470 UMA_HISTOGRAM_CLIPPED_TIMES("Net.Transaction_Latency_Total_Under_10",
[email protected]2227c692010-05-04 15:36:111471 total_duration,
1472 base::TimeDelta::FromMilliseconds(1),
1473 base::TimeDelta::FromMinutes(10), 100);
[email protected]808f6402009-03-30 20:02:071474 if (!reused_socket_) {
[email protected]f929f2f22009-06-12 16:56:581475 UMA_HISTOGRAM_CLIPPED_TIMES(
[email protected]808f6402009-03-30 20:02:071476 "Net.Transaction_Latency_Total_New_Connection_Under_10",
[email protected]808f6402009-03-30 20:02:071477 total_duration, base::TimeDelta::FromMilliseconds(1),
1478 base::TimeDelta::FromMinutes(10), 100);
1479 }
[email protected]56300172008-11-06 18:42:551480}
1481
[email protected]ccb40e52008-09-17 20:54:401482int HttpNetworkTransaction::HandleCertificateError(int error) {
1483 DCHECK(using_ssl_);
[email protected]d7660f1c62010-02-15 02:57:291484 DCHECK(IsCertificateError(error));
1485
1486 SSLClientSocket* ssl_socket =
[email protected]e60e47a2010-07-14 03:37:181487 static_cast<SSLClientSocket*>(connection_->socket());
[email protected]d7660f1c62010-02-15 02:57:291488 ssl_socket->GetSSLInfo(&response_.ssl_info);
1489
1490 // Add the bad certificate to the set of allowed certificates in the
1491 // SSL info object. This data structure will be consulted after calling
1492 // RestartIgnoringLastError(). And the user will be asked interactively
1493 // before RestartIgnoringLastError() is ever called.
1494 SSLConfig::CertAndStatus bad_cert;
1495 bad_cert.cert = response_.ssl_info.cert;
1496 bad_cert.cert_status = response_.ssl_info.cert_status;
1497 ssl_config_.allowed_bad_certs.push_back(bad_cert);
[email protected]ccb40e52008-09-17 20:54:401498
[email protected]e60e47a2010-07-14 03:37:181499 int load_flags = request_->load_flags;
[email protected]37a67922010-03-05 00:16:021500 if (g_ignore_certificate_errors)
[email protected]e60e47a2010-07-14 03:37:181501 load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS;
1502 if (ssl_socket->IgnoreCertError(error, load_flags))
[email protected]37a67922010-03-05 00:16:021503 return OK;
[email protected]ccb40e52008-09-17 20:54:401504 return error;
1505}
1506
[email protected]5e363962009-06-19 19:57:011507int HttpNetworkTransaction::HandleCertificateRequest(int error) {
[email protected]0b45559b2009-06-12 21:45:111508 // Close the connection while the user is selecting a certificate to send
1509 // to the server.
[email protected]8b498692010-07-16 17:11:431510 if (connection_->socket())
1511 connection_->socket()->Disconnect();
[email protected]1f14a912009-12-21 20:32:441512 connection_->Reset();
[email protected]5e363962009-06-19 19:57:011513
1514 // If the user selected one of the certificate in client_certs for this
1515 // server before, use it automatically.
1516 X509Certificate* client_cert = session_->ssl_client_auth_cache()->
[email protected]2227c692010-05-04 15:36:111517 Lookup(GetHostAndPort(request_->url));
[email protected]5e363962009-06-19 19:57:011518 if (client_cert) {
1519 const std::vector<scoped_refptr<X509Certificate> >& client_certs =
[email protected]a7e41312009-12-16 23:18:141520 response_.cert_request_info->client_certs;
[email protected]5e363962009-06-19 19:57:011521 for (size_t i = 0; i < client_certs.size(); ++i) {
[email protected]bd0b7432009-06-23 21:03:421522 if (client_cert->fingerprint().Equals(client_certs[i]->fingerprint())) {
[email protected]5e363962009-06-19 19:57:011523 ssl_config_.client_cert = client_cert;
1524 ssl_config_.send_client_cert = true;
1525 next_state_ = STATE_INIT_CONNECTION;
1526 // Reset the other member variables.
1527 // Note: this is necessary only with SSL renegotiation.
1528 ResetStateForRestart();
1529 return OK;
1530 }
1531 }
1532 }
1533 return error;
[email protected]0b45559b2009-06-12 21:45:111534}
1535
[email protected]c5949a32008-10-08 17:28:231536int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
[email protected]5e363962009-06-19 19:57:011537 if (ssl_config_.send_client_cert &&
[email protected]2227c692010-05-04 15:36:111538 (error == ERR_SSL_PROTOCOL_ERROR ||
1539 error == ERR_BAD_SSL_CLIENT_AUTH_CERT)) {
[email protected]5e363962009-06-19 19:57:011540 session_->ssl_client_auth_cache()->Remove(GetHostAndPort(request_->url));
1541 }
1542
[email protected]5a179bcc2008-10-13 18:10:591543 switch (error) {
1544 case ERR_SSL_PROTOCOL_ERROR:
1545 case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
[email protected]aeaca1f2010-04-20 22:05:211546 case ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
[email protected]0ed94682010-05-18 15:09:001547 case ERR_SSL_BAD_RECORD_MAC_ALERT:
[email protected]d102f542010-06-30 14:51:051548 if (ssl_config_.tls1_enabled &&
1549 !SSLConfigService::IsKnownStrictTLSServer(request_->url.host())) {
[email protected]0ed94682010-05-18 15:09:001550 // This could be a TLS-intolerant server, an SSL 3.0 server that
1551 // chose a TLS-only cipher suite or a server with buggy DEFLATE
1552 // support. Turn off TLS 1.0, DEFLATE support and retry.
[email protected]aeaca1f2010-04-20 22:05:211553 g_tls_intolerant_servers->insert(GetHostAndPort(request_->url));
1554 ResetConnectionAndRequestForResend();
[email protected]5a179bcc2008-10-13 18:10:591555 error = OK;
1556 }
1557 break;
[email protected]c5949a32008-10-08 17:28:231558 }
[email protected]c5949a32008-10-08 17:28:231559 return error;
1560}
1561
[email protected]96d570e42008-08-05 22:43:041562// This method determines whether it is safe to resend the request after an
1563// IO error. It can only be called in response to request header or body
1564// write errors or response header read errors. It should not be used in
1565// other cases, such as a Connect error.
initial.commit586acc5fe2008-07-26 22:42:521566int HttpNetworkTransaction::HandleIOError(int error) {
1567 switch (error) {
1568 // If we try to reuse a connection that the server is in the process of
1569 // closing, we may end up successfully writing out our request (or a
1570 // portion of our request) only to find a connection error when we try to
1571 // read from (or finish writing to) the socket.
1572 case ERR_CONNECTION_RESET:
1573 case ERR_CONNECTION_CLOSED:
1574 case ERR_CONNECTION_ABORTED:
[email protected]1f14a912009-12-21 20:32:441575 LogIOErrorMetrics(*connection_);
[email protected]a19f1c602009-08-24 21:35:281576 if (ShouldResendRequest(error)) {
[email protected]1c773ea12009-04-28 19:58:421577 ResetConnectionAndRequestForResend();
initial.commit586acc5fe2008-07-26 22:42:521578 error = OK;
[email protected]1c773ea12009-04-28 19:58:421579 }
initial.commit586acc5fe2008-07-26 22:42:521580 break;
1581 }
1582 return error;
1583}
1584
[email protected]c3b35c22008-09-27 03:19:421585void HttpNetworkTransaction::ResetStateForRestart() {
[email protected]0757e7702009-03-27 04:00:221586 pending_auth_target_ = HttpAuth::AUTH_NONE;
[email protected]c3b35c22008-09-27 03:19:421587 read_buf_ = NULL;
1588 read_buf_len_ = 0;
[email protected]1f14a912009-12-21 20:32:441589 http_stream_.reset();
[email protected]0877e3d2009-10-17 22:29:571590 headers_valid_ = false;
1591 request_headers_.clear();
[email protected]a7e41312009-12-16 23:18:141592 response_ = HttpResponseInfo();
[email protected]0877e3d2009-10-17 22:29:571593}
1594
1595HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const {
[email protected]a7e41312009-12-16 23:18:141596 return response_.headers;
[email protected]c3b35c22008-09-27 03:19:421597}
1598
[email protected]a19f1c602009-08-24 21:35:281599bool HttpNetworkTransaction::ShouldResendRequest(int error) const {
[email protected]2a5c76b2008-09-25 22:15:161600 // NOTE: we resend a request only if we reused a keep-alive connection.
1601 // This automatically prevents an infinite resend loop because we'll run
1602 // out of the cached keep-alive connections eventually.
[email protected]8a1f3312010-05-25 19:25:041603 if (!connection_->ShouldResendFailedRequest(error) ||
[email protected]0877e3d2009-10-17 22:29:571604 GetResponseHeaders()) { // We have received some response headers.
[email protected]2a5c76b2008-09-25 22:15:161605 return false;
1606 }
[email protected]1c773ea12009-04-28 19:58:421607 return true;
1608}
1609
1610void HttpNetworkTransaction::ResetConnectionAndRequestForResend() {
[email protected]e60e47a2010-07-14 03:37:181611 if (connection_->socket())
1612 connection_->socket()->Disconnect();
[email protected]1f14a912009-12-21 20:32:441613 connection_->Reset();
[email protected]0877e3d2009-10-17 22:29:571614 // We need to clear request_headers_ because it contains the real request
1615 // headers, but we may need to resend the CONNECT request first to recreate
1616 // the SSL tunnel.
[email protected]e60e47a2010-07-14 03:37:181617
[email protected]0877e3d2009-10-17 22:29:571618 request_headers_.clear();
[email protected]2a5c76b2008-09-25 22:15:161619 next_state_ = STATE_INIT_CONNECTION; // Resend the request.
[email protected]2a5c76b2008-09-25 22:15:161620}
1621
[email protected]86ec30d2008-09-29 21:53:541622int HttpNetworkTransaction::ReconsiderProxyAfterError(int error) {
1623 DCHECK(!pac_request_);
1624
1625 // A failure to resolve the hostname or any error related to establishing a
1626 // TCP connection could be grounds for trying a new proxy configuration.
[email protected]7be51312008-09-29 23:21:301627 //
1628 // Why do this when a hostname cannot be resolved? Some URLs only make sense
1629 // to proxy servers. The hostname in those URLs might fail to resolve if we
1630 // are still using a non-proxy config. We need to check if a proxy config
1631 // now exists that corresponds to a proxy server that could load the URL.
1632 //
[email protected]86ec30d2008-09-29 21:53:541633 switch (error) {
1634 case ERR_NAME_NOT_RESOLVED:
1635 case ERR_INTERNET_DISCONNECTED:
1636 case ERR_ADDRESS_UNREACHABLE:
1637 case ERR_CONNECTION_CLOSED:
1638 case ERR_CONNECTION_RESET:
1639 case ERR_CONNECTION_REFUSED:
1640 case ERR_CONNECTION_ABORTED:
1641 case ERR_TIMED_OUT:
1642 case ERR_TUNNEL_CONNECTION_FAILED:
[email protected]d5a309592010-02-05 02:22:521643 case ERR_SOCKS_CONNECTION_FAILED:
[email protected]86ec30d2008-09-29 21:53:541644 break;
[email protected]d5a309592010-02-05 02:22:521645 case ERR_SOCKS_CONNECTION_HOST_UNREACHABLE:
1646 // Remap the SOCKS-specific "host unreachable" error to a more
1647 // generic error code (this way consumers like the link doctor
1648 // know to substitute their error page).
1649 //
1650 // Note that if the host resolving was done by the SOCSK5 proxy, we can't
1651 // differentiate between a proxy-side "host not found" versus a proxy-side
1652 // "address unreachable" error, and will report both of these failures as
1653 // ERR_ADDRESS_UNREACHABLE.
1654 return ERR_ADDRESS_UNREACHABLE;
[email protected]86ec30d2008-09-29 21:53:541655 default:
1656 return error;
1657 }
1658
[email protected]677c90572008-12-10 09:03:151659 if (request_->load_flags & LOAD_BYPASS_PROXY) {
1660 return error;
1661 }
1662
[email protected]86ec30d2008-09-29 21:53:541663 int rv = session_->proxy_service()->ReconsiderProxyAfterError(
[email protected]9e743cd2010-03-16 07:03:531664 request_->url, &proxy_info_, &io_callback_, &pac_request_, net_log_);
[email protected]86ec30d2008-09-29 21:53:541665 if (rv == OK || rv == ERR_IO_PENDING) {
[email protected]9172a982009-06-06 00:30:251666 // If the error was during connection setup, there is no socket to
1667 // disconnect.
[email protected]1f14a912009-12-21 20:32:441668 if (connection_->socket())
1669 connection_->socket()->Disconnect();
1670 connection_->Reset();
[email protected]86ec30d2008-09-29 21:53:541671 next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
1672 } else {
[email protected]69719062010-01-05 20:09:211673 // If ReconsiderProxyAfterError() failed synchronously, it means
1674 // there was nothing left to fall-back to, so fail the transaction
1675 // with the last connection error we got.
1676 // TODO(eroman): This is a confusing contract, make it more obvious.
[email protected]86ec30d2008-09-29 21:53:541677 rv = error;
1678 }
1679
1680 return rv;
1681}
1682
[email protected]1c773ea12009-04-28 19:58:421683bool HttpNetworkTransaction::ShouldApplyProxyAuth() const {
[email protected]8a1f3312010-05-25 19:25:041684 return !using_ssl_ && proxy_info_.is_http();
[email protected]1c773ea12009-04-28 19:58:421685}
license.botbf09a502008-08-24 00:55:551686
[email protected]1c773ea12009-04-28 19:58:421687bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
[email protected]8a1f3312010-05-25 19:25:041688 return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA);
[email protected]1c773ea12009-04-28 19:58:421689}
1690
[email protected]e772db3f2010-07-12 18:11:131691int HttpNetworkTransaction::HandleAuthChallenge() {
[email protected]0877e3d2009-10-17 22:29:571692 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
1693 DCHECK(headers);
[email protected]c3b35c22008-09-27 03:19:421694
[email protected]0877e3d2009-10-17 22:29:571695 int status = headers->response_code();
[email protected]c3b35c22008-09-27 03:19:421696 if (status != 401 && status != 407)
1697 return OK;
1698 HttpAuth::Target target = status == 407 ?
[email protected]2227c692010-05-04 15:36:111699 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER;
[email protected]038e9a32008-10-08 22:40:161700 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
1701 return ERR_UNEXPECTED_PROXY_AUTH;
[email protected]c3b35c22008-09-27 03:19:421702
[email protected]a7ea8832010-07-12 17:54:541703 int rv = auth_controllers_[target]->HandleAuthChallenge(
[email protected]560c0432010-07-13 20:45:311704 headers, (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false,
1705 net_log_);
[email protected]228404f2010-06-24 04:31:411706 if (auth_controllers_[target]->HaveAuthHandler())
1707 pending_auth_target_ = target;
1708
1709 scoped_refptr<AuthChallengeInfo> auth_info =
1710 auth_controllers_[target]->auth_info();
1711 if (auth_info.get())
1712 response_.auth_challenge = auth_info;
1713
[email protected]228404f2010-06-24 04:31:411714 return rv;
[email protected]f9ee6b52008-11-08 06:46:231715}
1716
[email protected]228404f2010-06-24 04:31:411717GURL HttpNetworkTransaction::AuthURL(HttpAuth::Target target) const {
1718 switch (target) {
1719 case HttpAuth::AUTH_PROXY:
1720 if (!proxy_info_.proxy_server().is_valid() ||
1721 proxy_info_.proxy_server().is_direct()) {
1722 return GURL(); // There is no proxy server.
1723 }
1724 return GURL("http://" + proxy_info_.proxy_server().host_and_port());
1725 case HttpAuth::AUTH_SERVER:
1726 return request_->url;
1727 default:
1728 return GURL();
1729 }
[email protected]c3b35c22008-09-27 03:19:421730}
1731
[email protected]a2cb8122010-03-10 17:22:421732void HttpNetworkTransaction::MarkBrokenAlternateProtocolAndFallback() {
[email protected]631f1322010-04-30 17:59:111733 // We have to:
1734 // * Reset the endpoint to be the unmodified URL specified destination.
1735 // * Mark the endpoint as broken so we don't try again.
1736 // * Set the alternate protocol mode to kDoNotUseAlternateProtocol so we
1737 // ignore future Alternate-Protocol headers from the HostPortPair.
1738 // * Reset the connection and go back to STATE_INIT_CONNECTION.
1739
1740 endpoint_ = HostPortPair(request_->url.HostNoBrackets(),
1741 request_->url.EffectiveIntPort());
[email protected]a2cb8122010-03-10 17:22:421742
1743 session_->mutable_alternate_protocols()->MarkBrokenAlternateProtocolFor(
[email protected]631f1322010-04-30 17:59:111744 endpoint_);
[email protected]a2cb8122010-03-10 17:22:421745
1746 alternate_protocol_mode_ = kDoNotUseAlternateProtocol;
1747 if (connection_->socket())
1748 connection_->socket()->Disconnect();
1749 connection_->Reset();
1750 next_state_ = STATE_INIT_CONNECTION;
1751}
1752
[email protected]aef04272010-06-28 18:03:041753#define STATE_CASE(s) case s: \
1754 description = StringPrintf("%s (0x%08X)", #s, s); \
1755 break
1756
1757std::string HttpNetworkTransaction::DescribeState(State state) {
1758 std::string description;
1759 switch (state) {
1760 STATE_CASE(STATE_RESOLVE_PROXY);
1761 STATE_CASE(STATE_RESOLVE_PROXY_COMPLETE);
1762 STATE_CASE(STATE_INIT_CONNECTION);
1763 STATE_CASE(STATE_INIT_CONNECTION_COMPLETE);
[email protected]a7ea8832010-07-12 17:54:541764 STATE_CASE(STATE_TUNNEL_RESTART_WITH_AUTH);
[email protected]aef04272010-06-28 18:03:041765 STATE_CASE(STATE_SSL_CONNECT);
1766 STATE_CASE(STATE_SSL_CONNECT_COMPLETE);
1767 STATE_CASE(STATE_GENERATE_PROXY_AUTH_TOKEN);
1768 STATE_CASE(STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE);
1769 STATE_CASE(STATE_GENERATE_SERVER_AUTH_TOKEN);
1770 STATE_CASE(STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE);
1771 STATE_CASE(STATE_SEND_REQUEST);
1772 STATE_CASE(STATE_SEND_REQUEST_COMPLETE);
1773 STATE_CASE(STATE_READ_HEADERS);
1774 STATE_CASE(STATE_READ_HEADERS_COMPLETE);
[email protected]aef04272010-06-28 18:03:041775 STATE_CASE(STATE_READ_BODY);
1776 STATE_CASE(STATE_READ_BODY_COMPLETE);
1777 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART);
1778 STATE_CASE(STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE);
1779 STATE_CASE(STATE_SPDY_SEND_REQUEST);
1780 STATE_CASE(STATE_SPDY_SEND_REQUEST_COMPLETE);
1781 STATE_CASE(STATE_SPDY_READ_HEADERS);
1782 STATE_CASE(STATE_SPDY_READ_HEADERS_COMPLETE);
1783 STATE_CASE(STATE_SPDY_READ_BODY);
1784 STATE_CASE(STATE_SPDY_READ_BODY_COMPLETE);
1785 STATE_CASE(STATE_NONE);
1786 default:
1787 description = StringPrintf("Unknown state 0x%08X (%u)", state, state);
1788 break;
1789 }
1790 return description;
1791}
1792
1793#undef STATE_CASE
1794
[email protected]c3b35c22008-09-27 03:19:421795} // namespace net