OLD | NEW |
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 Loading... |
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 |
OLD | NEW |