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

Side by Side Diff: net/spdy/hpack/hpack_decoder.cc

Issue 2832973003: Split net/spdy into core and chromium subdirectories. (Closed)
Patch Set: Fix some more build rules. Created 3 years, 8 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/hpack/hpack_decoder.h ('k') | net/spdy/hpack/hpack_decoder3.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/spdy/hpack/hpack_decoder.h"
6
7 #include <utility>
8
9 #include "base/logging.h"
10 #include "net/spdy/hpack/hpack_constants.h"
11 #include "net/spdy/hpack/hpack_entry.h"
12 #include "net/spdy/platform/api/spdy_estimate_memory_usage.h"
13 #include "net/spdy/spdy_flags.h"
14
15 namespace net {
16
17 HpackDecoder::HpackDecoder()
18 : handler_(nullptr),
19 total_header_bytes_(0),
20 total_parsed_bytes_(0),
21 header_block_started_(false),
22 size_updates_seen_(0),
23 size_updates_allowed_(true),
24 incremental_decode_(false) {}
25
26 HpackDecoder::~HpackDecoder() {}
27
28 void HpackDecoder::ApplyHeaderTableSizeSetting(size_t size_setting) {
29 header_table_.SetSettingsHeaderTableSize(size_setting);
30 }
31
32 void HpackDecoder::HandleControlFrameHeadersStart(
33 SpdyHeadersHandlerInterface* handler) {
34 handler_ = handler;
35 total_header_bytes_ = 0;
36 }
37
38 bool HpackDecoder::HandleControlFrameHeadersData(const char* headers_data,
39 size_t headers_data_length) {
40 if (!header_block_started_) {
41 decoded_block_.clear();
42 header_block_started_ = true;
43 size_updates_allowed_ = true;
44 size_updates_seen_ = 0;
45 if (handler_ != nullptr) {
46 handler_->OnHeaderBlockStart();
47 }
48 }
49 size_t new_size = headers_block_buffer_.size() + headers_data_length;
50 if (max_decode_buffer_size_bytes_ > 0 &&
51 new_size > max_decode_buffer_size_bytes_) {
52 DVLOG(1) << "max_decode_buffer_size_bytes_ < new_size: "
53 << max_decode_buffer_size_bytes_ << " < " << new_size;
54 return false;
55 }
56 headers_block_buffer_.insert(headers_block_buffer_.end(), headers_data,
57 headers_data + headers_data_length);
58
59 // Parse as many whole HPACK entries in the buffer as possible,
60 // and then remove the parsed data from the buffer.
61 HpackInputStream input_stream(headers_block_buffer_);
62 while (input_stream.HasMoreData()) {
63 if (!DecodeNextOpcodeWrapper(&input_stream)) {
64 if (input_stream.NeedMoreData()) {
65 break;
66 }
67 DVLOG(1) << "!DecodeNextOpcodeWrapper";
68 return false;
69 }
70 }
71 uint32_t parsed_bytes = input_stream.ParsedBytes();
72 DCHECK_GE(headers_block_buffer_.size(), parsed_bytes);
73 headers_block_buffer_.erase(0, parsed_bytes);
74 total_parsed_bytes_ += parsed_bytes;
75
76 return true;
77 }
78
79 bool HpackDecoder::HandleControlFrameHeadersComplete(size_t* compressed_len) {
80 if (compressed_len != nullptr) {
81 *compressed_len = total_parsed_bytes_;
82 }
83
84 // Data in headers_block_buffer_ should have been parsed by
85 // HandleControlFrameHeadersData and removed.
86 if (headers_block_buffer_.size() > 0) {
87 DVLOG(1) << "headers_block_buffer_.size() should be zero, but is "
88 << headers_block_buffer_.size();
89 return false;
90 }
91
92 if (handler_ != nullptr) {
93 if (FLAGS_chromium_http2_flag_log_compressed_size) {
94 handler_->OnHeaderBlockEnd(total_header_bytes_, total_parsed_bytes_);
95 } else {
96 handler_->OnHeaderBlockEnd(total_header_bytes_);
97 }
98 }
99 headers_block_buffer_.clear();
100 total_parsed_bytes_ = 0;
101 header_block_started_ = false;
102 handler_ = nullptr;
103 return true;
104 }
105
106 const SpdyHeaderBlock& HpackDecoder::decoded_block() const {
107 return decoded_block_;
108 }
109
110 void HpackDecoder::SetHeaderTableDebugVisitor(
111 std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) {
112 header_table_.set_debug_visitor(std::move(visitor));
113 }
114
115 void HpackDecoder::set_max_decode_buffer_size_bytes(
116 size_t max_decode_buffer_size_bytes) {
117 max_decode_buffer_size_bytes_ = max_decode_buffer_size_bytes;
118 }
119
120 size_t HpackDecoder::EstimateMemoryUsage() const {
121 return SpdyEstimateMemoryUsage(header_table_) +
122 SpdyEstimateMemoryUsage(headers_block_buffer_) +
123 SpdyEstimateMemoryUsage(decoded_block_) +
124 SpdyEstimateMemoryUsage(key_buffer_) +
125 SpdyEstimateMemoryUsage(value_buffer_);
126 }
127
128 bool HpackDecoder::HandleHeaderRepresentation(SpdyStringPiece name,
129 SpdyStringPiece value) {
130 size_updates_allowed_ = false;
131 total_header_bytes_ += name.size() + value.size();
132
133 if (handler_ == nullptr) {
134 decoded_block_.AppendValueOrAddHeader(name, value);
135 } else {
136 DCHECK(decoded_block_.empty());
137 handler_->OnHeader(name, value);
138 }
139 return true;
140 }
141
142 bool HpackDecoder::DecodeNextOpcodeWrapper(HpackInputStream* input_stream) {
143 if (DecodeNextOpcode(input_stream)) {
144 // Decoding next opcode succeeds. Mark total bytes parsed successfully.
145 input_stream->MarkCurrentPosition();
146 return true;
147 }
148 return false;
149 }
150
151 bool HpackDecoder::DecodeNextOpcode(HpackInputStream* input_stream) {
152 // Implements 7.1: Indexed Header Field Representation.
153 if (input_stream->MatchPrefixAndConsume(kIndexedOpcode)) {
154 return DecodeNextIndexedHeader(input_stream);
155 }
156 // Implements 7.2.1: Literal Header Field with Incremental Indexing.
157 if (input_stream->MatchPrefixAndConsume(kLiteralIncrementalIndexOpcode)) {
158 return DecodeNextLiteralHeader(input_stream, true);
159 }
160 // Implements 7.2.2: Literal Header Field without Indexing.
161 if (input_stream->MatchPrefixAndConsume(kLiteralNoIndexOpcode)) {
162 return DecodeNextLiteralHeader(input_stream, false);
163 }
164 // Implements 7.2.3: Literal Header Field never Indexed.
165 // TODO(jgraettinger): Preserve the never-indexed bit.
166 if (input_stream->MatchPrefixAndConsume(kLiteralNeverIndexOpcode)) {
167 return DecodeNextLiteralHeader(input_stream, false);
168 }
169 // Implements 7.3: Header Table Size Update.
170 if (input_stream->MatchPrefixAndConsume(kHeaderTableSizeUpdateOpcode)) {
171 // Header table size updates cannot appear mid-block.
172 return DecodeNextHeaderTableSizeUpdate(input_stream);
173 }
174 // Unrecognized opcode.
175 return false;
176 }
177
178 bool HpackDecoder::DecodeNextHeaderTableSizeUpdate(
179 HpackInputStream* input_stream) {
180 uint32_t size = 0;
181 if (!input_stream->DecodeNextUint32(&size)) {
182 return false;
183 }
184 if (!size_updates_allowed_) {
185 DVLOG(1) << "Size updates not allowed after header entries.";
186 return false;
187 }
188 ++size_updates_seen_;
189 if (size_updates_seen_ > 2) {
190 DVLOG(1) << "Too many size updates at the start of the block.";
191 return false;
192 }
193 if (size > header_table_.settings_size_bound()) {
194 DVLOG(1) << "Size (" << size << ") exceeds SETTINGS limit ("
195 << header_table_.settings_size_bound() << ")";
196 return false;
197 }
198 header_table_.SetMaxSize(size);
199 return true;
200 }
201
202 bool HpackDecoder::DecodeNextIndexedHeader(HpackInputStream* input_stream) {
203 uint32_t index = 0;
204 if (!input_stream->DecodeNextUint32(&index)) {
205 return false;
206 }
207
208 const HpackEntry* entry = header_table_.GetByIndex(index);
209 if (entry == NULL) {
210 DVLOG(1) << "Index " << index << " is not valid.";
211 return false;
212 }
213
214 return HandleHeaderRepresentation(entry->name(), entry->value());
215 }
216
217 bool HpackDecoder::DecodeNextLiteralHeader(HpackInputStream* input_stream,
218 bool should_index) {
219 SpdyStringPiece name;
220 if (!DecodeNextName(input_stream, &name)) {
221 return false;
222 }
223
224 SpdyStringPiece value;
225 if (!DecodeNextStringLiteral(input_stream, false, &value)) {
226 return false;
227 }
228
229 if (!HandleHeaderRepresentation(name, value)) {
230 return false;
231 }
232
233 if (!should_index) {
234 return true;
235 }
236
237 ignore_result(header_table_.TryAddEntry(name, value));
238 return true;
239 }
240
241 bool HpackDecoder::DecodeNextName(HpackInputStream* input_stream,
242 SpdyStringPiece* next_name) {
243 uint32_t index_or_zero = 0;
244 if (!input_stream->DecodeNextUint32(&index_or_zero)) {
245 DVLOG(1) << "Failed to decode the next uint.";
246 return false;
247 }
248
249 if (index_or_zero == 0) {
250 return DecodeNextStringLiteral(input_stream, true, next_name);
251 }
252
253 const HpackEntry* entry = header_table_.GetByIndex(index_or_zero);
254 if (entry == NULL) {
255 DVLOG(1) << "index " << index_or_zero << " is not valid.";
256 return false;
257 }
258 if (entry->IsStatic()) {
259 *next_name = entry->name();
260 } else {
261 // |entry| could be evicted as part of this insertion. Preemptively copy.
262 key_buffer_.assign(entry->name().data(), entry->name().size());
263 *next_name = key_buffer_;
264 }
265 return true;
266 }
267
268 bool HpackDecoder::DecodeNextStringLiteral(HpackInputStream* input_stream,
269 bool is_key,
270 SpdyStringPiece* output) {
271 if (input_stream->MatchPrefixAndConsume(kStringLiteralHuffmanEncoded)) {
272 SpdyString* buffer = is_key ? &key_buffer_ : &value_buffer_;
273 bool result = input_stream->DecodeNextHuffmanString(buffer);
274 *output = SpdyStringPiece(*buffer);
275 return result;
276 } else if (input_stream->MatchPrefixAndConsume(
277 kStringLiteralIdentityEncoded)) {
278 return input_stream->DecodeNextIdentityString(output);
279 } else {
280 DVLOG(1) << "String literal is neither Huffman nor identity encoded!";
281 return false;
282 }
283 }
284
285 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/hpack/hpack_decoder.h ('k') | net/spdy/hpack/hpack_decoder3.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698