OLD | NEW |
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_)); | |
46 } | 48 } |
47 | 49 |
48 BufferedSpdyFramer::~BufferedSpdyFramer() { | 50 BufferedSpdyFramer::~BufferedSpdyFramer() { |
49 } | 51 } |
50 | 52 |
51 void BufferedSpdyFramer::set_visitor( | 53 void BufferedSpdyFramer::set_visitor( |
52 BufferedSpdyFramerVisitorInterface* visitor) { | 54 BufferedSpdyFramerVisitorInterface* visitor) { |
53 visitor_ = visitor; | 55 visitor_ = visitor; |
54 spdy_framer_.set_visitor(this); | 56 spdy_framer_.set_visitor(this); |
55 } | 57 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 bool BufferedSpdyFramer::OnControlFrameHeaderData(SpdyStreamId stream_id, | 122 bool BufferedSpdyFramer::OnControlFrameHeaderData(SpdyStreamId stream_id, |
121 const char* header_data, | 123 const char* header_data, |
122 size_t len) { | 124 size_t len) { |
123 CHECK_EQ(header_stream_id_, stream_id); | 125 CHECK_EQ(header_stream_id_, stream_id); |
124 | 126 |
125 if (len == 0) { | 127 if (len == 0) { |
126 // Indicates end-of-header-block. | 128 // Indicates end-of-header-block. |
127 CHECK(header_buffer_valid_); | 129 CHECK(header_buffer_valid_); |
128 | 130 |
129 SpdyHeaderBlock headers; | 131 SpdyHeaderBlock headers; |
130 if (!spdy_framer_.ParseHeaderBlockInBuffer(header_buffer_, | 132 if (!spdy_framer_.ParseHeaderBlockInBuffer( |
131 header_buffer_used_, &headers)) { | 133 header_buffer_.data(), header_buffer_.size(), &headers)) { |
132 visitor_->OnStreamError( | 134 visitor_->OnStreamError( |
133 stream_id, "Could not parse Spdy Control Frame Header."); | 135 stream_id, "Could not parse Spdy Control Frame Header."); |
134 return false; | 136 return false; |
135 } | 137 } |
136 DCHECK(control_frame_fields_.get()); | 138 DCHECK(control_frame_fields_.get()); |
137 switch (control_frame_fields_->type) { | 139 switch (control_frame_fields_->type) { |
138 case SYN_STREAM: | 140 case SYN_STREAM: |
139 visitor_->OnSynStream(control_frame_fields_->stream_id, | 141 visitor_->OnSynStream(control_frame_fields_->stream_id, |
140 control_frame_fields_->associated_stream_id, | 142 control_frame_fields_->associated_stream_id, |
141 control_frame_fields_->priority, | 143 control_frame_fields_->priority, |
(...skipping 22 matching lines...) Expand all Loading... |
164 break; | 166 break; |
165 default: | 167 default: |
166 DCHECK(false) << "Unexpect control frame type: " | 168 DCHECK(false) << "Unexpect control frame type: " |
167 << control_frame_fields_->type; | 169 << control_frame_fields_->type; |
168 break; | 170 break; |
169 } | 171 } |
170 control_frame_fields_.reset(NULL); | 172 control_frame_fields_.reset(NULL); |
171 return true; | 173 return true; |
172 } | 174 } |
173 | 175 |
174 const size_t available = kHeaderBufferSize - header_buffer_used_; | 176 const size_t new_size = header_buffer_.size() + len; |
175 if (len > available) { | 177 if (new_size > kHeaderBufferMaxSize) { |
176 header_buffer_valid_ = false; | 178 header_buffer_valid_ = false; |
177 visitor_->OnStreamError( | 179 visitor_->OnStreamError(stream_id, "Received too much header data."); |
178 stream_id, "Received more data than the allocated size."); | |
179 return false; | 180 return false; |
180 } | 181 } |
181 memcpy(header_buffer_ + header_buffer_used_, header_data, len); | 182 |
182 header_buffer_used_ += len; | 183 if (new_size > header_buffer_.capacity()) { |
| 184 // Grow |header_buffer_| exponentially to reduce memory allocations and |
| 185 // copies. |
| 186 size_t new_capacity = std::max(new_size, kHeaderBufferInitialSize); |
| 187 new_capacity = std::max(new_capacity, 2 * header_buffer_.capacity()); |
| 188 new_capacity = std::min(new_capacity, kHeaderBufferMaxSize); |
| 189 header_buffer_.reserve(new_capacity); |
| 190 } |
| 191 header_buffer_.append(header_data, len); |
183 return true; | 192 return true; |
184 } | 193 } |
185 | 194 |
186 void BufferedSpdyFramer::OnDataFrameHeader(SpdyStreamId stream_id, | 195 void BufferedSpdyFramer::OnDataFrameHeader(SpdyStreamId stream_id, |
187 size_t length, | 196 size_t length, |
188 bool fin) { | 197 bool fin) { |
189 frames_received_++; | 198 frames_received_++; |
190 header_stream_id_ = stream_id; | 199 header_stream_id_ = stream_id; |
191 visitor_->OnDataFrameHeader(stream_id, length, fin); | 200 visitor_->OnDataFrameHeader(stream_id, length, fin); |
192 } | 201 } |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 SpdyPushPromiseIR push_promise_ir(stream_id, promised_stream_id); | 444 SpdyPushPromiseIR push_promise_ir(stream_id, promised_stream_id); |
436 push_promise_ir.set_header_block(*headers); | 445 push_promise_ir.set_header_block(*headers); |
437 return spdy_framer_.SerializePushPromise(push_promise_ir); | 446 return spdy_framer_.SerializePushPromise(push_promise_ir); |
438 } | 447 } |
439 | 448 |
440 SpdyPriority BufferedSpdyFramer::GetHighestPriority() const { | 449 SpdyPriority BufferedSpdyFramer::GetHighestPriority() const { |
441 return spdy_framer_.GetHighestPriority(); | 450 return spdy_framer_.GetHighestPriority(); |
442 } | 451 } |
443 | 452 |
444 void BufferedSpdyFramer::InitHeaderStreaming(SpdyStreamId stream_id) { | 453 void BufferedSpdyFramer::InitHeaderStreaming(SpdyStreamId stream_id) { |
445 memset(header_buffer_, 0, kHeaderBufferSize); | 454 header_buffer_.clear(); |
446 header_buffer_used_ = 0; | |
447 header_buffer_valid_ = true; | 455 header_buffer_valid_ = true; |
448 header_stream_id_ = stream_id; | 456 header_stream_id_ = stream_id; |
449 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream); | 457 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream); |
450 } | 458 } |
451 | 459 |
452 } // namespace net | 460 } // namespace net |
OLD | NEW |