diff options
Diffstat (limited to 'net/http/http_stream_parser.cc')
-rw-r--r-- | net/http/http_stream_parser.cc | 56 |
1 files changed, 38 insertions, 18 deletions
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc index dcde04f..aa8eaad 100644 --- a/net/http/http_stream_parser.cc +++ b/net/http/http_stream_parser.cc @@ -6,7 +6,6 @@ #include "base/compiler_specific.h" #include "base/metrics/histogram.h" -#include "base/stringprintf.h" #include "base/string_util.h" #include "net/base/address_list.h" #include "net/base/auth.h" @@ -63,6 +62,9 @@ bool HeadersContainMultipleCopiesOfField( namespace net { +// 2 CRLFs + max of 8 hex chars. +const size_t HttpStreamParser::kChunkHeaderFooterSize = 12; + HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection, const HttpRequestInfo* request, GrowableIOBuffer* read_buffer, @@ -85,6 +87,8 @@ HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection, io_callback_( base::Bind(&HttpStreamParser::OnIOComplete, base::Unretained(this)))), + chunk_buffer_size_(UploadDataStream::GetBufferSize() + + kChunkHeaderFooterSize), chunk_length_(0), chunk_length_without_encoding_(0), sent_last_chunk_(false) { @@ -127,9 +131,7 @@ int HttpStreamParser::SendRequest(const std::string& request_line, request_body_.reset(request_body); if (request_body_ != NULL && request_body_->is_chunked()) { request_body_->set_chunk_callback(this); - const int kChunkHeaderFooterSize = 12; // 2 CRLFs + max of 8 hex chars. - chunk_buf_ = new IOBuffer(request_body_->GetMaxBufferSize() + - kChunkHeaderFooterSize); + chunk_buf_ = new IOBuffer(chunk_buffer_size_); } io_state_ = STATE_SENDING_HEADERS; @@ -359,23 +361,17 @@ int HttpStreamParser::DoSendBody(int result) { request_body_->MarkConsumedAndFillBuffer(chunk_length_without_encoding_); chunk_length_without_encoding_ = 0; - int buf_len = static_cast<int>(request_body_->buf_len()); if (request_body_->eof()) { - static const char kLastChunk[] = "0\r\n\r\n"; - chunk_length_ = strlen(kLastChunk); - memcpy(chunk_buf_->data(), kLastChunk, chunk_length_); + chunk_length_ = EncodeChunk( + base::StringPiece(), chunk_buf_->data(), chunk_buffer_size_); sent_last_chunk_ = true; - } else if (buf_len) { + } else if (request_body_->buf_len() > 0) { // Encode and send the buffer as 1 chunk. - std::string chunk_header = StringPrintf("%X\r\n", buf_len); - char* chunk_ptr = chunk_buf_->data(); - memcpy(chunk_ptr, chunk_header.data(), chunk_header.length()); - chunk_ptr += chunk_header.length(); - memcpy(chunk_ptr, request_body_->buf()->data(), buf_len); - chunk_ptr += buf_len; - memcpy(chunk_ptr, "\r\n", 2); - chunk_length_without_encoding_ = buf_len; - chunk_length_ = chunk_header.length() + buf_len + 2; + const base::StringPiece payload(request_body_->buf()->data(), + request_body_->buf_len()); + chunk_length_ = EncodeChunk(payload, chunk_buf_->data(), + chunk_buffer_size_); + chunk_length_without_encoding_ = payload.size(); } else { // Nothing to send. More POST data is yet to come? return ERR_IO_PENDING; @@ -783,4 +779,28 @@ void HttpStreamParser::GetSSLCertRequestInfo( } } +int HttpStreamParser::EncodeChunk(const base::StringPiece& payload, + char* output, + size_t output_size) { + if (output_size < payload.size() + kChunkHeaderFooterSize) + return ERR_INVALID_ARGUMENT; + + char* cursor = output; + // Add the header. + const int num_chars = base::snprintf(output, output_size, + "%X\r\n", + static_cast<int>(payload.size())); + cursor += num_chars; + // Add the payload if any. + if (payload.size() > 0) { + memcpy(cursor, payload.data(), payload.size()); + cursor += payload.size(); + } + // Add the trailing CRLF. + memcpy(cursor, "\r\n", 2); + cursor += 2; + + return cursor - output; +} + } // namespace net |