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