http_stream_parser.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 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" 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/histogram.h" 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/io_buffer.h" 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_request_info.h" 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_response_headers.h" 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_util.h" 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net { 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHttpStreamParser::HttpStreamParser(ClientSocketHandle* connection, 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GrowableIOBuffer* read_buffer, 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BoundNetLog& net_log) 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : io_state_(STATE_NONE), 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request_(NULL), 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request_headers_(NULL), 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request_body_(NULL), 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_(read_buffer), 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_unused_offset_(0), 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_header_start_offset_(-1), 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_body_length_(-1), 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_body_read_(0), 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott chunked_decoder_(NULL), 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_(NULL), 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_len_(0), 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_(NULL), 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott connection_(connection), 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_(net_log), 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ALLOW_THIS_IN_INITIALIZER_LIST( 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_callback_(this, &HttpStreamParser::OnIOComplete)) { 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(0, read_buffer->offset()); 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHttpStreamParser::~HttpStreamParser() {} 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::SendRequest(const HttpRequestInfo* request, 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string& headers, 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UploadDataStream* request_body, 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpResponseInfo* response, 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback) { 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(STATE_NONE, io_state_); 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_callback_); 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(callback); 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(response); 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request_ = request; 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_ = response; 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_refptr<StringIOBuffer> headers_io_buf = new StringIOBuffer(headers); 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request_headers_ = new DrainableIOBuffer(headers_io_buf, 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers_io_buf->size()); 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request_body_.reset(request_body); 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_SENDING_HEADERS; 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int result = DoLoop(OK); 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == ERR_IO_PENDING) 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_ = callback; 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result > 0 ? OK : result; 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::ReadResponseHeaders(CompletionCallback* callback) { 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(io_state_ == STATE_REQUEST_SENT || io_state_ == STATE_DONE); 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_callback_); 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(callback); 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This function can be called with io_state_ == STATE_DONE if the 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // connection is closed after seeing just a 1xx response code. 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (io_state_ == STATE_DONE) 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CONNECTION_CLOSED; 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int result = OK; 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_READ_HEADERS; 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (read_buf_->offset() > 0) { 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Simulate the state where the data was just read from the socket. 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = read_buf_->offset() - read_buf_unused_offset_; 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->set_offset(read_buf_unused_offset_); 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result > 0) 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_READ_HEADERS_COMPLETE; 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoLoop(result); 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == ERR_IO_PENDING) 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_ = callback; 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result > 0 ? OK : result; 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::ReadResponseBody(IOBuffer* buf, int buf_len, 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompletionCallback* callback) { 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(io_state_ == STATE_BODY_PENDING || io_state_ == STATE_DONE); 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_callback_); 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(callback); 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_LE(buf_len, kMaxBufSize); 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (io_state_ == STATE_DONE) 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_ = buf; 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_len_ = buf_len; 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_READ_BODY; 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int result = DoLoop(OK); 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == ERR_IO_PENDING) 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_ = callback; 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpStreamParser::OnIOComplete(int result) { 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoLoop(result); 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The client callback can do anything, including destroying this class, 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // so any pending callback must be issued after everything else is done. 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result != ERR_IO_PENDING && user_callback_) { 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* c = user_callback_; 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_ = NULL; 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott c->Run(result); 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::DoLoop(int result) { 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool can_do_more = true; 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (io_state_) { 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_SENDING_HEADERS: 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0) 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott can_do_more = false; 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoSendHeaders(result); 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_SENDING_BODY: 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0) 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott can_do_more = false; 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoSendBody(result); 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_REQUEST_SENT: 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(result != ERR_IO_PENDING); 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott can_do_more = false; 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_READ_HEADERS: 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_PARSER_READ_HEADERS, NULL); 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoReadHeaders(); 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_READ_HEADERS_COMPLETE: 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoReadHeadersComplete(result); 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_PARSER_READ_HEADERS, NULL); 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_BODY_PENDING: 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(result != ERR_IO_PENDING); 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott can_do_more = false; 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_READ_BODY: 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoReadBody(); 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // DoReadBodyComplete handles error conditions. 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_READ_BODY_COMPLETE: 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoReadBodyComplete(result); 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_DONE: 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(result != ERR_IO_PENDING); 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott can_do_more = false; 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED(); 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott can_do_more = false; 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while (result != ERR_IO_PENDING && can_do_more); 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::DoSendHeaders(int result) { 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request_headers_->DidConsume(result); 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int bytes_remaining = request_headers_->BytesRemaining(); 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (bytes_remaining > 0) { 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Record our best estimate of the 'request time' as the time when we send 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // out the first bytes of the request headers. 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (bytes_remaining == request_headers_->size()) { 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_->request_time = base::Time::Now(); 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We'll record the count of uncoalesced packets IFF coalescing will help, 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and otherwise we'll use an enum to tell why it won't help. 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch enum COALESCE_POTENTIAL { 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NO_ADVANTAGE = 0, // Coalescing won't reduce packet count. 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HEADER_ONLY = 1, // There is only a header packet (can't coalesce). 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch COALESCE_POTENTIAL_MAX = 30 // Various cases of coalasced savings. 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t coalesce = HEADER_ONLY; 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request_body_ != NULL) { 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const size_t kBytesPerPacket = 1430; 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uint64 body_packets = (request_body_->size() + kBytesPerPacket - 1) / 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kBytesPerPacket; 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uint64 header_packets = (bytes_remaining + kBytesPerPacket - 1) / 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kBytesPerPacket; 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uint64 coalesced_packets = (request_body_->size() + bytes_remaining + 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kBytesPerPacket - 1) / kBytesPerPacket; 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (coalesced_packets < header_packets + body_packets) { 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (coalesced_packets > COALESCE_POTENTIAL_MAX) 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch coalesce = COALESCE_POTENTIAL_MAX; 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch coalesce = static_cast<size_t>(header_packets + body_packets); 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch coalesce = NO_ADVANTAGE; 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_ENUMERATION("Net.CoalescePotential", coalesce, 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch COALESCE_POTENTIAL_MAX); 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = connection_->socket()->Write(request_headers_, 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bytes_remaining, 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &io_callback_); 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (request_body_ != NULL && request_body_->size()) { 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_SENDING_BODY; 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = OK; 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_REQUEST_SENT; 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::DoSendBody(int result) { 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result > 0) 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request_body_->DidConsume(result); 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!request_body_->eof()) { 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int buf_len = static_cast<int>(request_body_->buf_len()); 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = connection_->socket()->Write(request_body_->buf(), buf_len, 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &io_callback_); 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_REQUEST_SENT; 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::DoReadHeaders() { 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_READ_HEADERS_COMPLETE; 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Grow the read buffer if necessary. 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (read_buf_->RemainingCapacity() == 0) 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL. 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // See if the user is passing in an IOBuffer with a NULL |data_|. 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECK(read_buf_->data()); 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return connection_->socket()->Read(read_buf_, 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->RemainingCapacity(), 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &io_callback_); 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::DoReadHeadersComplete(int result) { 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == 0) 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = ERR_CONNECTION_CLOSED; 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0 && result != ERR_CONNECTION_CLOSED) { 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_DONE; 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == ERR_CONNECTION_CLOSED && read_buf_->offset() == 0 && 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott connection_->ShouldResendFailedRequest(result)) { 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_DONE; 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Record our best estimate of the 'response time' as the time when we read 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the first bytes of the response headers. 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (read_buf_->offset() == 0 && result != ERR_CONNECTION_CLOSED) 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_->response_time = base::Time::Now(); 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == ERR_CONNECTION_CLOSED) { 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The connection closed before we detected the end of the headers. 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // parse things as well as we can and let the caller decide what to do. 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (read_buf_->offset() == 0) { 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The connection was closed before any data was sent. Likely an error 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // rather than empty HTTP/0.9 response. 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_DONE; 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_EMPTY_RESPONSE; 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int end_offset; 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_header_start_offset_ >= 0) { 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_READ_BODY_COMPLETE; 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end_offset = read_buf_->offset(); 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_BODY_PENDING; 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end_offset = 0; 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoParseResponseHeaders(end_offset); 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->set_offset(read_buf_->offset() + result); 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_LE(read_buf_->offset(), read_buf_->capacity()); 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(result >= 0); 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int end_of_header_offset = ParseResponseHeaders(); 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (end_of_header_offset == -1) { 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_READ_HEADERS; 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Prevent growing the headers buffer indefinitely. 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (read_buf_->offset() - read_buf_unused_offset_ >= kMaxHeaderBufSize) { 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_DONE; 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_RESPONSE_HEADERS_TOO_BIG; 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note where the headers stop. 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_unused_offset_ = end_of_header_offset; 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_->headers->response_code() / 100 == 1) { 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // After processing a 1xx response, the caller will ask for the next 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // header, so reset state to support that. We don't just skip these 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // completely because 1xx codes aren't acceptable when establishing a 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // tunnel. 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_REQUEST_SENT; 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_header_start_offset_ = -1; 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_BODY_PENDING; 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CalculateResponseBodySize(); 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If the body is 0, the caller may not call ReadResponseBody, which 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // is where any extra data is copied to read_buf_, so we move the 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // data here and transition to DONE. 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_body_length_ == 0) { 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_DONE; 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int extra_bytes = read_buf_->offset() - read_buf_unused_offset_; 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (extra_bytes) { 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK_GT(extra_bytes, 0); 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memmove(read_buf_->StartOfBuffer(), 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->StartOfBuffer() + read_buf_unused_offset_, 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott extra_bytes); 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->SetCapacity(extra_bytes); 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_unused_offset_ = 0; 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::DoReadBody() { 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_READ_BODY_COMPLETE; 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // There may be some data left over from reading the response headers. 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (read_buf_->offset()) { 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int available = read_buf_->offset() - read_buf_unused_offset_; 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (available) { 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK_GT(available, 0); 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int bytes_from_buffer = std::min(available, user_read_buf_len_); 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(user_read_buf_->data(), 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->StartOfBuffer() + read_buf_unused_offset_, 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_from_buffer); 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_unused_offset_ += bytes_from_buffer; 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes_from_buffer == available) { 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->SetCapacity(0); 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_unused_offset_ = 0; 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return bytes_from_buffer; 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->SetCapacity(0); 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_unused_offset_ = 0; 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check to see if we're done reading. 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (IsResponseBodyComplete()) 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(0, read_buf_->offset()); 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return connection_->socket()->Read(user_read_buf_, user_read_buf_len_, 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &io_callback_); 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::DoReadBodyComplete(int result) { 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we didn't get a content-length and aren't using a chunked encoding, 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the only way to signal the end of a stream is to close the connection, 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so we don't treat that as an error, though in some cases we may not 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // have completely received the resource. 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (result == 0 && !IsResponseBodyComplete() && CanFindEndOfResponse()) 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = ERR_CONNECTION_CLOSED; 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Filter incoming data if appropriate. FilterBuf may return an error. 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result > 0 && chunked_decoder_.get()) { 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = chunked_decoder_->FilterBuf(user_read_buf_->data(), result); 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == 0 && !chunked_decoder_->reached_eof()) { 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Don't signal completion of the Read call yet or else it'll look like 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // we received end-of-file. Wait for more data. 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_READ_BODY; 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result > 0) 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_body_read_ += result; 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (result <= 0 || IsResponseBodyComplete()) { 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_DONE; 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Save the overflow data, which can be in two places. There may be 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // some left over in |user_read_buf_|, plus there may be more 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // in |read_buf_|. But the part left over in |user_read_buf_| must have 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // come from the |read_buf_|, so there's room to put it back at the 409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // start first. 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int additional_save_amount = read_buf_->offset() - read_buf_unused_offset_; 411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int save_amount = 0; 412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (chunked_decoder_.get()) { 413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott save_amount = chunked_decoder_->bytes_after_eof(); 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (response_body_length_ >= 0) { 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int64 extra_data_read = response_body_read_ - response_body_length_; 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (extra_data_read > 0) { 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott save_amount = static_cast<int>(extra_data_read); 418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result > 0) 419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result -= save_amount; 420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK_LE(save_amount + additional_save_amount, kMaxBufSize); 424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (read_buf_->capacity() < save_amount + additional_save_amount) { 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->SetCapacity(save_amount + additional_save_amount); 426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (save_amount) { 429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(read_buf_->StartOfBuffer(), user_read_buf_->data() + result, 430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott save_amount); 431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->set_offset(save_amount); 433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (additional_save_amount) { 434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memmove(read_buf_->data(), 435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->StartOfBuffer() + read_buf_unused_offset_, 436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott additional_save_amount); 437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->set_offset(save_amount + additional_save_amount); 438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_unused_offset_ = 0; 440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_state_ = STATE_BODY_PENDING; 442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_ = NULL; 443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_len_ = 0; 444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint HttpStreamParser::ParseResponseHeaders() { 450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int end_offset = -1; 451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Look for the start of the status line, if it hasn't been found yet. 453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_header_start_offset_ < 0) { 454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_header_start_offset_ = HttpUtil::LocateStartOfStatusLine( 455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->StartOfBuffer() + read_buf_unused_offset_, 456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->offset() - read_buf_unused_offset_); 457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_header_start_offset_ >= 0) { 460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end_offset = HttpUtil::LocateEndOfHeaders( 461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->StartOfBuffer() + read_buf_unused_offset_, 462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->offset() - read_buf_unused_offset_, 463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_header_start_offset_); 464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (read_buf_->offset() - read_buf_unused_offset_ >= 8) { 465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Enough data to decide that this is an HTTP/0.9 response. 466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 8 bytes = (4 bytes of junk) + "http".length() 467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end_offset = 0; 468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (end_offset == -1) 471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return -1; 472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoParseResponseHeaders(end_offset); 474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return end_offset + read_buf_unused_offset_; 475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpStreamParser::DoParseResponseHeaders(int end_offset) { 478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_refptr<HttpResponseHeaders> headers; 479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_header_start_offset_ >= 0) { 480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers = new HttpResponseHeaders(HttpUtil::AssembleRawHeaders( 481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_->StartOfBuffer() + read_buf_unused_offset_, end_offset)); 482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Enough data was read -- there is no status line. 484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK")); 485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_->headers = headers; 488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_->vary_data.Init(*request_, *response_->headers); 489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpStreamParser::CalculateResponseBodySize() { 492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Figure how to determine EOF: 493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // For certain responses, we know the content length is always 0. From 495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // RFC 2616 Section 4.3 Message Body: 496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // For response messages, whether or not a message-body is included with 498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // a message is dependent on both the request method and the response 499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // status code (section 6.1.1). All responses to the HEAD request method 500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // MUST NOT include a message-body, even though the presence of entity- 501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // header fields might lead one to believe they do. All 1xx 502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // (informational), 204 (no content), and 304 (not modified) responses 503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // MUST NOT include a message-body. All other responses do include a 504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // message-body, although it MAY be of zero length. 505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (response_->headers->response_code()) { 506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note that 1xx was already handled earlier. 507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 204: // No Content 508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 205: // Reset Content 509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 304: // Not Modified 510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_body_length_ = 0; 511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (request_->method == "HEAD") 514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_body_length_ = 0; 515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_body_length_ == -1) { 517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Ignore spurious chunked responses from HTTP/1.0 servers and 518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // proxies. Otherwise "Transfer-Encoding: chunked" trumps 519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // "Content-Length: N" 520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_->headers->GetHttpVersion() >= HttpVersion(1, 1) && 521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_->headers->HasHeaderValue("Transfer-Encoding", "chunked")) { 522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott chunked_decoder_.reset(new HttpChunkedDecoder()); 523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_body_length_ = response_->headers->GetContentLength(); 525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If response_body_length_ is still -1, then we have to wait 526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // for the server to close the connection. 527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottuint64 HttpStreamParser::GetUploadProgress() const { 532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!request_body_.get()) 533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return request_body_->position(); 536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHttpResponseInfo* HttpStreamParser::GetResponseInfo() { 539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return response_; 540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpStreamParser::IsResponseBodyComplete() const { 543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (chunked_decoder_.get()) 544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return chunked_decoder_->reached_eof(); 545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_body_length_ != -1) 546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return response_body_read_ >= response_body_length_; 547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; // Must read to EOF. 549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpStreamParser::CanFindEndOfResponse() const { 552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return chunked_decoder_.get() || response_body_length_ >= 0; 553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpStreamParser::IsMoreDataBuffered() const { 556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return read_buf_->offset() > read_buf_unused_offset_; 557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 560