Index: net/spdy/buffered_spdy_framer.cc |
diff --git a/net/spdy/buffered_spdy_framer.cc b/net/spdy/buffered_spdy_framer.cc |
index 2372aff1a56ce65f05df688c7a87bf410fcd66b6..d136d1df4224af762d6fdcc0ede544ccacffc4df 100644 |
--- a/net/spdy/buffered_spdy_framer.cc |
+++ b/net/spdy/buffered_spdy_framer.cc |
@@ -13,6 +13,10 @@ namespace { |
// GOAWAY frame debug data is only buffered up to this many bytes. |
size_t kGoAwayDebugDataMaxSize = 1024; |
+// Initial and maximum sizes for header block buffer. |
+size_t kHeaderBufferInitialSize = 8 * 1024; |
+size_t kHeaderBufferMaxSize = 256 * 1024; |
+ |
} // namespace |
SpdyMajorVersion NextProtoToSpdyMajorVersion(NextProto next_proto) { |
@@ -37,12 +41,10 @@ BufferedSpdyFramer::BufferedSpdyFramer(SpdyMajorVersion version, |
bool enable_compression) |
: spdy_framer_(version), |
visitor_(NULL), |
- header_buffer_used_(0), |
header_buffer_valid_(false), |
header_stream_id_(SpdyFramer::kInvalidStream), |
frames_received_(0) { |
spdy_framer_.set_enable_compression(enable_compression); |
- memset(header_buffer_, 0, sizeof(header_buffer_)); |
} |
BufferedSpdyFramer::~BufferedSpdyFramer() { |
@@ -127,8 +129,8 @@ bool BufferedSpdyFramer::OnControlFrameHeaderData(SpdyStreamId stream_id, |
CHECK(header_buffer_valid_); |
SpdyHeaderBlock headers; |
- if (!spdy_framer_.ParseHeaderBlockInBuffer(header_buffer_, |
- header_buffer_used_, &headers)) { |
+ if (!spdy_framer_.ParseHeaderBlockInBuffer( |
+ header_buffer_.data(), header_buffer_.size(), &headers)) { |
visitor_->OnStreamError( |
stream_id, "Could not parse Spdy Control Frame Header."); |
return false; |
@@ -171,15 +173,22 @@ bool BufferedSpdyFramer::OnControlFrameHeaderData(SpdyStreamId stream_id, |
return true; |
} |
- const size_t available = kHeaderBufferSize - header_buffer_used_; |
- if (len > available) { |
+ const size_t new_size = header_buffer_.size() + len; |
+ if (new_size > kHeaderBufferMaxSize) { |
header_buffer_valid_ = false; |
- visitor_->OnStreamError( |
- stream_id, "Received more data than the allocated size."); |
+ visitor_->OnStreamError(stream_id, "Received too much header data."); |
return false; |
} |
- memcpy(header_buffer_ + header_buffer_used_, header_data, len); |
- header_buffer_used_ += len; |
+ |
+ if (new_size > header_buffer_.capacity()) { |
+ // Grow |header_buffer_| exponentially to reduce memory allocations and |
+ // copies. |
+ size_t new_capacity = std::max(new_size, kHeaderBufferInitialSize); |
+ new_capacity = std::max(new_capacity, 2 * header_buffer_.capacity()); |
+ new_capacity = std::min(new_capacity, kHeaderBufferMaxSize); |
+ header_buffer_.reserve(new_capacity); |
+ } |
+ header_buffer_.append(header_data, len); |
return true; |
} |
@@ -442,8 +451,7 @@ SpdyPriority BufferedSpdyFramer::GetHighestPriority() const { |
} |
void BufferedSpdyFramer::InitHeaderStreaming(SpdyStreamId stream_id) { |
- memset(header_buffer_, 0, kHeaderBufferSize); |
- header_buffer_used_ = 0; |
+ header_buffer_.clear(); |
header_buffer_valid_ = true; |
header_stream_id_ = stream_id; |
DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream); |