diff options
author | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-19 15:13:08 +0000 |
---|---|---|
committer | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-19 15:13:08 +0000 |
commit | d7f5ecd6dc2156872e641cf892a39a3d6b62d386 (patch) | |
tree | 3ee768538c2a7fc8decac8f8d8a389f9d8b2b3c7 /net/http | |
parent | 91ee3680d8087a7877a866114df12842a95a3229 (diff) | |
download | chromium_src-d7f5ecd6dc2156872e641cf892a39a3d6b62d386.zip chromium_src-d7f5ecd6dc2156872e641cf892a39a3d6b62d386.tar.gz chromium_src-d7f5ecd6dc2156872e641cf892a39a3d6b62d386.tar.bz2 |
Revert 118265 (added a static initializer on linux)
- Factor out chunk encoding logic into HttpStreamParser::EncodeChunk().
The logic is meaty enough to be factored out.
Add unit tests along the way.
BUG=72001
TEST=add unit tests.
Review URL: http://codereview.chromium.org/9242018
TBR=satorux@chromium.org
Review URL: https://chromiumcodereview.appspot.com/9264010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@118295 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http')
-rw-r--r-- | net/http/http_stream_parser.cc | 60 | ||||
-rw-r--r-- | net/http/http_stream_parser.h | 21 | ||||
-rw-r--r-- | net/http/http_stream_parser_unittest.cc | 77 |
3 files changed, 20 insertions, 138 deletions
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc index a61349a..bd9bda1 100644 --- a/net/http/http_stream_parser.cc +++ b/net/http/http_stream_parser.cc @@ -6,6 +6,7 @@ #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" @@ -60,15 +61,6 @@ bool HeadersContainMultipleCopiesOfField( namespace net { -// 2 CRLFs + max of 8 hex chars. -const size_t HttpStreamParser::kChunkHeaderFooterSize = 12; - -// The size of the chunk buffer (chunk_buf_). The chunk buffer is -// guaranteed to be large enough to hold the encoded chunk. -static const size_t kChunkBufferSize = - UploadDataStream::kBufferSize + - HttpStreamParser::kChunkHeaderFooterSize; - HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection, const HttpRequestInfo* request, GrowableIOBuffer* read_buffer, @@ -136,7 +128,9 @@ 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); - chunk_buf_ = new IOBuffer(kChunkBufferSize); + const int kChunkHeaderFooterSize = 12; // 2 CRLFs + max of 8 hex chars. + chunk_buf_ = new IOBuffer(request_body_->GetMaxBufferSize() + + kChunkHeaderFooterSize); } io_state_ = STATE_SENDING_HEADERS; @@ -355,17 +349,23 @@ 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()) { - chunk_length_ = EncodeChunk( - base::StringPiece(), chunk_buf_->data(), kChunkBufferSize); + static const char kLastChunk[] = "0\r\n\r\n"; + chunk_length_ = strlen(kLastChunk); + memcpy(chunk_buf_->data(), kLastChunk, chunk_length_); sent_last_chunk_ = true; - } else if (request_body_->buf_len() > 0) { + } else if (buf_len) { // Encode and send the buffer as 1 chunk. - const base::StringPiece payload(request_body_->buf()->data(), - request_body_->buf_len()); - chunk_length_ = EncodeChunk(payload, chunk_buf_->data(), - kChunkBufferSize); - chunk_length_without_encoding_ = payload.size(); + 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; } else { // Nothing to send. More POST data is yet to come? return ERR_IO_PENDING; @@ -773,28 +773,4 @@ 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 diff --git a/net/http/http_stream_parser.h b/net/http/http_stream_parser.h index efb41a0..ae9fc3e 100644 --- a/net/http/http_stream_parser.h +++ b/net/http/http_stream_parser.h @@ -1,4 +1,4 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,9 +9,7 @@ #include <string> #include "base/basictypes.h" -#include "base/string_piece.h" #include "net/base/completion_callback.h" -#include "net/base/net_export.h" #include "net/base/net_log.h" #include "net/base/upload_data_stream.h" #include "net/http/http_chunked_decoder.h" @@ -28,7 +26,7 @@ class IOBuffer; class SSLCertRequestInfo; class SSLInfo; -class NET_EXPORT_PRIVATE HttpStreamParser : public ChunkCallback { +class HttpStreamParser : public ChunkCallback { public: // Any data in |read_buffer| will be used before reading from the socket // and any data left over after parsing the stream will be put into @@ -79,21 +77,6 @@ class NET_EXPORT_PRIVATE HttpStreamParser : public ChunkCallback { // ChunkCallback methods. virtual void OnChunkAvailable() OVERRIDE; - // Encodes the given |payload| in the chunked format to |output|. - // Returns the number of bytes written to |output|. |output_size| should - // be large enough to store the encoded chunk, which is payload.size() + - // kChunkHeaderFooterSize. Returns ERR_INVALID_ARGUMENT if |output_size| - // is not large enough. - // - // The output will look like: "HEX\r\n[payload]\r\n" - // where HEX is a length in hexdecimal (without the "0x" prefix). - static int EncodeChunk(const base::StringPiece& payload, - char* output, - size_t output_size); - - // The number of extra bytes required to encode a chunk. - static const size_t kChunkHeaderFooterSize; - private: // FOO_COMPLETE states implement the second half of potentially asynchronous // operations and don't necessarily mean that FOO is complete. diff --git a/net/http/http_stream_parser_unittest.cc b/net/http/http_stream_parser_unittest.cc deleted file mode 100644 index d40eac6..0000000 --- a/net/http/http_stream_parser_unittest.cc +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/http/http_stream_parser.h" - -#include "base/string_piece.h" -#include "base/stringprintf.h" -#include "net/base/net_errors.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace net { - -const size_t kOutputSize = 1024; // Just large enough for this test. -// The number of bytes that can fit in a buffer of kOutputSize. -const size_t kMaxPayloadSize = - kOutputSize - HttpStreamParser::kChunkHeaderFooterSize; - -// The empty payload is how the last chunk is encoded. -TEST(HttpStreamParser, EncodeChunk_EmptyPayload) { - char output[kOutputSize]; - - const base::StringPiece kPayload = ""; - const base::StringPiece kExpected = "0\r\n\r\n"; - const int num_bytes_written = - HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output)); - ASSERT_EQ(kExpected.size(), static_cast<size_t>(num_bytes_written)); - EXPECT_EQ(kExpected, base::StringPiece(output, num_bytes_written)); -} - -TEST(HttpStreamParser, EncodeChunk_ShortPayload) { - char output[kOutputSize]; - - const std::string kPayload("foo\x00\x11\x22", 6); - // 11 = payload size + sizeof("6") + CRLF x 2. - const std::string kExpected("6\r\nfoo\x00\x11\x22\r\n", 11); - const int num_bytes_written = - HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output)); - ASSERT_EQ(kExpected.size(), static_cast<size_t>(num_bytes_written)); - EXPECT_EQ(kExpected, base::StringPiece(output, num_bytes_written)); -} - -TEST(HttpStreamParser, EncodeChunk_LargePayload) { - char output[kOutputSize]; - - const std::string kPayload(1000, '\xff'); // '\xff' x 1000. - // 3E8 = 1000 in hex. - const std::string kExpected = "3E8\r\n" + kPayload + "\r\n"; - const int num_bytes_written = - HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output)); - ASSERT_EQ(kExpected.size(), static_cast<size_t>(num_bytes_written)); - EXPECT_EQ(kExpected, base::StringPiece(output, num_bytes_written)); -} - -TEST(HttpStreamParser, EncodeChunk_FullPayload) { - char output[kOutputSize]; - - const std::string kPayload(kMaxPayloadSize, '\xff'); - // 3F4 = 1012 in hex. - const std::string kExpected = "3F4\r\n" + kPayload + "\r\n"; - const int num_bytes_written = - HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output)); - ASSERT_EQ(kExpected.size(), static_cast<size_t>(num_bytes_written)); - EXPECT_EQ(kExpected, base::StringPiece(output, num_bytes_written)); -} - -TEST(HttpStreamParser, EncodeChunk_TooLargePayload) { - char output[kOutputSize]; - - // The payload is one byte larger the output buffer size. - const std::string kPayload(kMaxPayloadSize + 1, '\xff'); - const int num_bytes_written = - HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output)); - ASSERT_EQ(ERR_INVALID_ARGUMENT, num_bytes_written); -} - -} // namespace net |