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_encoder.h" | 5 #include "net/spdy/hpack_encoder.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_header_table.h" | 10 #include "net/spdy/hpack_header_table.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 // Set on a referenced HpackEntry which is not part of the current header set. | 24 // Set on a referenced HpackEntry which is not part of the current header set. |
25 const uint8 kReferencedExplicitOff = 2; | 25 const uint8 kReferencedExplicitOff = 2; |
26 // Set on a entries added to the reference set during this encoding. | 26 // Set on a entries added to the reference set during this encoding. |
27 const uint8 kReferencedThisEncoding = 3; | 27 const uint8 kReferencedThisEncoding = 3; |
28 | 28 |
29 } // namespace | 29 } // namespace |
30 | 30 |
31 HpackEncoder::HpackEncoder(const HpackHuffmanTable& table) | 31 HpackEncoder::HpackEncoder(const HpackHuffmanTable& table) |
32 : output_stream_(), | 32 : output_stream_(), |
33 allow_huffman_compression_(true), | 33 allow_huffman_compression_(true), |
34 huffman_table_(table) {} | 34 huffman_table_(table), |
| 35 char_counts_(NULL), |
| 36 total_char_counts_(NULL) {} |
35 | 37 |
36 HpackEncoder::~HpackEncoder() {} | 38 HpackEncoder::~HpackEncoder() {} |
37 | 39 |
38 bool HpackEncoder::EncodeHeaderSet(const std::map<string, string>& header_set, | 40 bool HpackEncoder::EncodeHeaderSet(const std::map<string, string>& header_set, |
39 string* output) { | 41 string* output) { |
40 // Walk the set of entries to encode, which are not already implied by the | 42 // Walk the set of entries to encode, which are not already implied by the |
41 // header table's reference set. They must be explicitly emitted. | 43 // header table's reference set. They must be explicitly emitted. |
42 Representations explicit_set(DetermineEncodingDelta(header_set)); | 44 Representations explicit_set(DetermineEncodingDelta(header_set)); |
43 for (Representations::const_iterator it = explicit_set.begin(); | 45 for (Representations::const_iterator it = explicit_set.begin(); |
44 it != explicit_set.end(); ++it) { | 46 it != explicit_set.end(); ++it) { |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 : huffman_table_.EncodedSize(str)); | 173 : huffman_table_.EncodedSize(str)); |
172 if (encoded_size < str.size()) { | 174 if (encoded_size < str.size()) { |
173 output_stream_.AppendPrefix(kStringLiteralHuffmanEncoded); | 175 output_stream_.AppendPrefix(kStringLiteralHuffmanEncoded); |
174 output_stream_.AppendUint32(encoded_size); | 176 output_stream_.AppendUint32(encoded_size); |
175 huffman_table_.EncodeString(str, &output_stream_); | 177 huffman_table_.EncodeString(str, &output_stream_); |
176 } else { | 178 } else { |
177 output_stream_.AppendPrefix(kStringLiteralIdentityEncoded); | 179 output_stream_.AppendPrefix(kStringLiteralIdentityEncoded); |
178 output_stream_.AppendUint32(str.size()); | 180 output_stream_.AppendUint32(str.size()); |
179 output_stream_.AppendBytes(str); | 181 output_stream_.AppendBytes(str); |
180 } | 182 } |
| 183 UpdateCharacterCounts(str); |
181 } | 184 } |
182 | 185 |
183 // static | 186 // static |
184 HpackEncoder::Representations HpackEncoder::DetermineEncodingDelta( | 187 HpackEncoder::Representations HpackEncoder::DetermineEncodingDelta( |
185 const std::map<string, string>& header_set) { | 188 const std::map<string, string>& header_set) { |
186 // Flatten & crumble headers into an ordered list of representations. | 189 // Flatten & crumble headers into an ordered list of representations. |
187 Representations full_set; | 190 Representations full_set; |
188 for (std::map<string, string>::const_iterator it = header_set.begin(); | 191 for (std::map<string, string>::const_iterator it = header_set.begin(); |
189 it != header_set.end(); ++it) { | 192 it != header_set.end(); ++it) { |
190 if (it->first == "cookie") { | 193 if (it->first == "cookie") { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 explicit_set.push_back(*r_it); | 233 explicit_set.push_back(*r_it); |
231 ++r_it; | 234 ++r_it; |
232 } | 235 } |
233 while (s_it != header_table_.reference_set().end()) { | 236 while (s_it != header_table_.reference_set().end()) { |
234 (*s_it)->set_state(kReferencedExplicitOff); | 237 (*s_it)->set_state(kReferencedExplicitOff); |
235 ++s_it; | 238 ++s_it; |
236 } | 239 } |
237 return explicit_set; | 240 return explicit_set; |
238 } | 241 } |
239 | 242 |
| 243 void HpackEncoder::SetCharCountsStorage(std::vector<size_t>* char_counts, |
| 244 size_t* total_char_counts) { |
| 245 CHECK_LE(256u, char_counts->size()); |
| 246 char_counts_ = char_counts; |
| 247 total_char_counts_ = total_char_counts; |
| 248 } |
| 249 |
| 250 void HpackEncoder::UpdateCharacterCounts(base::StringPiece str) { |
| 251 if (char_counts_ == NULL || total_char_counts_ == NULL) { |
| 252 return; |
| 253 } |
| 254 for (StringPiece::const_iterator it = str.begin(); it != str.end(); ++it) { |
| 255 ++(*char_counts_)[static_cast<uint8>(*it)]; |
| 256 } |
| 257 (*total_char_counts_) += str.size(); |
| 258 } |
| 259 |
240 // static | 260 // static |
241 void HpackEncoder::CookieToCrumbs(const Representation& cookie, | 261 void HpackEncoder::CookieToCrumbs(const Representation& cookie, |
242 Representations* out) { | 262 Representations* out) { |
243 // See Section 8.1.3.4 "Compressing the Cookie Header Field" in the HTTP/2 | 263 // See Section 8.1.3.4 "Compressing the Cookie Header Field" in the HTTP/2 |
244 // specification at http://tools.ietf.org/html/draft-ietf-httpbis-http2-11 | 264 // specification at http://tools.ietf.org/html/draft-ietf-httpbis-http2-11 |
245 // Cookie values are split into individually-encoded HPACK representations. | 265 // Cookie values are split into individually-encoded HPACK representations. |
246 for (size_t pos = 0;;) { | 266 for (size_t pos = 0;;) { |
247 size_t end = cookie.second.find(";", pos); | 267 size_t end = cookie.second.find(";", pos); |
248 | 268 |
249 if (end == StringPiece::npos) { | 269 if (end == StringPiece::npos) { |
250 out->push_back(make_pair( | 270 out->push_back(make_pair( |
251 cookie.first, | 271 cookie.first, |
252 cookie.second.substr(pos))); | 272 cookie.second.substr(pos))); |
253 return; | 273 return; |
254 } | 274 } |
255 out->push_back(make_pair( | 275 out->push_back(make_pair( |
256 cookie.first, | 276 cookie.first, |
257 cookie.second.substr(pos, end - pos))); | 277 cookie.second.substr(pos, end - pos))); |
258 | 278 |
259 // Consume next space if present. | 279 // Consume next space if present. |
260 pos = end + 1; | 280 pos = end + 1; |
261 if (pos != cookie.second.size() && cookie.second[pos] == ' ') { | 281 if (pos != cookie.second.size() && cookie.second[pos] == ' ') { |
262 pos++; | 282 pos++; |
263 } | 283 } |
264 } | 284 } |
265 } | 285 } |
266 | 286 |
267 } // namespace net | 287 } // namespace net |
OLD | NEW |