15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_stream_parser.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 90529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/logging.h" 107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/ip_endpoint.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/upload_data_stream.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_chunked_decoder.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_request_headers.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_request_info.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_util.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/client_socket_handle.h" 217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "net/socket/ssl_client_socket.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace net { 240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaxMergedHeaderAndBodySize = 1400; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kRequestBodyBufferSize = 1 << 14; // 16KB 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochstd::string GetResponseHeaderLines(const HttpResponseHeaders& headers) { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string raw_headers = headers.raw_headers(); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* null_separated_headers = raw_headers.c_str(); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* header_line = null_separated_headers; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string cr_separated_headers; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (header_line[0] != 0) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cr_separated_headers += header_line; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cr_separated_headers += "\n"; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_line += strlen(header_line) + 1; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cr_separated_headers; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return true if |headers| contain multiple |field_name| fields with different 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// values. 450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool HeadersContainMultipleCopiesOfField(const HttpResponseHeaders& headers, 460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::string& field_name) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* it = NULL; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string field_value; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!headers.EnumerateHeader(&it, field_name, &field_value)) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There's at least one |field_name| header. Check if there are any more 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // such headers, and if so, return true if they have different values. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string field_value2; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (headers.EnumerateHeader(&it, field_name, &field_value2)) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (field_value != field_value2) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbase::Value* NetLogSendRequestBodyCallback(int length, 620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool is_chunked, 630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool did_merge, 640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch NetLog::LogLevel /* log_level */) { 657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::DictionaryValue* dict = new base::DictionaryValue(); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("length", length); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetBoolean("is_chunked", is_chunked); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetBoolean("did_merge", did_merge); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dict; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Returns true if |error_code| is an error for which we give the server a 730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// chance to send a body containing error information, if the error was received 740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// while trying to upload a request body. 750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool ShouldTryReadingOnUploadError(int error_code) { 760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return (error_code == ERR_CONNECTION_RESET); 770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} // namespace 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Similar to DrainableIOBuffer(), but this version comes with its own 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// storage. The motivation is to avoid repeated allocations of 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DrainableIOBuffer. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Example: 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// scoped_refptr<SeekableIOBuffer> buf = new SeekableIOBuffer(1024); 884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// // capacity() == 1024. size() == BytesRemaining() == BytesConsumed() == 0. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// // data() points to the beginning of the buffer. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// // Read() takes an IOBuffer. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// int bytes_read = some_reader->Read(buf, buf->capacity()); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// buf->DidAppend(bytes_read); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// // size() == BytesRemaining() == bytes_read. data() is unaffected. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// while (buf->BytesRemaining() > 0) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// // Write() takes an IOBuffer. If it takes const char*, we could 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// // simply use the regular IOBuffer like buf->data() + offset. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// int bytes_written = Write(buf, buf->BytesRemaining()); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// buf->DidConsume(bytes_written); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// // BytesRemaining() == 0. BytesConsumed() == size(). 1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// // data() points to the end of the consumed bytes (exclusive). 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// // If you want to reuse the buffer, be sure to clear the buffer. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// buf->Clear(); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// // size() == BytesRemaining() == BytesConsumed() == 0. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// // data() points to the beginning of the buffer. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochclass HttpStreamParser::SeekableIOBuffer : public IOBuffer { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit SeekableIOBuffer(int capacity) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : IOBuffer(capacity), 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) real_data_(data_), 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) capacity_(capacity), 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_(0), 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) used_(0) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DidConsume() changes the |data_| pointer so that |data_| always points 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to the first unconsumed byte. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DidConsume(int bytes) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetOffset(used_ + bytes); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the number of unconsumed bytes. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int BytesRemaining() const { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return size_ - used_; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Seeks to an arbitrary point in the buffer. The notion of bytes consumed 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and remaining are updated appropriately. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetOffset(int bytes) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(bytes, 0); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(bytes, size_); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) used_ = bytes; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_ = real_data_ + used_; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called after data is added to the buffer. Adds |bytes| added to 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |size_|. data() is unaffected. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DidAppend(int bytes) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(bytes, 0); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(size_ + bytes, 0); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(size_ + bytes, capacity_); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_ += bytes; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Changes the logical size to 0, and the offset to 0. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Clear() { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_ = 0; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetOffset(0); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the logical size of the buffer (i.e the number of bytes of data 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in the buffer). 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int size() const { return size_; } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the capacity of the buffer. The capacity is the size used when 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the object is created. 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int capacity() const { return capacity_; }; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~SeekableIOBuffer() { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // data_ will be deleted in IOBuffer::~IOBuffer(). 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_ = real_data_; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* real_data_; 1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const int capacity_; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int size_; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int used_; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2 CRLFs + max of 8 hex chars. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t HttpStreamParser::kChunkHeaderFooterSize = 12; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection, 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const HttpRequestInfo* request, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GrowableIOBuffer* read_buffer, 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BoundNetLog& net_log) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : io_state_(STATE_NONE), 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_(request), 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_headers_(NULL), 1850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch request_headers_length_(0), 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_(read_buffer), 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_unused_offset_(0), 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_header_start_offset_(-1), 189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) received_bytes_(0), 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_body_length_(-1), 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_body_read_(0), 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_read_buf_(NULL), 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_read_buf_len_(0), 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connection_(connection), 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_(net_log), 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sent_last_chunk_(false), 1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch upload_error_(OK), 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_(this) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_callback_ = base::Bind(&HttpStreamParser::OnIOComplete, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr()); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpStreamParser::~HttpStreamParser() { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpStreamParser::SendRequest(const std::string& request_line, 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const HttpRequestHeaders& headers, 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpResponseInfo* response, 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(STATE_NONE, io_state_); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(callback_.is_null()); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback.is_null()); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(response); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent( 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS, 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&HttpRequestHeaders::NetLogCallback, 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(&headers), 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &request_line)); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << __FUNCTION__ << "()" 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " request_line = \"" << request_line << "\"" 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " headers = \"" << headers.ToString() << "\""; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_ = response; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Put the peer's IP address and port into the response. 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPEndPoint ip_endpoint; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = connection_->socket()->GetPeerAddress(&ip_endpoint); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != OK) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_->socket_address = HostPortPair::FromIPEndPoint(ip_endpoint); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string request = request_line + headers.ToString(); 2340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch request_headers_length_ = request.size(); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (request_->upload_data_stream != NULL) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_send_buf_ = new SeekableIOBuffer(kRequestBodyBufferSize); 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (request_->upload_data_stream->is_chunked()) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read buffer is adjusted to guarantee that |request_body_send_buf_| is 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // large enough to hold the encoded chunk. 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_read_buf_ = 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new SeekableIOBuffer(kRequestBodyBufferSize - kChunkHeaderFooterSize); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No need to encode request body, just send the raw data. 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_read_buf_ = request_body_send_buf_; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_SEND_HEADERS; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we have a small request body, then we'll merge with the headers into a 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // single write. 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool did_merge = false; 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (ShouldMergeRequestHeadersAndBody(request, request_->upload_data_stream)) { 2550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch size_t merged_size = 2560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch request_headers_length_ + request_->upload_data_stream->size(); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<IOBuffer> merged_request_headers_and_body( 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new IOBuffer(merged_size)); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We'll repurpose |request_headers_| to store the merged headers and 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // body. 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_headers_ = new DrainableIOBuffer( 262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) merged_request_headers_and_body.get(), merged_size); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch memcpy(request_headers_->data(), request.data(), request_headers_length_); 2650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch request_headers_->DidConsume(request_headers_length_); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t todo = request_->upload_data_stream->size(); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (todo) { 269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int consumed = request_->upload_data_stream 270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ->Read(request_headers_.get(), todo, CompletionCallback()); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(consumed, 0); // Read() won't fail if not chunked. 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_headers_->DidConsume(consumed); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) todo -= consumed; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(request_->upload_data_stream->IsEOF()); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset the offset, so the buffer can be read from the beginning. 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_headers_->SetOffset(0); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) did_merge = true; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent( 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_BODY, 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&NetLogSendRequestBodyCallback, 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_->upload_data_stream->size(), 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, /* not chunked */ 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true /* merged */)); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!did_merge) { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we didn't merge the body with the headers, then |request_headers_| 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // contains just the HTTP headers. 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<StringIOBuffer> headers_io_buf(new StringIOBuffer(request)); 292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) request_headers_ = 293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) new DrainableIOBuffer(headers_io_buf.get(), headers_io_buf->size()); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = DoLoop(OK); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == ERR_IO_PENDING) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_ = callback; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result > 0 ? OK : result; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpStreamParser::ReadResponseHeaders(const CompletionCallback& callback) { 3040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(io_state_ == STATE_NONE || io_state_ == STATE_DONE); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(callback_.is_null()); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback.is_null()); 3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK_EQ(0, read_buf_unused_offset_); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This function can be called with io_state_ == STATE_DONE if the 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // connection is closed after seeing just a 1xx response code. 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (io_state_ == STATE_DONE) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CONNECTION_CLOSED; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = OK; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_state_ = STATE_READ_HEADERS; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (read_buf_->offset() > 0) { 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Simulate the state where the data was just read from the socket. 3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) result = read_buf_->offset(); 3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) read_buf_->set_offset(0); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result > 0) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_state_ = STATE_READ_HEADERS_COMPLETE; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = DoLoop(result); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == ERR_IO_PENDING) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_ = callback; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result > 0 ? OK : result; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpStreamParser::Close(bool not_reusable) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (not_reusable && connection_->socket()) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connection_->socket()->Disconnect(); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connection_->Reset(); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpStreamParser::ReadResponseBody(IOBuffer* buf, int buf_len, 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 3400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(io_state_ == STATE_NONE || io_state_ == STATE_DONE); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(callback_.is_null()); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback.is_null()); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(buf_len, kMaxBufSize); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (io_state_ == STATE_DONE) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_read_buf_ = buf; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_read_buf_len_ = buf_len; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_state_ = STATE_READ_BODY; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = DoLoop(OK); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == ERR_IO_PENDING) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_ = callback; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpStreamParser::OnIOComplete(int result) { 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = DoLoop(result); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The client callback can do anything, including destroying this class, 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so any pending callback must be issued after everything else is done. 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != ERR_IO_PENDING && !callback_.is_null()) { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompletionCallback c = callback_; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_.Reset(); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c.Run(result); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpStreamParser::DoLoop(int result) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 3730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_NE(ERR_IO_PENDING, result); 3740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_NE(STATE_DONE, io_state_); 3750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_NE(STATE_NONE, io_state_); 3760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch State state = io_state_; 3770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_NONE; 3780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch switch (state) { 3790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case STATE_SEND_HEADERS: 3800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_EQ(OK, result); 3810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch result = DoSendHeaders(); 3820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch break; 3830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case STATE_SEND_HEADERS_COMPLETE: 3840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch result = DoSendHeadersComplete(result); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case STATE_SEND_BODY: 3870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_EQ(OK, result); 3880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch result = DoSendBody(); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case STATE_SEND_BODY_COMPLETE: 3910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch result = DoSendBodyComplete(result); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case STATE_SEND_REQUEST_READ_BODY_COMPLETE: 3940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch result = DoSendRequestReadBodyComplete(result); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_READ_HEADERS: 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_PARSER_READ_HEADERS); 3980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_GE(result, 0); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = DoReadHeaders(); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_READ_HEADERS_COMPLETE: 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = DoReadHeadersComplete(result); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode( 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_HTTP_STREAM_PARSER_READ_HEADERS, result); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_READ_BODY: 4070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_GE(result, 0); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = DoReadBody(); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_READ_BODY_COMPLETE: 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = DoReadBodyComplete(result); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } while (result != ERR_IO_PENDING && 4180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (io_state_ != STATE_DONE && io_state_ != STATE_NONE)); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint HttpStreamParser::DoSendHeaders() { 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_remaining = request_headers_->BytesRemaining(); 4250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_GT(bytes_remaining, 0); 4260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Record our best estimate of the 'request time' as the time when we send 4280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // out the first bytes of the request headers. 4290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (bytes_remaining == request_headers_->size()) 4300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch response_->request_time = base::Time::Now(); 4310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_SEND_HEADERS_COMPLETE; 4330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return connection_->socket() 4340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ->Write(request_headers_.get(), bytes_remaining, io_callback_); 4350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 4360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint HttpStreamParser::DoSendHeadersComplete(int result) { 4380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (result < 0) { 4390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // In the unlikely case that the headers and body were merged, all the 4400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // the headers were sent, but not all of the body way, and |result| is 4410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // an error that this should try reading after, stash the error for now and 4420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // act like the request was successfully sent. 4430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (request_headers_->BytesConsumed() >= request_headers_length_ && 4440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ShouldTryReadingOnUploadError(result)) { 4450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch upload_error_ = result; 4460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return OK; 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return result; 4490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch request_headers_->DidConsume(result); 4520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (request_headers_->BytesRemaining() > 0) { 4530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_SEND_HEADERS; 4540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return OK; 4550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (request_->upload_data_stream != NULL && 4580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (request_->upload_data_stream->is_chunked() || 4590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // !IsEOF() indicates that the body wasn't merged. 4600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (request_->upload_data_stream->size() > 0 && 4610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch !request_->upload_data_stream->IsEOF()))) { 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent( 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_BODY, 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&NetLogSendRequestBodyCallback, 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_->upload_data_stream->size(), 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_->upload_data_stream->is_chunked(), 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false /* not merged */)); 4680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_SEND_BODY; 4690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return OK; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Finished sending the request. 4730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return OK; 4740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint HttpStreamParser::DoSendBody() { 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request_body_send_buf_->BytesRemaining() > 0) { 4780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_SEND_BODY_COMPLETE; 479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return connection_->socket() 480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ->Write(request_body_send_buf_.get(), 481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) request_body_send_buf_->BytesRemaining(), 482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) io_callback_); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (request_->upload_data_stream->is_chunked() && sent_last_chunk_) { 4860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Finished sending the request. 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_read_buf_->Clear(); 4910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_SEND_REQUEST_READ_BODY_COMPLETE; 492868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return request_->upload_data_stream->Read(request_body_read_buf_.get(), 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_body_read_buf_->capacity(), 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) io_callback_); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint HttpStreamParser::DoSendBodyComplete(int result) { 4980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (result < 0) { 4990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // If |result| is an error that this should try reading after, stash the 5000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // error for now and act like the request was successfully sent. 5010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (ShouldTryReadingOnUploadError(result)) { 5020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch upload_error_ = result; 5030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return OK; 5040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 5050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return result; 5060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 5070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch request_body_send_buf_->DidConsume(result); 5090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_SEND_BODY; 5110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return OK; 5120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 5130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint HttpStreamParser::DoSendRequestReadBodyComplete(int result) { 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |result| is the result of read from the request body from the last call to 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DoSendBody(). 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(result, 0); // There won't be errors. 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chunked data needs to be encoded. 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (request_->upload_data_stream->is_chunked()) { 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == 0) { // Reached the end. 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(request_->upload_data_stream->IsEOF()); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sent_last_chunk_ = true; 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Encode the buffer as 1 chunk. 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::StringPiece payload(request_body_read_buf_->data(), result); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_send_buf_->Clear(); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = EncodeChunk(payload, 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_send_buf_->data(), 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_send_buf_->capacity()); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == 0) { // Reached the end. 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reaching EOF means we can finish sending request body unless the data is 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // chunked. (i.e. No need to send the terminal chunk.) 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(request_->upload_data_stream->IsEOF()); 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!request_->upload_data_stream->is_chunked()); 5380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Finished sending the request. 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (result > 0) { 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body_send_buf_->DidAppend(result); 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = 0; 5420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_SEND_BODY; 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpStreamParser::DoReadHeaders() { 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_state_ = STATE_READ_HEADERS_COMPLETE; 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Grow the read buffer if necessary. 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (read_buf_->RemainingCapacity() == 0) 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL. 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See if the user is passing in an IOBuffer with a NULL |data_|. 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(read_buf_->data()); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return connection_->socket() 559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ->Read(read_buf_.get(), read_buf_->RemainingCapacity(), io_callback_); 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpStreamParser::DoReadHeadersComplete(int result) { 5630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch result = HandleReadHeaderResult(result); 5644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 5650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // TODO(mmenke): The code below is ugly and hacky. A much better and more 5660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // flexible long term solution would be to separate out the read and write 5670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // loops, though this would involve significant changes, both here and 5680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // elsewhere (WebSockets, for instance). 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // If still reading the headers, or there was no error uploading the request 5710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // body, just return the result. 5720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (io_state_ == STATE_READ_HEADERS || upload_error_ == OK) 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 5740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // If the result is ERR_IO_PENDING, |io_state_| should be STATE_READ_HEADERS. 5760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_NE(ERR_IO_PENDING, result); 5770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 5780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // On errors, use the original error received when sending the request. 5790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // The main cases where these are different is when there's a header-related 5800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // error code, or when there's an ERR_CONNECTION_CLOSED, which can result in 5810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // special handling of partial responses and HTTP/0.9 responses. 5820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (result < 0) { 5830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Nothing else to do. In the HTTP/0.9 or only partial headers received 5840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // cases, can normally go to other states after an error reading headers. 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_state_ = STATE_DONE; 5860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Don't let caller see the headers. 5870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch response_->headers = NULL; 5880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return upload_error_; 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Skip over 1xx responses as usual, and allow 4xx/5xx error responses to 5920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // override the error received while uploading the body. 5930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int response_code_class = response_->headers->response_code() / 100; 5940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (response_code_class == 1 || response_code_class == 4 || 5950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch response_code_class == 5) { 596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return result; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // All other status codes are not allowed after an error during upload, to 6000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // make sure the consumer has some indication there was an error. 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Nothing else to do. 6030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_DONE; 6040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Don't let caller see the headers. 6050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch response_->headers = NULL; 6060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return upload_error_; 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpStreamParser::DoReadBody() { 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_state_ = STATE_READ_BODY_COMPLETE; 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There may be some data left over from reading the response headers. 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (read_buf_->offset()) { 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int available = read_buf_->offset() - read_buf_unused_offset_; 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (available) { 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_GT(available, 0); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_from_buffer = std::min(available, user_read_buf_len_); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(user_read_buf_->data(), 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_->StartOfBuffer() + read_buf_unused_offset_, 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_from_buffer); 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_unused_offset_ += bytes_from_buffer; 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_from_buffer == available) { 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_->SetCapacity(0); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_unused_offset_ = 0; 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bytes_from_buffer; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_->SetCapacity(0); 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_unused_offset_ = 0; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check to see if we're done reading. 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsResponseBodyComplete()) 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(0, read_buf_->offset()); 638868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return connection_->socket() 639868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ->Read(user_read_buf_.get(), user_read_buf_len_, io_callback_); 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpStreamParser::DoReadBodyComplete(int result) { 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When the connection is closed, there are numerous ways to interpret it. 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - If a Content-Length header is present and the body contains exactly that 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // number of bytes at connection close, the response is successful. 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - If a Content-Length header is present and the body contains fewer bytes 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // than promised by the header at connection close, it may indicate that 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the connection was closed prematurely, or it may indicate that the 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // server sent an invalid Content-Length header. Unfortunately, the invalid 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Content-Length header case does occur in practice and other browsers are 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tolerant of it. We choose to treat it as an error for now, but the 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // download system treats it as a non-error, and URLRequestHttpJob also 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // treats it as OK if the Content-Length is the post-decoded body content 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // length. 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - If chunked encoding is used and the terminating chunk has been processed 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when the connection is closed, the response is successful. 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - If chunked encoding is used and the terminating chunk has not been 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // processed when the connection is closed, it may indicate that the 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // connection was closed prematurely or it may indicate that the server 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sent an invalid chunked encoding. We choose to treat it as 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an invalid chunked encoding. 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - If a Content-Length is not present and chunked encoding is not used, 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // connection close is the only way to signal that the response is 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // complete. Unfortunately, this also means that there is no way to detect 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // early close of a connection. No error is returned. 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == 0 && !IsResponseBodyComplete() && CanFindEndOfResponse()) { 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chunked_decoder_.get()) 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = ERR_INCOMPLETE_CHUNKED_ENCODING; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = ERR_CONTENT_LENGTH_MISMATCH; 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 678a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (result > 0) 679a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) received_bytes_ += result; 680a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Filter incoming data if appropriate. FilterBuf may return an error. 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result > 0 && chunked_decoder_.get()) { 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = chunked_decoder_->FilterBuf(user_read_buf_->data(), result); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == 0 && !chunked_decoder_->reached_eof()) { 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't signal completion of the Read call yet or else it'll look like 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we received end-of-file. Wait for more data. 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_state_ = STATE_READ_BODY; 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result > 0) 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_body_read_ += result; 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result <= 0 || IsResponseBodyComplete()) { 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_state_ = STATE_DONE; 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the overflow data, which can be in two places. There may be 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // some left over in |user_read_buf_|, plus there may be more 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in |read_buf_|. But the part left over in |user_read_buf_| must have 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // come from the |read_buf_|, so there's room to put it back at the 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // start first. 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int additional_save_amount = read_buf_->offset() - read_buf_unused_offset_; 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int save_amount = 0; 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chunked_decoder_.get()) { 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_amount = chunked_decoder_->bytes_after_eof(); 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (response_body_length_ >= 0) { 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 extra_data_read = response_body_read_ - response_body_length_; 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extra_data_read > 0) { 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_amount = static_cast<int>(extra_data_read); 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result > 0) 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result -= save_amount; 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LE(save_amount + additional_save_amount, kMaxBufSize); 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (read_buf_->capacity() < save_amount + additional_save_amount) { 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_->SetCapacity(save_amount + additional_save_amount); 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (save_amount) { 722a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) received_bytes_ -= save_amount; 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(read_buf_->StartOfBuffer(), user_read_buf_->data() + result, 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_amount); 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_->set_offset(save_amount); 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (additional_save_amount) { 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memmove(read_buf_->data(), 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_->StartOfBuffer() + read_buf_unused_offset_, 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) additional_save_amount); 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_->set_offset(save_amount + additional_save_amount); 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_unused_offset_ = 0; 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Now waiting for more of the body to be read. 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_read_buf_ = NULL; 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_read_buf_len_ = 0; 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint HttpStreamParser::HandleReadHeaderResult(int result) { 7440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_EQ(0, read_buf_unused_offset_); 7450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 7460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (result == 0) 7470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch result = ERR_CONNECTION_CLOSED; 7480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 7490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (result < 0 && result != ERR_CONNECTION_CLOSED) { 7500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_DONE; 7510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return result; 7520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 7530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // If we've used the connection before, then we know it is not a HTTP/0.9 7540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // response and return ERR_CONNECTION_CLOSED. 7550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (result == ERR_CONNECTION_CLOSED && read_buf_->offset() == 0 && 7560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch connection_->is_reused()) { 7570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_DONE; 7580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return result; 7590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 7600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 7610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Record our best estimate of the 'response time' as the time when we read 7620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // the first bytes of the response headers. 7630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (read_buf_->offset() == 0 && result != ERR_CONNECTION_CLOSED) 7640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch response_->response_time = base::Time::Now(); 7650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 7660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (result == ERR_CONNECTION_CLOSED) { 7670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // The connection closed before we detected the end of the headers. 7680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (read_buf_->offset() == 0) { 7690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // The connection was closed before any data was sent. Likely an error 7700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // rather than empty HTTP/0.9 response. 7710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_DONE; 7720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return ERR_EMPTY_RESPONSE; 7730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else if (request_->url.SchemeIsSecure()) { 7740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // The connection was closed in the middle of the headers. For HTTPS we 7750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // don't parse partial headers. Return a different error code so that we 7760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // know that we shouldn't attempt to retry the request. 7770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_DONE; 7780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return ERR_RESPONSE_HEADERS_TRUNCATED; 7790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 7800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Parse things as well as we can and let the caller decide what to do. 7810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int end_offset; 7820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (response_header_start_offset_ >= 0) { 7830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_READ_BODY_COMPLETE; 7840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch end_offset = read_buf_->offset(); 7850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 7860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Now waiting for the body to be read. 7870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch end_offset = 0; 7880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 7890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int rv = DoParseResponseHeaders(end_offset); 7900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (rv < 0) 7910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return rv; 7920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return result; 7930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 7940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 7950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch read_buf_->set_offset(read_buf_->offset() + result); 7960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_LE(read_buf_->offset(), read_buf_->capacity()); 7970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_GE(result, 0); 7980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 7990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int end_of_header_offset = ParseResponseHeaders(); 8000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Note: -1 is special, it indicates we haven't found the end of headers. 8020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Anything less than -1 is a net::Error, so we bail out. 8030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (end_of_header_offset < -1) 8040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return end_of_header_offset; 8050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (end_of_header_offset == -1) { 8070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_READ_HEADERS; 8080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Prevent growing the headers buffer indefinitely. 8090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (read_buf_->offset() >= kMaxHeaderBufSize) { 8100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_DONE; 8110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return ERR_RESPONSE_HEADERS_TOO_BIG; 8120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 8130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 8140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CalculateResponseBodySize(); 8150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // If the body is zero length, the caller may not call ReadResponseBody, 8160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // which is where any extra data is copied to read_buf_, so we move the 8170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // data here. 8180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (response_body_length_ == 0) { 8190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int extra_bytes = read_buf_->offset() - end_of_header_offset; 8200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (extra_bytes) { 8210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CHECK_GT(extra_bytes, 0); 8220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch memmove(read_buf_->StartOfBuffer(), 8230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch read_buf_->StartOfBuffer() + end_of_header_offset, 8240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch extra_bytes); 8250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 8260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch read_buf_->SetCapacity(extra_bytes); 8270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (response_->headers->response_code() / 100 == 1) { 8280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // After processing a 1xx response, the caller will ask for the next 8290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // header, so reset state to support that. We don't completely ignore a 8300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // 1xx response because it cannot be returned in reply to a CONNECT 8310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // request so we return OK here, which lets the caller inspect the 8320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // response and reject it in the event that we're setting up a CONNECT 8330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // tunnel. 8340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch response_header_start_offset_ = -1; 8350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch response_body_length_ = -1; 8360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Now waiting for the second set of headers to be read. 8370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 8380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch io_state_ = STATE_DONE; 8390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 8400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return OK; 8410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 8420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Note where the headers stop. 8440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch read_buf_unused_offset_ = end_of_header_offset; 8450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Now waiting for the body to be read. 8460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 8470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return result; 8480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 8490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpStreamParser::ParseResponseHeaders() { 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int end_offset = -1; 8524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK_EQ(0, read_buf_unused_offset_); 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Look for the start of the status line, if it hasn't been found yet. 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_header_start_offset_ < 0) { 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_header_start_offset_ = HttpUtil::LocateStartOfStatusLine( 8574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) read_buf_->StartOfBuffer(), read_buf_->offset()); 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_header_start_offset_ >= 0) { 8614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) end_offset = HttpUtil::LocateEndOfHeaders(read_buf_->StartOfBuffer(), 8624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) read_buf_->offset(), 8634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) response_header_start_offset_); 8644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (read_buf_->offset() >= 8) { 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Enough data to decide that this is an HTTP/0.9 response. 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 8 bytes = (4 bytes of junk) + "http".length() 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) end_offset = 0; 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (end_offset == -1) 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = DoParseResponseHeaders(end_offset); 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv < 0) 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 8764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return end_offset; 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpStreamParser::DoParseResponseHeaders(int end_offset) { 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<HttpResponseHeaders> headers; 8814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK_EQ(0, read_buf_unused_offset_); 8824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_header_start_offset_ >= 0) { 884a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) received_bytes_ += end_offset; 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) headers = new HttpResponseHeaders(HttpUtil::AssembleRawHeaders( 8864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) read_buf_->StartOfBuffer(), end_offset)); 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Enough data was read -- there is no status line. 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK")); 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for multiple Content-Length headers with no Transfer-Encoding header. 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If they exist, and have distinct values, it's a potential response 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // smuggling attack. 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!headers->HasHeader("Transfer-Encoding")) { 896868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (HeadersContainMultipleCopiesOfField(*headers.get(), "Content-Length")) 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH; 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for multiple Content-Disposition or Location headers. If they exist, 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it's also a potential response smuggling attack. 902868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (HeadersContainMultipleCopiesOfField(*headers.get(), 903868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "Content-Disposition")) 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION; 905868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (HeadersContainMultipleCopiesOfField(*headers.get(), "Location")) 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION; 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_->headers = headers; 9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_->connection_info = HttpResponseInfo::CONNECTION_INFO_HTTP1; 910868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) response_->vary_data.Init(*request_, *response_->headers.get()); 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << __FUNCTION__ << "()" 912868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) << " content_length = \"" << response_->headers->GetContentLength() 913868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) << "\n\"" 914868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) << " headers = \"" 915868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) << GetResponseHeaderLines(*response_->headers.get()) << "\""; 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpStreamParser::CalculateResponseBodySize() { 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Figure how to determine EOF: 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For certain responses, we know the content length is always 0. From 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RFC 2616 Section 4.3 Message Body: 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For response messages, whether or not a message-body is included with 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a message is dependent on both the request method and the response 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // status code (section 6.1.1). All responses to the HEAD request method 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // MUST NOT include a message-body, even though the presence of entity- 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // header fields might lead one to believe they do. All 1xx 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (informational), 204 (no content), and 304 (not modified) responses 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // MUST NOT include a message-body. All other responses do include a 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // message-body, although it MAY be of zero length. 9334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (response_->headers->response_code() / 100 == 1) { 9344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) response_body_length_ = 0; 9354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 9364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) switch (response_->headers->response_code()) { 9374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case 204: // No Content 9384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case 205: // Reset Content 9394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case 304: // Not Modified 9404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) response_body_length_ = 0; 9414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 9424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request_->method == "HEAD") 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_body_length_ = 0; 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_body_length_ == -1) { 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "Transfer-Encoding: chunked" trumps "Content-Length: N" 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_->headers->IsChunkEncoded()) { 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chunked_decoder_.reset(new HttpChunkedDecoder()); 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_body_length_ = response_->headers->GetContentLength(); 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If response_body_length_ is still -1, then we have to wait 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for the server to close the connection. 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UploadProgress HttpStreamParser::GetUploadProgress() const { 9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!request_->upload_data_stream) 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return UploadProgress(); 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return UploadProgress(request_->upload_data_stream->position(), 9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_->upload_data_stream->size()); 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpStreamParser::IsResponseBodyComplete() const { 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chunked_decoder_.get()) 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return chunked_decoder_->reached_eof(); 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_body_length_ != -1) 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return response_body_read_ >= response_body_length_; 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Must read to EOF. 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpStreamParser::CanFindEndOfResponse() const { 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return chunked_decoder_.get() || response_body_length_ >= 0; 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpStreamParser::IsMoreDataBuffered() const { 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return read_buf_->offset() > read_buf_unused_offset_; 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpStreamParser::IsConnectionReused() const { 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSocketHandle::SocketReuseType reuse_type = connection_->reuse_type(); 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return connection_->is_reused() || 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reuse_type == ClientSocketHandle::UNUSED_IDLE; 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpStreamParser::SetConnectionReused() { 99123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) connection_->set_reuse_type(ClientSocketHandle::REUSED_IDLE); 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpStreamParser::IsConnectionReusable() const { 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return connection_->socket() && connection_->socket()->IsConnectedAndIdle(); 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpStreamParser::GetSSLInfo(SSLInfo* ssl_info) { 9997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (request_->url.SchemeIsSecure() && connection_->socket()) { 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLClientSocket* ssl_socket = 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<SSLClientSocket*>(connection_->socket()); 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_socket->GetSSLInfo(ssl_info); 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpStreamParser::GetSSLCertRequestInfo( 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLCertRequestInfo* cert_request_info) { 10087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (request_->url.SchemeIsSecure() && connection_->socket()) { 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLClientSocket* ssl_socket = 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<SSLClientSocket*>(connection_->socket()); 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_socket->GetSSLCertRequestInfo(cert_request_info); 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpStreamParser::EncodeChunk(const base::StringPiece& payload, 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* output, 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t output_size) { 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (output_size < payload.size() + kChunkHeaderFooterSize) 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_INVALID_ARGUMENT; 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* cursor = output; 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the header. 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int num_chars = base::snprintf(output, output_size, 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%X\r\n", 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(payload.size())); 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor += num_chars; 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the payload if any. 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (payload.size() > 0) { 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(cursor, payload.data(), payload.size()); 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor += payload.size(); 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the trailing CRLF. 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(cursor, "\r\n", 2); 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor += 2; 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cursor - output; 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpStreamParser::ShouldMergeRequestHeadersAndBody( 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& request_headers, 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const UploadDataStream* request_body) { 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request_body != NULL && 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IsInMemory() ensures that the request body is not chunked. 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body->IsInMemory() && 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_body->size() > 0) { 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t merged_size = request_headers.size() + request_body->size(); 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (merged_size <= kMaxMergedHeaderAndBodySize) 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 1055