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

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

Issue 1914193002: Implements incremental decode in HPACK. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 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
« no previous file with comments | « net/spdy/hpack/hpack_input_stream.h ('k') | net/spdy/hpack/hpack_input_stream_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/hpack_input_stream.h" 5 #include "net/spdy/hpack/hpack_input_stream.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "net/spdy/hpack/hpack_huffman_decoder.h" 10 #include "net/spdy/hpack/hpack_huffman_decoder.h"
11 #include "net/spdy/spdy_bug_tracker.h" 11 #include "net/spdy/spdy_bug_tracker.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 HpackInputStream::HpackInputStream(uint32_t max_string_literal_size, 18 HpackInputStream::HpackInputStream(uint32_t max_string_literal_size,
19 StringPiece buffer) 19 StringPiece buffer)
20 : max_string_literal_size_(max_string_literal_size), 20 : max_string_literal_size_(max_string_literal_size),
21 buffer_(buffer), 21 buffer_(buffer),
22 bit_offset_(0) {} 22 bit_offset_(0),
23 parsed_bytes_(0),
24 parsed_bytes_current_(0),
25 need_more_data_(false) {}
23 26
24 HpackInputStream::~HpackInputStream() {} 27 HpackInputStream::~HpackInputStream() {}
25 28
26 bool HpackInputStream::HasMoreData() const { 29 bool HpackInputStream::HasMoreData() const {
27 return !buffer_.empty(); 30 return !buffer_.empty();
28 } 31 }
29 32
30 bool HpackInputStream::MatchPrefixAndConsume(HpackPrefix prefix) { 33 bool HpackInputStream::MatchPrefixAndConsume(HpackPrefix prefix) {
34 if (buffer_.empty()) {
35 need_more_data_ = true;
36 return false;
37 }
38
31 DCHECK_GT(prefix.bit_size, 0u); 39 DCHECK_GT(prefix.bit_size, 0u);
32 DCHECK_LE(prefix.bit_size, 8u); 40 DCHECK_LE(prefix.bit_size, 8u);
33 41
34 uint32_t peeked = 0; 42 uint32_t peeked = 0;
35 size_t peeked_count = 0; 43 size_t peeked_count = 0;
36 44
37 if (!PeekBits(&peeked_count, &peeked)) { 45 if (!PeekBits(&peeked_count, &peeked)) {
38 return false; 46 return false;
39 } 47 }
40 48
41 if ((peeked >> (32 - prefix.bit_size)) == prefix.bits) { 49 if ((peeked >> (32 - prefix.bit_size)) == prefix.bits) {
42 ConsumeBits(prefix.bit_size); 50 ConsumeBits(prefix.bit_size);
43 return true; 51 return true;
44 } 52 }
45 return false; 53 return false;
46 } 54 }
47 55
48 bool HpackInputStream::PeekNextOctet(uint8_t* next_octet) { 56 bool HpackInputStream::PeekNextOctet(uint8_t* next_octet) {
49 if ((bit_offset_ > 0) || buffer_.empty()) { 57 if (buffer_.empty()) {
58 need_more_data_ = true;
59 return false;
60 }
61 if ((bit_offset_ > 0)) {
50 DVLOG(1) << "HpackInputStream::PeekNextOctet bit_offset_=" << bit_offset_; 62 DVLOG(1) << "HpackInputStream::PeekNextOctet bit_offset_=" << bit_offset_;
51 return false; 63 return false;
52 } 64 }
53 65
54 *next_octet = buffer_[0]; 66 *next_octet = buffer_[0];
55 return true; 67 return true;
56 } 68 }
57 69
58 bool HpackInputStream::DecodeNextOctet(uint8_t* next_octet) { 70 bool HpackInputStream::DecodeNextOctet(uint8_t* next_octet) {
59 if (!PeekNextOctet(next_octet)) { 71 if (!PeekNextOctet(next_octet)) {
60 return false; 72 return false;
61 } 73 }
62 74
63 buffer_.remove_prefix(1); 75 buffer_.remove_prefix(1);
76 parsed_bytes_current_ += 1;
64 return true; 77 return true;
65 } 78 }
66 79
67 bool HpackInputStream::DecodeNextUint32(uint32_t* I) { 80 bool HpackInputStream::DecodeNextUint32(uint32_t* I) {
68 size_t N = 8 - bit_offset_; 81 size_t N = 8 - bit_offset_;
69 DCHECK_GT(N, 0u); 82 DCHECK_GT(N, 0u);
70 DCHECK_LE(N, 8u); 83 DCHECK_LE(N, 8u);
71 84
72 bit_offset_ = 0; 85 bit_offset_ = 0;
73 86
74 *I = 0; 87 *I = 0;
75 88
76 uint8_t next_marker = (1 << N) - 1; 89 uint8_t next_marker = (1 << N) - 1;
77 uint8_t next_octet = 0; 90 uint8_t next_octet = 0;
78 if (!DecodeNextOctet(&next_octet)) { 91 if (!DecodeNextOctet(&next_octet)) {
79 DVLOG(1) << "HpackInputStream::DecodeNextUint32 initial octet error"; 92 if (!need_more_data_) {
93 DVLOG(1) << "HpackInputStream::DecodeNextUint32 initial octet error";
94 }
80 return false; 95 return false;
81 } 96 }
82 *I = next_octet & next_marker; 97 *I = next_octet & next_marker;
83 98
84 bool has_more = (*I == next_marker); 99 bool has_more = (*I == next_marker);
85 size_t shift = 0; 100 size_t shift = 0;
86 while (has_more && (shift < 32)) { 101 while (has_more && (shift < 32)) {
87 uint8_t next_octet = 0; 102 uint8_t next_octet = 0;
88 if (!DecodeNextOctet(&next_octet)) { 103 if (!DecodeNextOctet(&next_octet)) {
89 DVLOG(1) << "HpackInputStream::DecodeNextUint32 shift=" << shift; 104 if (!need_more_data_) {
105 DVLOG(1) << "HpackInputStream::DecodeNextUint32 shift=" << shift;
106 }
90 return false; 107 return false;
91 } 108 }
92 has_more = (next_octet & 0x80) != 0; 109 has_more = (next_octet & 0x80) != 0;
93 next_octet &= 0x7f; 110 next_octet &= 0x7f;
94 uint32_t addend = next_octet << shift; 111 uint32_t addend = next_octet << shift;
95 // Check for overflow. 112 // Check for overflow.
96 if ((addend >> shift) != next_octet) { 113 if ((addend >> shift) != next_octet) {
97 DVLOG(1) << "HpackInputStream::DecodeNextUint32 overflow"; 114 DVLOG(1) << "HpackInputStream::DecodeNextUint32 overflow";
98 return false; 115 return false;
99 } 116 }
100 *I += addend; 117 *I += addend;
101 shift += 7; 118 shift += 7;
102 } 119 }
103 120
104 return !has_more; 121 return !has_more;
105 } 122 }
106 123
107 bool HpackInputStream::DecodeNextIdentityString(StringPiece* str) { 124 bool HpackInputStream::DecodeNextIdentityString(StringPiece* str) {
108 uint32_t size = 0; 125 uint32_t size = 0;
109 if (!DecodeNextUint32(&size)) { 126 if (!DecodeNextUint32(&size)) {
110 return false; 127 return false;
111 } 128 }
112 129
113 if (size > max_string_literal_size_) { 130 if (size > max_string_literal_size_) {
114 return false; 131 return false;
115 } 132 }
116 133
117 if (size > buffer_.size()) { 134 if (size > buffer_.size()) {
135 need_more_data_ = true;
118 return false; 136 return false;
119 } 137 }
120 138
121 *str = StringPiece(buffer_.data(), size); 139 *str = StringPiece(buffer_.data(), size);
122 buffer_.remove_prefix(size); 140 buffer_.remove_prefix(size);
141 parsed_bytes_current_ += size;
123 return true; 142 return true;
124 } 143 }
125 144
126 bool HpackInputStream::DecodeNextHuffmanString(string* str) { 145 bool HpackInputStream::DecodeNextHuffmanString(string* str) {
127 uint32_t encoded_size = 0; 146 uint32_t encoded_size = 0;
128 if (!DecodeNextUint32(&encoded_size)) { 147 if (!DecodeNextUint32(&encoded_size)) {
129 DVLOG(1) << "HpackInputStream::DecodeNextHuffmanString " 148 if (!need_more_data_) {
130 << "unable to decode size"; 149 DVLOG(1) << "HpackInputStream::DecodeNextHuffmanString "
150 << "unable to decode size";
151 }
131 return false; 152 return false;
132 } 153 }
133 154
134 if (encoded_size > buffer_.size()) { 155 if (encoded_size > buffer_.size()) {
156 need_more_data_ = true;
135 DVLOG(1) << "HpackInputStream::DecodeNextHuffmanString " << encoded_size 157 DVLOG(1) << "HpackInputStream::DecodeNextHuffmanString " << encoded_size
136 << " > " << buffer_.size(); 158 << " > " << buffer_.size();
137 return false; 159 return false;
138 } 160 }
139 161
140 HpackInputStream bounded_reader(max_string_literal_size_, 162 HpackInputStream bounded_reader(max_string_literal_size_,
141 StringPiece(buffer_.data(), encoded_size)); 163 StringPiece(buffer_.data(), encoded_size));
142 buffer_.remove_prefix(encoded_size); 164 buffer_.remove_prefix(encoded_size);
165 parsed_bytes_current_ += encoded_size;
143 166
144 // DecodeString will not append more than |max_string_literal_size_| chars 167 // DecodeString will not append more than |max_string_literal_size_| chars
145 // to |str|. 168 // to |str|.
146 return HpackHuffmanDecoder::DecodeString(&bounded_reader, 169 return HpackHuffmanDecoder::DecodeString(&bounded_reader,
147 max_string_literal_size_, str); 170 max_string_literal_size_, str);
148 } 171 }
149 172
150 bool HpackInputStream::PeekBits(size_t* peeked_count, uint32_t* out) const { 173 bool HpackInputStream::PeekBits(size_t* peeked_count, uint32_t* out) const {
151 size_t byte_offset = (bit_offset_ + *peeked_count) / 8; 174 size_t byte_offset = (bit_offset_ + *peeked_count) / 8;
152 size_t bit_offset = (bit_offset_ + *peeked_count) % 8; 175 size_t bit_offset = (bit_offset_ + *peeked_count) % 8;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 } 231 }
209 232
210 void HpackInputStream::ConsumeBits(size_t bit_count) { 233 void HpackInputStream::ConsumeBits(size_t bit_count) {
211 size_t byte_count = (bit_offset_ + bit_count) / 8; 234 size_t byte_count = (bit_offset_ + bit_count) / 8;
212 bit_offset_ = (bit_offset_ + bit_count) % 8; 235 bit_offset_ = (bit_offset_ + bit_count) % 8;
213 CHECK_GE(buffer_.size(), byte_count); 236 CHECK_GE(buffer_.size(), byte_count);
214 if (bit_offset_ != 0) { 237 if (bit_offset_ != 0) {
215 CHECK_GT(buffer_.size(), 0u); 238 CHECK_GT(buffer_.size(), 0u);
216 } 239 }
217 buffer_.remove_prefix(byte_count); 240 buffer_.remove_prefix(byte_count);
241 parsed_bytes_current_ += byte_count;
218 } 242 }
219 243
220 void HpackInputStream::ConsumeByteRemainder() { 244 void HpackInputStream::ConsumeByteRemainder() {
221 if (bit_offset_ != 0) { 245 if (bit_offset_ != 0) {
222 ConsumeBits(8 - bit_offset_); 246 ConsumeBits(8 - bit_offset_);
223 } 247 }
224 } 248 }
225 249
250 uint32_t HpackInputStream::ParsedBytes() const {
251 return parsed_bytes_;
252 }
253
254 bool HpackInputStream::NeedMoreData() const {
255 return need_more_data_;
256 }
257
258 void HpackInputStream::MarkCurrentPosition() {
259 parsed_bytes_ = parsed_bytes_current_;
260 }
261
226 } // namespace net 262 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/hpack/hpack_input_stream.h ('k') | net/spdy/hpack/hpack_input_stream_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698