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