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 <algorithm> |
7 #include <utility> | 8 #include <utility> |
8 | 9 |
9 #include "base/logging.h" | 10 #include "base/logging.h" |
10 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
11 | 12 |
12 namespace net { | 13 namespace net { |
13 | 14 |
14 namespace { | 15 namespace { |
15 | 16 |
16 // GOAWAY frame debug data is only buffered up to this many bytes. | 17 // GOAWAY frame debug data is only buffered up to this many bytes. |
17 size_t kGoAwayDebugDataMaxSize = 1024; | 18 size_t kGoAwayDebugDataMaxSize = 1024; |
18 | 19 |
19 // Initial and maximum sizes for header block buffer. | |
20 size_t kHeaderBufferInitialSize = 8 * 1024; | |
21 size_t kHeaderBufferMaxSize = 256 * 1024; | |
22 | |
23 } // namespace | 20 } // namespace |
24 | 21 |
25 BufferedSpdyFramer::BufferedSpdyFramer() | 22 BufferedSpdyFramer::BufferedSpdyFramer() |
26 : spdy_framer_(HTTP2), | 23 : spdy_framer_(HTTP2), |
27 visitor_(NULL), | 24 visitor_(NULL), |
28 header_buffer_valid_(false), | 25 header_buffer_valid_(false), |
29 header_stream_id_(SpdyFramer::kInvalidStream), | 26 header_stream_id_(SpdyFramer::kInvalidStream), |
30 frames_received_(0) {} | 27 frames_received_(0) {} |
31 | 28 |
32 BufferedSpdyFramer::~BufferedSpdyFramer() { | 29 BufferedSpdyFramer::~BufferedSpdyFramer() { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 control_frame_fields_->fin = fin; | 74 control_frame_fields_->fin = fin; |
78 | 75 |
79 InitHeaderStreaming(stream_id); | 76 InitHeaderStreaming(stream_id); |
80 } | 77 } |
81 | 78 |
82 void BufferedSpdyFramer::OnSynReply(SpdyStreamId stream_id, | 79 void BufferedSpdyFramer::OnSynReply(SpdyStreamId stream_id, |
83 bool fin) { | 80 bool fin) { |
84 NOTREACHED(); | 81 NOTREACHED(); |
85 } | 82 } |
86 | 83 |
87 bool BufferedSpdyFramer::OnControlFrameHeaderData(SpdyStreamId stream_id, | |
88 const char* header_data, | |
89 size_t len) { | |
90 CHECK_EQ(header_stream_id_, stream_id); | |
91 | |
92 if (len == 0) { | |
93 // Indicates end-of-header-block. | |
94 CHECK(header_buffer_valid_); | |
95 | |
96 SpdyHeaderBlock headers; | |
97 if (!spdy_framer_.ParseHeaderBlockInBuffer( | |
98 header_buffer_.data(), header_buffer_.size(), &headers)) { | |
99 visitor_->OnStreamError( | |
100 stream_id, "Could not parse Spdy Control Frame Header."); | |
101 return false; | |
102 } | |
103 DCHECK(control_frame_fields_.get()); | |
104 switch (control_frame_fields_->type) { | |
105 case SYN_STREAM: | |
106 NOTREACHED(); | |
107 break; | |
108 case SYN_REPLY: | |
109 NOTREACHED(); | |
110 break; | |
111 case HEADERS: | |
112 visitor_->OnHeaders(control_frame_fields_->stream_id, | |
113 control_frame_fields_->has_priority, | |
114 control_frame_fields_->weight, | |
115 control_frame_fields_->parent_stream_id, | |
116 control_frame_fields_->exclusive, | |
117 control_frame_fields_->fin, std::move(headers)); | |
118 break; | |
119 case PUSH_PROMISE: | |
120 visitor_->OnPushPromise(control_frame_fields_->stream_id, | |
121 control_frame_fields_->promised_stream_id, | |
122 std::move(headers)); | |
123 break; | |
124 default: | |
125 DCHECK(false) << "Unexpect control frame type: " | |
126 << control_frame_fields_->type; | |
127 break; | |
128 } | |
129 control_frame_fields_.reset(NULL); | |
130 return true; | |
131 } | |
132 | |
133 const size_t new_size = header_buffer_.size() + len; | |
134 if (new_size > kHeaderBufferMaxSize) { | |
135 header_buffer_valid_ = false; | |
136 visitor_->OnStreamError(stream_id, "Received too much header data."); | |
137 return false; | |
138 } | |
139 | |
140 if (new_size > header_buffer_.capacity()) { | |
141 // Grow |header_buffer_| exponentially to reduce memory allocations and | |
142 // copies. | |
143 size_t new_capacity = std::max(new_size, kHeaderBufferInitialSize); | |
144 new_capacity = std::max(new_capacity, 2 * header_buffer_.capacity()); | |
145 new_capacity = std::min(new_capacity, kHeaderBufferMaxSize); | |
146 header_buffer_.reserve(new_capacity); | |
147 } | |
148 header_buffer_.append(header_data, len); | |
149 return true; | |
150 } | |
151 | |
152 void BufferedSpdyFramer::OnDataFrameHeader(SpdyStreamId stream_id, | 84 void BufferedSpdyFramer::OnDataFrameHeader(SpdyStreamId stream_id, |
153 size_t length, | 85 size_t length, |
154 bool fin) { | 86 bool fin) { |
155 frames_received_++; | 87 frames_received_++; |
156 header_stream_id_ = stream_id; | 88 header_stream_id_ = stream_id; |
157 visitor_->OnDataFrameHeader(stream_id, length, fin); | 89 visitor_->OnDataFrameHeader(stream_id, length, fin); |
158 } | 90 } |
159 | 91 |
160 void BufferedSpdyFramer::OnStreamFrameData(SpdyStreamId stream_id, | 92 void BufferedSpdyFramer::OnStreamFrameData(SpdyStreamId stream_id, |
161 const char* data, | 93 const char* data, |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
418 } | 350 } |
419 | 351 |
420 void BufferedSpdyFramer::InitHeaderStreaming(SpdyStreamId stream_id) { | 352 void BufferedSpdyFramer::InitHeaderStreaming(SpdyStreamId stream_id) { |
421 header_buffer_.clear(); | 353 header_buffer_.clear(); |
422 header_buffer_valid_ = true; | 354 header_buffer_valid_ = true; |
423 header_stream_id_ = stream_id; | 355 header_stream_id_ = stream_id; |
424 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream); | 356 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream); |
425 } | 357 } |
426 | 358 |
427 } // namespace net | 359 } // namespace net |
OLD | NEW |