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

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

Issue 246073007: SPDY & HPACK: Land recent internal changes (through 65328503) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase on upstream change: Expanded FRAME_TOO_LARGE/FRAME_SIZE_ERROR comment. Created 6 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « net/spdy/hpack_decoder.h ('k') | net/spdy/hpack_decoder_test.cc » ('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 2014 The Chromium Authors. All rights reserved. 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 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/hpack_decoder.h" 5 #include "net/spdy/hpack_decoder.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/strings/string_util.h" 9 #include "base/strings/string_util.h"
10 #include "net/spdy/hpack_constants.h" 10 #include "net/spdy/hpack_constants.h"
11 #include "net/spdy/hpack_output_stream.h" 11 #include "net/spdy/hpack_output_stream.h"
12 12
13 namespace net { 13 namespace net {
14 14
15 using base::StringPiece; 15 using base::StringPiece;
16 using std::string; 16 using std::string;
17 17
18 namespace {
19
20 const uint8 kNoState = 0;
21 // Set on entries added to the reference set during this decoding.
22 const uint8 kReferencedThisEncoding = 1;
23
24 } // namespace
25
18 HpackDecoder::HpackDecoder(const HpackHuffmanTable& table) 26 HpackDecoder::HpackDecoder(const HpackHuffmanTable& table)
19 : max_string_literal_size_(kDefaultMaxStringLiteralSize), 27 : max_string_literal_size_(kDefaultMaxStringLiteralSize),
20 huffman_table_(table) {} 28 huffman_table_(table) {}
21 29
22 HpackDecoder::~HpackDecoder() {} 30 HpackDecoder::~HpackDecoder() {}
23 31
24 void HpackDecoder::ApplyHeaderTableSizeSetting(uint32 max_size) {
25 context_.ApplyHeaderTableSizeSetting(max_size);
26 }
27
28 bool HpackDecoder::HandleControlFrameHeadersData(SpdyStreamId id, 32 bool HpackDecoder::HandleControlFrameHeadersData(SpdyStreamId id,
29 const char* headers_data, 33 const char* headers_data,
30 size_t headers_data_length) { 34 size_t headers_data_length) {
31 decoded_block_.clear(); 35 decoded_block_.clear();
32 36
33 size_t new_size = headers_block_buffer_.size() + headers_data_length; 37 size_t new_size = headers_block_buffer_.size() + headers_data_length;
34 if (new_size > kMaxDecodeBufferSize) { 38 if (new_size > kMaxDecodeBufferSize) {
35 return false; 39 return false;
36 } 40 }
37 headers_block_buffer_.insert(headers_block_buffer_.end(), 41 headers_block_buffer_.insert(headers_block_buffer_.end(),
38 headers_data, 42 headers_data,
39 headers_data + headers_data_length); 43 headers_data + headers_data_length);
40 return true; 44 return true;
41 } 45 }
42 46
43 bool HpackDecoder::HandleControlFrameHeadersComplete(SpdyStreamId id) { 47 bool HpackDecoder::HandleControlFrameHeadersComplete(SpdyStreamId id) {
44 HpackInputStream input_stream(max_string_literal_size_, 48 HpackInputStream input_stream(max_string_literal_size_,
45 headers_block_buffer_); 49 headers_block_buffer_);
46 while (input_stream.HasMoreData()) { 50 while (input_stream.HasMoreData()) {
47 if (!DecodeNextOpcode(&input_stream)) 51 if (!DecodeNextOpcode(&input_stream))
48 return false; 52 return false;
49 } 53 }
50 headers_block_buffer_.clear(); 54 headers_block_buffer_.clear();
51 55
52 // Emit everything in the reference set that hasn't already been emitted. 56 // Emit everything in the reference set that hasn't already been emitted.
53 for (size_t i = 1; i <= context_.GetMutableEntryCount(); ++i) { 57 // Also clear entry state for the next decoded headers block.
54 if (context_.IsReferencedAt(i) && 58 // TODO(jgraettinger): We may need to revisit the order in which headers
55 (context_.GetTouchCountAt(i) == HpackEncodingContext::kUntouched)) { 59 // are emitted (b/14051713).
56 HandleHeaderRepresentation(context_.GetNameAt(i).as_string(), 60 for (HpackEntry::OrderedSet::const_iterator it =
57 context_.GetValueAt(i).as_string()); 61 header_table_.reference_set().begin();
62 it != header_table_.reference_set().end(); ++it) {
63 HpackEntry* entry = *it;
64
65 if (entry->state() == kNoState) {
66 HandleHeaderRepresentation(entry->name(), entry->value());
67 } else {
68 entry->set_state(kNoState);
58 } 69 }
59 context_.ClearTouchesAt(i);
60 } 70 }
61 // Emit the Cookie header, if any crumbles were encountered. 71 // Emit the Cookie header, if any crumbles were encountered.
62 if (!cookie_name_.empty()) { 72 if (!cookie_name_.empty()) {
63 decoded_block_[cookie_name_] = cookie_value_; 73 decoded_block_[cookie_name_] = cookie_value_;
64 cookie_name_.clear(); 74 cookie_name_.clear();
65 cookie_value_.clear(); 75 cookie_value_.clear();
66 } 76 }
67 return true; 77 return true;
68 } 78 }
69 79
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 // Implements 4.3.2: Literal Header Field with Incremental Indexing. 120 // Implements 4.3.2: Literal Header Field with Incremental Indexing.
111 if (input_stream->MatchPrefixAndConsume(kLiteralIncrementalIndexOpcode)) { 121 if (input_stream->MatchPrefixAndConsume(kLiteralIncrementalIndexOpcode)) {
112 return DecodeNextLiteralHeader(input_stream, true); 122 return DecodeNextLiteralHeader(input_stream, true);
113 } 123 }
114 // Unrecognized opcode. 124 // Unrecognized opcode.
115 return false; 125 return false;
116 } 126 }
117 127
118 bool HpackDecoder::DecodeNextContextUpdate(HpackInputStream* input_stream) { 128 bool HpackDecoder::DecodeNextContextUpdate(HpackInputStream* input_stream) {
119 if (input_stream->MatchPrefixAndConsume(kEncodingContextEmptyReferenceSet)) { 129 if (input_stream->MatchPrefixAndConsume(kEncodingContextEmptyReferenceSet)) {
120 return context_.ProcessContextUpdateEmptyReferenceSet(); 130 header_table_.ClearReferenceSet();
131 return true;
121 } 132 }
122 if (input_stream->MatchPrefixAndConsume(kEncodingContextNewMaximumSize)) { 133 if (input_stream->MatchPrefixAndConsume(kEncodingContextNewMaximumSize)) {
123 uint32 size = 0; 134 uint32 size = 0;
124 if (!input_stream->DecodeNextUint32(&size)) { 135 if (!input_stream->DecodeNextUint32(&size)) {
125 return false; 136 return false;
126 } 137 }
127 return context_.ProcessContextUpdateNewMaximumSize(size); 138 if (size > header_table_.settings_size_bound()) {
139 return false;
140 }
141 header_table_.SetMaxSize(size);
142 return true;
128 } 143 }
129 // Unrecognized encoding context update. 144 // Unrecognized encoding context update.
130 return false; 145 return false;
131 } 146 }
132 147
133 bool HpackDecoder::DecodeNextIndexedHeader(HpackInputStream* input_stream) { 148 bool HpackDecoder::DecodeNextIndexedHeader(HpackInputStream* input_stream) {
134 uint32 index = 0; 149 uint32 index = 0;
135 if (!input_stream->DecodeNextUint32(&index)) 150 if (!input_stream->DecodeNextUint32(&index))
136 return false; 151 return false;
137 152
138 // If index == 0, |kEncodingContextOpcode| would have matched. 153 // If index == 0, |kEncodingContextOpcode| would have matched.
139 CHECK_NE(index, 0u); 154 CHECK_NE(index, 0u);
140 155
141 if (index > context_.GetEntryCount()) 156 HpackEntry* entry = header_table_.GetByIndex(index);
157 if (entry == NULL)
142 return false; 158 return false;
143 159
144 bool emitted = false; 160 if (entry->IsStatic()) {
145 // The index will be put into the reference set. 161 HandleHeaderRepresentation(entry->name(), entry->value());
146 if (!context_.IsReferencedAt(index)) { 162
147 HandleHeaderRepresentation(context_.GetNameAt(index).as_string(), 163 HpackEntry* new_entry = header_table_.TryAddEntry(
148 context_.GetValueAt(index).as_string()); 164 entry->name(), entry->value());
149 emitted = true; 165 if (new_entry) {
166 header_table_.Toggle(new_entry);
167 new_entry->set_state(kReferencedThisEncoding);
168 }
169 } else {
170 entry->set_state(kNoState);
171 if (header_table_.Toggle(entry)) {
172 HandleHeaderRepresentation(entry->name(), entry->value());
173 entry->set_state(kReferencedThisEncoding);
174 }
150 } 175 }
151
152 uint32 new_index = 0;
153 std::vector<uint32> removed_referenced_indices;
154 if (!context_.ProcessIndexedHeader(
155 index, &new_index, &removed_referenced_indices)) {
156 return false;
157 }
158 if (emitted && new_index > 0)
159 context_.AddTouchesAt(new_index, 0);
160
161 return true; 176 return true;
162 } 177 }
163 178
164 bool HpackDecoder::DecodeNextLiteralHeader(HpackInputStream* input_stream, 179 bool HpackDecoder::DecodeNextLiteralHeader(HpackInputStream* input_stream,
165 bool should_index) { 180 bool should_index) {
166 StringPiece name; 181 StringPiece name;
167 if (!DecodeNextName(input_stream, &name)) 182 if (!DecodeNextName(input_stream, &name))
168 return false; 183 return false;
169 184
170 StringPiece value; 185 StringPiece value;
171 if (!DecodeNextStringLiteral(input_stream, false, &value)) 186 if (!DecodeNextStringLiteral(input_stream, false, &value))
172 return false; 187 return false;
173 188
174 HandleHeaderRepresentation(name, value); 189 HandleHeaderRepresentation(name, value);
175 190
176 if (!should_index) 191 if (!should_index)
177 return true; 192 return true;
178 193
179 uint32 new_index = 0; 194 HpackEntry* new_entry = header_table_.TryAddEntry(name, value);
180 std::vector<uint32> removed_referenced_indices; 195 if (new_entry) {
181 if (!context_.ProcessLiteralHeaderWithIncrementalIndexing( 196 header_table_.Toggle(new_entry);
182 name, value, &new_index, &removed_referenced_indices)) { 197 new_entry->set_state(kReferencedThisEncoding);
183 return false;
184 } 198 }
185
186 if (new_index > 0)
187 context_.AddTouchesAt(new_index, 0);
188
189 return true; 199 return true;
190 } 200 }
191 201
192 bool HpackDecoder::DecodeNextName( 202 bool HpackDecoder::DecodeNextName(
193 HpackInputStream* input_stream, StringPiece* next_name) { 203 HpackInputStream* input_stream, StringPiece* next_name) {
194 uint32 index_or_zero = 0; 204 uint32 index_or_zero = 0;
195 if (!input_stream->DecodeNextUint32(&index_or_zero)) 205 if (!input_stream->DecodeNextUint32(&index_or_zero))
196 return false; 206 return false;
197 207
198 if (index_or_zero == 0) 208 if (index_or_zero == 0)
199 return DecodeNextStringLiteral(input_stream, true, next_name); 209 return DecodeNextStringLiteral(input_stream, true, next_name);
200 210
201 uint32 index = index_or_zero; 211 const HpackEntry* entry = header_table_.GetByIndex(index_or_zero);
202 if (index > context_.GetEntryCount()) 212 if (entry == NULL) {
203 return false; 213 return false;
204 214 } else if (entry->IsStatic()) {
205 *next_name = context_.GetNameAt(index_or_zero); 215 *next_name = entry->name();
216 } else {
217 // |entry| could be evicted as part of this insertion. Preemptively copy.
218 key_buffer_.assign(entry->name());
219 *next_name = key_buffer_;
220 }
206 return true; 221 return true;
207 } 222 }
208 223
209 bool HpackDecoder::DecodeNextStringLiteral(HpackInputStream* input_stream, 224 bool HpackDecoder::DecodeNextStringLiteral(HpackInputStream* input_stream,
210 bool is_key, 225 bool is_key,
211 StringPiece* output) { 226 StringPiece* output) {
212 if (input_stream->MatchPrefixAndConsume(kStringLiteralHuffmanEncoded)) { 227 if (input_stream->MatchPrefixAndConsume(kStringLiteralHuffmanEncoded)) {
213 string* buffer = is_key ? &huffman_key_buffer_ : &huffman_value_buffer_; 228 string* buffer = is_key ? &key_buffer_ : &value_buffer_;
214 bool result = input_stream->DecodeNextHuffmanString(huffman_table_, buffer); 229 bool result = input_stream->DecodeNextHuffmanString(huffman_table_, buffer);
215 *output = StringPiece(*buffer); 230 *output = StringPiece(*buffer);
216 return result; 231 return result;
217 } else if (input_stream->MatchPrefixAndConsume( 232 } else if (input_stream->MatchPrefixAndConsume(
218 kStringLiteralIdentityEncoded)) { 233 kStringLiteralIdentityEncoded)) {
219 return input_stream->DecodeNextIdentityString(output); 234 return input_stream->DecodeNextIdentityString(output);
220 } else { 235 } else {
221 return false; 236 return false;
222 } 237 }
223 } 238 }
224 239
225 } // namespace net 240 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/hpack_decoder.h ('k') | net/spdy/hpack_decoder_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698