| 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 |