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

Side by Side Diff: net/spdy/hpack/hpack_input_stream.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_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
(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_input_stream.h"
6
7 #include <algorithm>
8
9 #include "base/logging.h"
10 #include "net/spdy/hpack/hpack_huffman_decoder.h"
11 #include "net/spdy/spdy_bug_tracker.h"
12
13 namespace net {
14
15 HpackInputStream::HpackInputStream(SpdyStringPiece buffer)
16 : buffer_(buffer),
17 bit_offset_(0),
18 parsed_bytes_(0),
19 parsed_bytes_current_(0),
20 need_more_data_(false) {}
21
22 HpackInputStream::~HpackInputStream() {}
23
24 bool HpackInputStream::HasMoreData() const {
25 return !buffer_.empty();
26 }
27
28 bool HpackInputStream::MatchPrefixAndConsume(HpackPrefix prefix) {
29 if (buffer_.empty()) {
30 need_more_data_ = true;
31 return false;
32 }
33
34 DCHECK_GT(prefix.bit_size, 0u);
35 DCHECK_LE(prefix.bit_size, 8u);
36
37 uint32_t peeked = 0;
38 size_t peeked_count = 0;
39
40 if (!PeekBits(&peeked_count, &peeked)) {
41 return false;
42 }
43
44 if ((peeked >> (32 - prefix.bit_size)) == prefix.bits) {
45 ConsumeBits(prefix.bit_size);
46 return true;
47 }
48 return false;
49 }
50
51 bool HpackInputStream::PeekNextOctet(uint8_t* next_octet) {
52 if (buffer_.empty()) {
53 need_more_data_ = true;
54 return false;
55 }
56 if ((bit_offset_ > 0)) {
57 DVLOG(1) << "HpackInputStream::PeekNextOctet bit_offset_=" << bit_offset_;
58 return false;
59 }
60
61 *next_octet = buffer_[0];
62 return true;
63 }
64
65 bool HpackInputStream::DecodeNextOctet(uint8_t* next_octet) {
66 if (!PeekNextOctet(next_octet)) {
67 return false;
68 }
69
70 buffer_.remove_prefix(1);
71 parsed_bytes_current_ += 1;
72 return true;
73 }
74
75 bool HpackInputStream::DecodeNextUint32(uint32_t* I) {
76 size_t N = 8 - bit_offset_;
77 DCHECK_GT(N, 0u);
78 DCHECK_LE(N, 8u);
79
80 bit_offset_ = 0;
81
82 *I = 0;
83
84 uint8_t next_marker = (1 << N) - 1;
85 uint8_t next_octet = 0;
86 if (!DecodeNextOctet(&next_octet)) {
87 if (!need_more_data_) {
88 DVLOG(1) << "HpackInputStream::DecodeNextUint32 initial octet error";
89 }
90 return false;
91 }
92 *I = next_octet & next_marker;
93
94 bool has_more = (*I == next_marker);
95 size_t shift = 0;
96 while (has_more && (shift < 32)) {
97 uint8_t next_octet = 0;
98 if (!DecodeNextOctet(&next_octet)) {
99 if (!need_more_data_) {
100 DVLOG(1) << "HpackInputStream::DecodeNextUint32 shift=" << shift;
101 }
102 return false;
103 }
104 has_more = (next_octet & 0x80) != 0;
105 next_octet &= 0x7f;
106 uint32_t addend = next_octet << shift;
107 // Check for overflow.
108 if ((addend >> shift) != next_octet) {
109 DVLOG(1) << "HpackInputStream::DecodeNextUint32 overflow";
110 return false;
111 }
112 *I += addend;
113 shift += 7;
114 }
115
116 return !has_more;
117 }
118
119 bool HpackInputStream::DecodeNextIdentityString(SpdyStringPiece* str) {
120 uint32_t size = 0;
121 if (!DecodeNextUint32(&size)) {
122 return false;
123 }
124
125 if (size > buffer_.size()) {
126 need_more_data_ = true;
127 return false;
128 }
129
130 *str = SpdyStringPiece(buffer_.data(), size);
131 buffer_.remove_prefix(size);
132 parsed_bytes_current_ += size;
133 return true;
134 }
135
136 bool HpackInputStream::DecodeNextHuffmanString(SpdyString* str) {
137 uint32_t encoded_size = 0;
138 if (!DecodeNextUint32(&encoded_size)) {
139 if (!need_more_data_) {
140 DVLOG(1) << "HpackInputStream::DecodeNextHuffmanString "
141 << "unable to decode size";
142 }
143 return false;
144 }
145
146 if (encoded_size > buffer_.size()) {
147 need_more_data_ = true;
148 DVLOG(1) << "HpackInputStream::DecodeNextHuffmanString " << encoded_size
149 << " > " << buffer_.size();
150 return false;
151 }
152
153 HpackInputStream bounded_reader(buffer_.substr(0, encoded_size));
154 buffer_.remove_prefix(encoded_size);
155 parsed_bytes_current_ += encoded_size;
156
157 return HpackHuffmanDecoder::DecodeString(&bounded_reader, str);
158 }
159
160 bool HpackInputStream::PeekBits(size_t* peeked_count, uint32_t* out) const {
161 size_t byte_offset = (bit_offset_ + *peeked_count) / 8;
162 size_t bit_offset = (bit_offset_ + *peeked_count) % 8;
163
164 if (*peeked_count >= 32 || byte_offset >= buffer_.size()) {
165 return false;
166 }
167 // We'll read the minimum of the current byte remainder,
168 // and the remaining unfilled bits of |out|.
169 size_t bits_to_read = std::min(32 - *peeked_count, 8 - bit_offset);
170
171 uint32_t new_bits = static_cast<uint32_t>(buffer_[byte_offset]);
172 // Shift byte remainder to most-signifcant bits of |new_bits|.
173 // This drops the leading |bit_offset| bits of the byte.
174 new_bits = new_bits << (24 + bit_offset);
175 // Shift bits to the most-significant open bits of |out|.
176 new_bits = new_bits >> *peeked_count;
177
178 CHECK_EQ(*out & new_bits, 0u);
179 *out |= new_bits;
180
181 *peeked_count += bits_to_read;
182 return true;
183 }
184
185 std::pair<size_t, uint32_t> HpackInputStream::InitializePeekBits() {
186 size_t peeked_count = 0;
187 uint32_t bits = 0;
188 if (bit_offset_ == 0) {
189 switch (buffer_.size()) {
190 default:
191 DCHECK_LE(4u, buffer_.size());
192 bits = static_cast<uint32_t>(static_cast<unsigned char>(buffer_[3]));
193 peeked_count += 8;
194 /* FALLTHROUGH */
195 case 3:
196 bits |= (static_cast<uint32_t>(static_cast<unsigned char>(buffer_[2]))
197 << 8);
198 peeked_count += 8;
199 /* FALLTHROUGH */
200 case 2:
201 bits |= (static_cast<uint32_t>(static_cast<unsigned char>(buffer_[1]))
202 << 16);
203 peeked_count += 8;
204 /* FALLTHROUGH */
205 case 1:
206 bits |= (static_cast<uint32_t>(static_cast<unsigned char>(buffer_[0]))
207 << 24);
208 peeked_count += 8;
209 break;
210 case 0:
211 break;
212 }
213 } else {
214 SPDY_BUG << "InitializePeekBits called with non-zero bit_offset_: "
215 << bit_offset_;
216 }
217 return std::make_pair(peeked_count, bits);
218 }
219
220 void HpackInputStream::ConsumeBits(size_t bit_count) {
221 size_t byte_count = (bit_offset_ + bit_count) / 8;
222 bit_offset_ = (bit_offset_ + bit_count) % 8;
223 CHECK_GE(buffer_.size(), byte_count);
224 if (bit_offset_ != 0) {
225 CHECK_GT(buffer_.size(), 0u);
226 }
227 buffer_.remove_prefix(byte_count);
228 parsed_bytes_current_ += byte_count;
229 }
230
231 void HpackInputStream::ConsumeByteRemainder() {
232 if (bit_offset_ != 0) {
233 ConsumeBits(8 - bit_offset_);
234 }
235 }
236
237 uint32_t HpackInputStream::ParsedBytes() const {
238 return parsed_bytes_;
239 }
240
241 bool HpackInputStream::NeedMoreData() const {
242 return need_more_data_;
243 }
244
245 void HpackInputStream::MarkCurrentPosition() {
246 parsed_bytes_ = parsed_bytes_current_;
247 }
248
249 } // 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