1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_stream_parser.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/compiler_specific.h" 8731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/histogram.h" 9dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/string_util.h" 10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/address_list.h" 113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/auth.h" 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/io_buffer.h" 133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/ssl_cert_request_info.h" 144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "net/http/http_net_log_params.h" 154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "net/http/http_request_headers.h" 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_request_info.h" 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_response_headers.h" 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_util.h" 193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/socket/ssl_client_socket.h" 203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/socket/client_socket_handle.h" 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net { 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHttpStreamParser::HttpStreamParser(ClientSocketHandle* connection, 253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const HttpRequestInfo* request, 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GrowableIOBuffer* read_buffer, 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BoundNetLog& net_log) 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : io_state_(STATE_NONE), 293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request_(request), 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request_headers_(NULL), 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request_body_(NULL), 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_(read_buffer), 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_unused_offset_(0), 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_header_start_offset_(-1), 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_body_length_(-1), 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_body_read_(0), 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott chunked_decoder_(NULL), 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_(NULL), 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_len_(0), 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_(NULL), 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott connection_(connection), 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_(net_log), 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ALLOW_THIS_IN_INITIALIZER_LIST( 44dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen io_callback_(this, &HttpStreamParser::OnIOComplete)), 45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen chunk_length_(0), 46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen chunk_length_without_encoding_(0), 47dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sent_last_chunk_(false) { 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(0, read_buffer->offset()); 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenHttpStreamParser::~HttpStreamParser() { 5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (request_body_ != NULL && request_body_->is_chunked()) 5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen request_body_->set_chunk_callback(NULL); 5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochint HttpStreamParser::SendRequest(const std::string& request_line, 574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const HttpRequestHeaders& headers, 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UploadDataStream* request_body, 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpResponseInfo* response, 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback) { 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(STATE_NONE, io_state_); 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_callback_); 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(callback); 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(response); 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (net_log_.IsLoggingAllEvents()) { 674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch net_log_.AddEvent( 684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS, 694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch make_scoped_refptr(new NetLogHttpRequestParameter( 704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch request_line, headers))); 714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_ = response; 73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Put the peer's IP address and port into the response. 75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen AddressList address; 76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int result = connection_->socket()->GetPeerAddress(&address); 77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (result != OK) 78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return result; 79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen response_->socket_address = HostPortPair::FromAddrInfo(address.head()); 80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string request = request_line + headers.ToString(); 824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch scoped_refptr<StringIOBuffer> headers_io_buf(new StringIOBuffer(request)); 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request_headers_ = new DrainableIOBuffer(headers_io_buf, 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers_io_buf->size()); 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request_body_.reset(request_body); 86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (request_body_ != NULL && request_body_->is_chunked()) { 8772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen request_body_->set_chunk_callback(this); 88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const int kChunkHeaderFooterSize = 12; // 2 CRLFs + max of 8 hex chars. 89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen chunk_buf_ = new IOBuffer(request_body_->GetMaxBufferSize() + 90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen kChunkHeaderFooterSize); 91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_SENDING_HEADERS; 94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen result = DoLoop(OK); 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == ERR_IO_PENDING) 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_ = callback; 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result > 0 ? OK : result; 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::ReadResponseHeaders(CompletionCallback* callback) { 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(io_state_ == STATE_REQUEST_SENT || io_state_ == STATE_DONE); 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_callback_); 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(callback); 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This function can be called with io_state_ == STATE_DONE if the 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // connection is closed after seeing just a 1xx response code. 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (io_state_ == STATE_DONE) 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CONNECTION_CLOSED; 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int result = OK; 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_READ_HEADERS; 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (read_buf_->offset() > 0) { 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Simulate the state where the data was just read from the socket. 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = read_buf_->offset() - read_buf_unused_offset_; 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->set_offset(read_buf_unused_offset_); 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result > 0) 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_READ_HEADERS_COMPLETE; 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoLoop(result); 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == ERR_IO_PENDING) 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_ = callback; 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result > 0 ? OK : result; 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HttpStreamParser::Close(bool not_reusable) { 1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (not_reusable && connection_->socket()) 1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick connection_->socket()->Disconnect(); 1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick connection_->Reset(); 1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::ReadResponseBody(IOBuffer* buf, int buf_len, 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompletionCallback* callback) { 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(io_state_ == STATE_BODY_PENDING || io_state_ == STATE_DONE); 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_callback_); 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(callback); 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_LE(buf_len, kMaxBufSize); 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (io_state_ == STATE_DONE) 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_ = buf; 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_len_ = buf_len; 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_READ_BODY; 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int result = DoLoop(OK); 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == ERR_IO_PENDING) 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_ = callback; 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpStreamParser::OnIOComplete(int result) { 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoLoop(result); 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The client callback can do anything, including destroying this class, 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // so any pending callback must be issued after everything else is done. 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result != ERR_IO_PENDING && user_callback_) { 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* c = user_callback_; 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_ = NULL; 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott c->Run(result); 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid HttpStreamParser::OnChunkAvailable() { 16972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // This method may get called while sending the headers or body, so check 17072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // before processing the new data. If we were still initializing or sending 17172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // headers, we will automatically start reading the chunks once we get into 17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // STATE_SENDING_BODY so nothing to do here. 17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(io_state_ == STATE_SENDING_HEADERS || io_state_ == STATE_SENDING_BODY); 17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (io_state_ == STATE_SENDING_BODY) 17572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnIOComplete(0); 17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 17772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::DoLoop(int result) { 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool can_do_more = true; 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (io_state_) { 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_SENDING_HEADERS: 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0) 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott can_do_more = false; 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoSendHeaders(result); 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_SENDING_BODY: 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0) 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott can_do_more = false; 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoSendBody(result); 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_REQUEST_SENT: 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(result != ERR_IO_PENDING); 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott can_do_more = false; 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_READ_HEADERS: 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_PARSER_READ_HEADERS, NULL); 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoReadHeaders(); 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_READ_HEADERS_COMPLETE: 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoReadHeadersComplete(result); 20472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEventWithNetErrorCode( 20572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NetLog::TYPE_HTTP_STREAM_PARSER_READ_HEADERS, result); 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_BODY_PENDING: 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(result != ERR_IO_PENDING); 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott can_do_more = false; 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_READ_BODY: 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoReadBody(); 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // DoReadBodyComplete handles error conditions. 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_READ_BODY_COMPLETE: 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoReadBodyComplete(result); 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_DONE: 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(result != ERR_IO_PENDING); 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott can_do_more = false; 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED(); 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott can_do_more = false; 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while (result != ERR_IO_PENDING && can_do_more); 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::DoSendHeaders(int result) { 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request_headers_->DidConsume(result); 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int bytes_remaining = request_headers_->BytesRemaining(); 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (bytes_remaining > 0) { 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Record our best estimate of the 'request time' as the time when we send 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // out the first bytes of the request headers. 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (bytes_remaining == request_headers_->size()) { 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_->request_time = base::Time::Now(); 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We'll record the count of uncoalesced packets IFF coalescing will help, 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and otherwise we'll use an enum to tell why it won't help. 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch enum COALESCE_POTENTIAL { 24472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Coalescing won't reduce packet count. 24572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NO_ADVANTAGE = 0, 24672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // There is only a header packet or we have a request body but the 24772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // request body isn't available yet (can't coalesce). 24872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen HEADER_ONLY = 1, 24972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Various cases of coalasced savings. 25072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen COALESCE_POTENTIAL_MAX = 30 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t coalesce = HEADER_ONLY; 25372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (request_body_ != NULL && !request_body_->is_chunked()) { 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const size_t kBytesPerPacket = 1430; 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uint64 body_packets = (request_body_->size() + kBytesPerPacket - 1) / 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kBytesPerPacket; 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uint64 header_packets = (bytes_remaining + kBytesPerPacket - 1) / 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kBytesPerPacket; 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uint64 coalesced_packets = (request_body_->size() + bytes_remaining + 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kBytesPerPacket - 1) / kBytesPerPacket; 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (coalesced_packets < header_packets + body_packets) { 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (coalesced_packets > COALESCE_POTENTIAL_MAX) 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch coalesce = COALESCE_POTENTIAL_MAX; 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch coalesce = static_cast<size_t>(header_packets + body_packets); 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch coalesce = NO_ADVANTAGE; 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_ENUMERATION("Net.CoalescePotential", coalesce, 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch COALESCE_POTENTIAL_MAX); 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = connection_->socket()->Write(request_headers_, 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bytes_remaining, 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &io_callback_); 27672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else if (request_body_ != NULL && 27772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen (request_body_->is_chunked() || request_body_->size())) { 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_SENDING_BODY; 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = OK; 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_REQUEST_SENT; 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::DoSendBody(int result) { 287dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (request_body_->is_chunked()) { 288dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen chunk_length_ -= result; 289dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (chunk_length_) { 290dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen memmove(chunk_buf_->data(), chunk_buf_->data() + result, chunk_length_); 291dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return connection_->socket()->Write(chunk_buf_, chunk_length_, 292dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &io_callback_); 293dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 294dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 295dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (sent_last_chunk_) { 296dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen io_state_ = STATE_REQUEST_SENT; 297dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return OK; 298dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 299dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 300dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen request_body_->MarkConsumedAndFillBuffer(chunk_length_without_encoding_); 301dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen chunk_length_without_encoding_ = 0; 302dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen chunk_length_ = 0; 303dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 304dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int buf_len = static_cast<int>(request_body_->buf_len()); 305dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (request_body_->eof()) { 306dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen static const char kLastChunk[] = "0\r\n\r\n"; 307dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen chunk_length_ = strlen(kLastChunk); 308dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen memcpy(chunk_buf_->data(), kLastChunk, chunk_length_); 309dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sent_last_chunk_ = true; 310dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else if (buf_len) { 311dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Encode and send the buffer as 1 chunk. 312dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string chunk_header = StringPrintf("%X\r\n", buf_len); 313dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen char* chunk_ptr = chunk_buf_->data(); 314dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen memcpy(chunk_ptr, chunk_header.data(), chunk_header.length()); 315dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen chunk_ptr += chunk_header.length(); 316dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen memcpy(chunk_ptr, request_body_->buf()->data(), buf_len); 317dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen chunk_ptr += buf_len; 318dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen memcpy(chunk_ptr, "\r\n", 2); 319dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen chunk_length_without_encoding_ = buf_len; 320dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen chunk_length_ = chunk_header.length() + buf_len + 2; 321dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 322dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 323dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!chunk_length_) // More POST data is yet to come? 324dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return ERR_IO_PENDING; 325dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 326dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return connection_->socket()->Write(chunk_buf_, chunk_length_, 327dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &io_callback_); 328dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 329dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 330dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Non-chunked request body. 33172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen request_body_->MarkConsumedAndFillBuffer(result); 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!request_body_->eof()) { 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int buf_len = static_cast<int>(request_body_->buf_len()); 335dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen result = connection_->socket()->Write(request_body_->buf(), buf_len, 336dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &io_callback_); 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_REQUEST_SENT; 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::DoReadHeaders() { 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_READ_HEADERS_COMPLETE; 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Grow the read buffer if necessary. 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (read_buf_->RemainingCapacity() == 0) 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL. 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // See if the user is passing in an IOBuffer with a NULL |data_|. 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECK(read_buf_->data()); 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return connection_->socket()->Read(read_buf_, 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->RemainingCapacity(), 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &io_callback_); 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::DoReadHeadersComplete(int result) { 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == 0) 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = ERR_CONNECTION_CLOSED; 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0 && result != ERR_CONNECTION_CLOSED) { 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_DONE; 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 3673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If we've used the connection before, then we know it is not a HTTP/0.9 3683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // response and return ERR_CONNECTION_CLOSED. 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == ERR_CONNECTION_CLOSED && read_buf_->offset() == 0 && 3703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick connection_->is_reused()) { 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_DONE; 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Record our best estimate of the 'response time' as the time when we read 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the first bytes of the response headers. 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (read_buf_->offset() == 0 && result != ERR_CONNECTION_CLOSED) 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_->response_time = base::Time::Now(); 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == ERR_CONNECTION_CLOSED) { 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The connection closed before we detected the end of the headers. 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // parse things as well as we can and let the caller decide what to do. 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (read_buf_->offset() == 0) { 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The connection was closed before any data was sent. Likely an error 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // rather than empty HTTP/0.9 response. 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_DONE; 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_EMPTY_RESPONSE; 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int end_offset; 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_header_start_offset_ >= 0) { 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_READ_BODY_COMPLETE; 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end_offset = read_buf_->offset(); 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_BODY_PENDING; 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end_offset = 0; 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 3973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int rv = DoParseResponseHeaders(end_offset); 3983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (rv < 0) 3993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return rv; 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->set_offset(read_buf_->offset() + result); 405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_LE(read_buf_->offset(), read_buf_->capacity()); 4063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GE(result, 0); 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int end_of_header_offset = ParseResponseHeaders(); 4093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Note: -1 is special, it indicates we haven't found the end of headers. 4113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Anything less than -1 is a net::Error, so we bail out. 4123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (end_of_header_offset < -1) 4133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return end_of_header_offset; 4143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (end_of_header_offset == -1) { 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_READ_HEADERS; 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Prevent growing the headers buffer indefinitely. 418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (read_buf_->offset() - read_buf_unused_offset_ >= kMaxHeaderBufSize) { 419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_DONE; 420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_RESPONSE_HEADERS_TOO_BIG; 421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note where the headers stop. 424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_unused_offset_ = end_of_header_offset; 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_->headers->response_code() / 100 == 1) { 427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // After processing a 1xx response, the caller will ask for the next 428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // header, so reset state to support that. We don't just skip these 429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // completely because 1xx codes aren't acceptable when establishing a 430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // tunnel. 431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_REQUEST_SENT; 432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_header_start_offset_ = -1; 433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_BODY_PENDING; 435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CalculateResponseBodySize(); 436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If the body is 0, the caller may not call ReadResponseBody, which 437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // is where any extra data is copied to read_buf_, so we move the 438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // data here and transition to DONE. 439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_body_length_ == 0) { 440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_DONE; 441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int extra_bytes = read_buf_->offset() - read_buf_unused_offset_; 442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (extra_bytes) { 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK_GT(extra_bytes, 0); 444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memmove(read_buf_->StartOfBuffer(), 445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->StartOfBuffer() + read_buf_unused_offset_, 446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott extra_bytes); 447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->SetCapacity(extra_bytes); 449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_unused_offset_ = 0; 450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::DoReadBody() { 458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_READ_BODY_COMPLETE; 459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // There may be some data left over from reading the response headers. 461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (read_buf_->offset()) { 462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int available = read_buf_->offset() - read_buf_unused_offset_; 463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (available) { 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK_GT(available, 0); 465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int bytes_from_buffer = std::min(available, user_read_buf_len_); 466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(user_read_buf_->data(), 467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->StartOfBuffer() + read_buf_unused_offset_, 468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_from_buffer); 469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_unused_offset_ += bytes_from_buffer; 470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes_from_buffer == available) { 471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->SetCapacity(0); 472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_unused_offset_ = 0; 473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return bytes_from_buffer; 475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->SetCapacity(0); 477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_unused_offset_ = 0; 478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check to see if we're done reading. 482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (IsResponseBodyComplete()) 483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(0, read_buf_->offset()); 486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return connection_->socket()->Read(user_read_buf_, user_read_buf_len_, 487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &io_callback_); 488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::DoReadBodyComplete(int result) { 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we didn't get a content-length and aren't using a chunked encoding, 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the only way to signal the end of a stream is to close the connection, 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so we don't treat that as an error, though in some cases we may not 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // have completely received the resource. 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (result == 0 && !IsResponseBodyComplete() && CanFindEndOfResponse()) 496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = ERR_CONNECTION_CLOSED; 497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Filter incoming data if appropriate. FilterBuf may return an error. 499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result > 0 && chunked_decoder_.get()) { 500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = chunked_decoder_->FilterBuf(user_read_buf_->data(), result); 501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == 0 && !chunked_decoder_->reached_eof()) { 502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Don't signal completion of the Read call yet or else it'll look like 503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // we received end-of-file. Wait for more data. 504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_READ_BODY; 505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result > 0) 510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_body_read_ += result; 511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (result <= 0 || IsResponseBodyComplete()) { 513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_DONE; 514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Save the overflow data, which can be in two places. There may be 516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // some left over in |user_read_buf_|, plus there may be more 517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // in |read_buf_|. But the part left over in |user_read_buf_| must have 518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // come from the |read_buf_|, so there's room to put it back at the 519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // start first. 520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int additional_save_amount = read_buf_->offset() - read_buf_unused_offset_; 521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int save_amount = 0; 522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (chunked_decoder_.get()) { 523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott save_amount = chunked_decoder_->bytes_after_eof(); 524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (response_body_length_ >= 0) { 525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int64 extra_data_read = response_body_read_ - response_body_length_; 526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (extra_data_read > 0) { 527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott save_amount = static_cast<int>(extra_data_read); 528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result > 0) 529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result -= save_amount; 530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK_LE(save_amount + additional_save_amount, kMaxBufSize); 534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (read_buf_->capacity() < save_amount + additional_save_amount) { 535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->SetCapacity(save_amount + additional_save_amount); 536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (save_amount) { 539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(read_buf_->StartOfBuffer(), user_read_buf_->data() + result, 540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott save_amount); 541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->set_offset(save_amount); 543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (additional_save_amount) { 544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memmove(read_buf_->data(), 545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->StartOfBuffer() + read_buf_unused_offset_, 546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott additional_save_amount); 547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->set_offset(save_amount + additional_save_amount); 548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_unused_offset_ = 0; 550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_BODY_PENDING; 552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_ = NULL; 553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_len_ = 0; 554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::ParseResponseHeaders() { 560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int end_offset = -1; 561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Look for the start of the status line, if it hasn't been found yet. 563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_header_start_offset_ < 0) { 564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_header_start_offset_ = HttpUtil::LocateStartOfStatusLine( 565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->StartOfBuffer() + read_buf_unused_offset_, 566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->offset() - read_buf_unused_offset_); 567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_header_start_offset_ >= 0) { 570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end_offset = HttpUtil::LocateEndOfHeaders( 571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->StartOfBuffer() + read_buf_unused_offset_, 572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->offset() - read_buf_unused_offset_, 573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_header_start_offset_); 574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (read_buf_->offset() - read_buf_unused_offset_ >= 8) { 575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Enough data to decide that this is an HTTP/0.9 response. 576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 8 bytes = (4 bytes of junk) + "http".length() 577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end_offset = 0; 578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (end_offset == -1) 581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return -1; 582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int rv = DoParseResponseHeaders(end_offset); 5843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (rv < 0) 5853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return rv; 586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return end_offset + read_buf_unused_offset_; 587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint HttpStreamParser::DoParseResponseHeaders(int end_offset) { 590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_refptr<HttpResponseHeaders> headers; 591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_header_start_offset_ >= 0) { 592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers = new HttpResponseHeaders(HttpUtil::AssembleRawHeaders( 593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->StartOfBuffer() + read_buf_unused_offset_, end_offset)); 594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Enough data was read -- there is no status line. 596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK")); 597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Check for multiple Content-Length headers with a Transfer-Encoding header. 6003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If they exist, it's a potential response smuggling attack. 6013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 6023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void* it = NULL; 6033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string content_length_header("Content-Length"); 604513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::string content_length_value; 6053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!headers->HasHeader("Transfer-Encoding") && 6063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick headers->EnumerateHeader( 607513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch &it, content_length_header, &content_length_value)) { 608513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Ok, there's no Transfer-Encoding header and there's at least one 609513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Content-Length header. Check if there are any more Content-Length 610513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // headers, and if so, make sure they have the same value. Otherwise, it's 611513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // a possible response smuggling attack. 612513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::string content_length_value2; 613513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch while (headers->EnumerateHeader( 614513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch &it, content_length_header, &content_length_value2)) { 615513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (content_length_value != content_length_value2) 616513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH; 617513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 6183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 6193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_->headers = headers; 621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_->vary_data.Init(*request_, *response_->headers); 6223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return OK; 623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpStreamParser::CalculateResponseBodySize() { 626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Figure how to determine EOF: 627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // For certain responses, we know the content length is always 0. From 629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // RFC 2616 Section 4.3 Message Body: 630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // For response messages, whether or not a message-body is included with 632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // a message is dependent on both the request method and the response 633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // status code (section 6.1.1). All responses to the HEAD request method 634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // MUST NOT include a message-body, even though the presence of entity- 635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // header fields might lead one to believe they do. All 1xx 636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // (informational), 204 (no content), and 304 (not modified) responses 637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // MUST NOT include a message-body. All other responses do include a 638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // message-body, although it MAY be of zero length. 639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (response_->headers->response_code()) { 640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note that 1xx was already handled earlier. 641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 204: // No Content 642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 205: // Reset Content 643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 304: // Not Modified 644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_body_length_ = 0; 645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (request_->method == "HEAD") 648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_body_length_ = 0; 649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_body_length_ == -1) { 651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Ignore spurious chunked responses from HTTP/1.0 servers and 652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // proxies. Otherwise "Transfer-Encoding: chunked" trumps 653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // "Content-Length: N" 654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_->headers->GetHttpVersion() >= HttpVersion(1, 1) && 655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_->headers->HasHeaderValue("Transfer-Encoding", "chunked")) { 656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott chunked_decoder_.reset(new HttpChunkedDecoder()); 657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_body_length_ = response_->headers->GetContentLength(); 659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If response_body_length_ is still -1, then we have to wait 660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // for the server to close the connection. 661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottuint64 HttpStreamParser::GetUploadProgress() const { 666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!request_body_.get()) 667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return request_body_->position(); 670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHttpResponseInfo* HttpStreamParser::GetResponseInfo() { 673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return response_; 674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpStreamParser::IsResponseBodyComplete() const { 677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (chunked_decoder_.get()) 678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return chunked_decoder_->reached_eof(); 679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_body_length_ != -1) 680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return response_body_read_ >= response_body_length_; 681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; // Must read to EOF. 683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpStreamParser::CanFindEndOfResponse() const { 686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return chunked_decoder_.get() || response_body_length_ >= 0; 687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpStreamParser::IsMoreDataBuffered() const { 690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return read_buf_->offset() > read_buf_unused_offset_; 691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 6933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool HttpStreamParser::IsConnectionReused() const { 6943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ClientSocketHandle::SocketReuseType reuse_type = connection_->reuse_type(); 6953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return connection_->is_reused() || 6963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick reuse_type == ClientSocketHandle::UNUSED_IDLE; 6973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 6983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 6993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HttpStreamParser::SetConnectionReused() { 7003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick connection_->set_is_reused(true); 7013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 7023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 703ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool HttpStreamParser::IsConnectionReusable() const { 704ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return connection_->socket() && connection_->socket()->IsConnectedAndIdle(); 705ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 706ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 7073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HttpStreamParser::GetSSLInfo(SSLInfo* ssl_info) { 708731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (request_->url.SchemeIs("https") && connection_->socket()) { 7093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SSLClientSocket* ssl_socket = 7103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static_cast<SSLClientSocket*>(connection_->socket()); 7113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ssl_socket->GetSSLInfo(ssl_info); 7123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 7133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 7143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 7153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HttpStreamParser::GetSSLCertRequestInfo( 7163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SSLCertRequestInfo* cert_request_info) { 717731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (request_->url.SchemeIs("https") && connection_->socket()) { 7183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SSLClientSocket* ssl_socket = 7193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static_cast<SSLClientSocket*>(connection_->socket()); 7203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ssl_socket->GetSSLCertRequestInfo(cert_request_info); 7213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 7223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 7233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 725