Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(366)

Side by Side Diff: net/spdy/buffered_spdy_framer.cc

Issue 1566703002: Increase HTTP/2 response header buffer limit to 256 kB. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/spdy/buffered_spdy_framer.h ('k') | net/spdy/hpack/hpack_constants.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/spdy/buffered_spdy_framer.h" 5 #include "net/spdy/buffered_spdy_framer.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 8
9 namespace net { 9 namespace net {
10 10
11 namespace { 11 namespace {
12 12
13 // GOAWAY frame debug data is only buffered up to this many bytes. 13 // GOAWAY frame debug data is only buffered up to this many bytes.
14 size_t kGoAwayDebugDataMaxSize = 1024; 14 size_t kGoAwayDebugDataMaxSize = 1024;
15 15
16 // Initial and maximum sizes for header block buffer.
17 size_t kHeaderBufferInitialSize = 8 * 1024;
18 size_t kHeaderBufferMaxSize = 256 * 1024;
19
16 } // namespace 20 } // namespace
17 21
18 SpdyMajorVersion NextProtoToSpdyMajorVersion(NextProto next_proto) { 22 SpdyMajorVersion NextProtoToSpdyMajorVersion(NextProto next_proto) {
19 switch (next_proto) { 23 switch (next_proto) {
20 case kProtoDeprecatedSPDY2: 24 case kProtoDeprecatedSPDY2:
21 return SPDY2; 25 return SPDY2;
22 case kProtoSPDY3: 26 case kProtoSPDY3:
23 case kProtoSPDY31: 27 case kProtoSPDY31:
24 return SPDY3; 28 return SPDY3;
25 case kProtoHTTP2: 29 case kProtoHTTP2:
26 return HTTP2; 30 return HTTP2;
27 case kProtoUnknown: 31 case kProtoUnknown:
28 case kProtoHTTP11: 32 case kProtoHTTP11:
29 case kProtoQUIC1SPDY3: 33 case kProtoQUIC1SPDY3:
30 break; 34 break;
31 } 35 }
32 NOTREACHED(); 36 NOTREACHED();
33 return SPDY2; 37 return SPDY2;
34 } 38 }
35 39
36 BufferedSpdyFramer::BufferedSpdyFramer(SpdyMajorVersion version, 40 BufferedSpdyFramer::BufferedSpdyFramer(SpdyMajorVersion version,
37 bool enable_compression) 41 bool enable_compression)
38 : spdy_framer_(version), 42 : spdy_framer_(version),
39 visitor_(NULL), 43 visitor_(NULL),
40 header_buffer_used_(0),
41 header_buffer_valid_(false), 44 header_buffer_valid_(false),
42 header_stream_id_(SpdyFramer::kInvalidStream), 45 header_stream_id_(SpdyFramer::kInvalidStream),
43 frames_received_(0) { 46 frames_received_(0) {
44 spdy_framer_.set_enable_compression(enable_compression); 47 spdy_framer_.set_enable_compression(enable_compression);
45 memset(header_buffer_, 0, sizeof(header_buffer_)); 48 header_buffer_.clear();
Ryan Hamilton 2016/01/08 00:16:29 Does this do anything since the buffer was newly c
Bence 2016/01/08 18:58:24 Hm, I guess not. Thanks for catching it.
46 } 49 }
47 50
48 BufferedSpdyFramer::~BufferedSpdyFramer() { 51 BufferedSpdyFramer::~BufferedSpdyFramer() {
49 } 52 }
50 53
51 void BufferedSpdyFramer::set_visitor( 54 void BufferedSpdyFramer::set_visitor(
52 BufferedSpdyFramerVisitorInterface* visitor) { 55 BufferedSpdyFramerVisitorInterface* visitor) {
53 visitor_ = visitor; 56 visitor_ = visitor;
54 spdy_framer_.set_visitor(this); 57 spdy_framer_.set_visitor(this);
55 } 58 }
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 bool BufferedSpdyFramer::OnControlFrameHeaderData(SpdyStreamId stream_id, 123 bool BufferedSpdyFramer::OnControlFrameHeaderData(SpdyStreamId stream_id,
121 const char* header_data, 124 const char* header_data,
122 size_t len) { 125 size_t len) {
123 CHECK_EQ(header_stream_id_, stream_id); 126 CHECK_EQ(header_stream_id_, stream_id);
124 127
125 if (len == 0) { 128 if (len == 0) {
126 // Indicates end-of-header-block. 129 // Indicates end-of-header-block.
127 CHECK(header_buffer_valid_); 130 CHECK(header_buffer_valid_);
128 131
129 SpdyHeaderBlock headers; 132 SpdyHeaderBlock headers;
130 if (!spdy_framer_.ParseHeaderBlockInBuffer(header_buffer_, 133 if (!spdy_framer_.ParseHeaderBlockInBuffer(
131 header_buffer_used_, &headers)) { 134 header_buffer_.data(), header_buffer_.size(), &headers)) {
132 visitor_->OnStreamError( 135 visitor_->OnStreamError(
133 stream_id, "Could not parse Spdy Control Frame Header."); 136 stream_id, "Could not parse Spdy Control Frame Header.");
134 return false; 137 return false;
135 } 138 }
136 DCHECK(control_frame_fields_.get()); 139 DCHECK(control_frame_fields_.get());
137 switch (control_frame_fields_->type) { 140 switch (control_frame_fields_->type) {
138 case SYN_STREAM: 141 case SYN_STREAM:
139 visitor_->OnSynStream(control_frame_fields_->stream_id, 142 visitor_->OnSynStream(control_frame_fields_->stream_id,
140 control_frame_fields_->associated_stream_id, 143 control_frame_fields_->associated_stream_id,
141 control_frame_fields_->priority, 144 control_frame_fields_->priority,
(...skipping 22 matching lines...) Expand all
164 break; 167 break;
165 default: 168 default:
166 DCHECK(false) << "Unexpect control frame type: " 169 DCHECK(false) << "Unexpect control frame type: "
167 << control_frame_fields_->type; 170 << control_frame_fields_->type;
168 break; 171 break;
169 } 172 }
170 control_frame_fields_.reset(NULL); 173 control_frame_fields_.reset(NULL);
171 return true; 174 return true;
172 } 175 }
173 176
174 const size_t available = kHeaderBufferSize - header_buffer_used_; 177 const size_t new_size = header_buffer_.size() + len;
175 if (len > available) { 178 if (new_size > kHeaderBufferMaxSize) {
176 header_buffer_valid_ = false; 179 header_buffer_valid_ = false;
177 visitor_->OnStreamError( 180 visitor_->OnStreamError(stream_id, "Received too much header data.");
178 stream_id, "Received more data than the allocated size.");
179 return false; 181 return false;
180 } 182 }
181 memcpy(header_buffer_ + header_buffer_used_, header_data, len); 183
182 header_buffer_used_ += len; 184 if (new_size > header_buffer_.capacity()) {
185 // Grow |header_buffer_| exponentially to reduce memory allocations and
186 // copies.
187 size_t new_capacity = std::max(new_size, kHeaderBufferInitialSize);
Ryan Hamilton 2016/01/08 00:16:29 Can new_size ever be < kHeaderBufferInitialSize, s
Bence 2016/01/08 18:58:24 Yes, new_size can be smaller. This is the only pl
Ryan Hamilton 2016/01/08 21:20:46 Hah, I missed that. Good point :>
188 new_capacity = std::max(new_capacity, 2 * header_buffer_.capacity());
189 new_capacity = std::min(new_capacity, kHeaderBufferMaxSize);
190 header_buffer_.reserve(new_capacity);
191 }
192 header_buffer_.append(header_data, len);
183 return true; 193 return true;
Ryan Hamilton 2016/01/08 00:16:29 Should we have a unit test of this new behavior?
Bence 2016/01/08 18:58:24 The behavior of larger buffer limit? There is one
184 } 194 }
185 195
186 void BufferedSpdyFramer::OnDataFrameHeader(SpdyStreamId stream_id, 196 void BufferedSpdyFramer::OnDataFrameHeader(SpdyStreamId stream_id,
187 size_t length, 197 size_t length,
188 bool fin) { 198 bool fin) {
189 frames_received_++; 199 frames_received_++;
190 header_stream_id_ = stream_id; 200 header_stream_id_ = stream_id;
191 visitor_->OnDataFrameHeader(stream_id, length, fin); 201 visitor_->OnDataFrameHeader(stream_id, length, fin);
192 } 202 }
193 203
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 SpdyPushPromiseIR push_promise_ir(stream_id, promised_stream_id); 445 SpdyPushPromiseIR push_promise_ir(stream_id, promised_stream_id);
436 push_promise_ir.set_header_block(*headers); 446 push_promise_ir.set_header_block(*headers);
437 return spdy_framer_.SerializePushPromise(push_promise_ir); 447 return spdy_framer_.SerializePushPromise(push_promise_ir);
438 } 448 }
439 449
440 SpdyPriority BufferedSpdyFramer::GetHighestPriority() const { 450 SpdyPriority BufferedSpdyFramer::GetHighestPriority() const {
441 return spdy_framer_.GetHighestPriority(); 451 return spdy_framer_.GetHighestPriority();
442 } 452 }
443 453
444 void BufferedSpdyFramer::InitHeaderStreaming(SpdyStreamId stream_id) { 454 void BufferedSpdyFramer::InitHeaderStreaming(SpdyStreamId stream_id) {
445 memset(header_buffer_, 0, kHeaderBufferSize); 455 header_buffer_.clear();
446 header_buffer_used_ = 0;
447 header_buffer_valid_ = true; 456 header_buffer_valid_ = true;
448 header_stream_id_ = stream_id; 457 header_stream_id_ = stream_id;
449 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream); 458 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
450 } 459 }
451 460
452 } // namespace net 461 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/buffered_spdy_framer.h ('k') | net/spdy/hpack/hpack_constants.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698