| Index: net/spdy/hpack_decoder.cc
|
| diff --git a/net/spdy/hpack_decoder.cc b/net/spdy/hpack_decoder.cc
|
| index 2e1d5002079c482ddcc1502b12f5316f66a177f2..6aa4f59a4352196cd04654c7b14908ce0a24ec42 100644
|
| --- a/net/spdy/hpack_decoder.cc
|
| +++ b/net/spdy/hpack_decoder.cc
|
| @@ -15,16 +15,20 @@ namespace net {
|
| using base::StringPiece;
|
| using std::string;
|
|
|
| +namespace {
|
| +
|
| +const uint8 kNoState = 0;
|
| +// Set on entries added to the reference set during this decoding.
|
| +const uint8 kReferencedThisEncoding = 1;
|
| +
|
| +} // namespace
|
| +
|
| HpackDecoder::HpackDecoder(const HpackHuffmanTable& table)
|
| : max_string_literal_size_(kDefaultMaxStringLiteralSize),
|
| huffman_table_(table) {}
|
|
|
| HpackDecoder::~HpackDecoder() {}
|
|
|
| -void HpackDecoder::ApplyHeaderTableSizeSetting(uint32 max_size) {
|
| - context_.ApplyHeaderTableSizeSetting(max_size);
|
| -}
|
| -
|
| bool HpackDecoder::HandleControlFrameHeadersData(SpdyStreamId id,
|
| const char* headers_data,
|
| size_t headers_data_length) {
|
| @@ -50,13 +54,19 @@ bool HpackDecoder::HandleControlFrameHeadersComplete(SpdyStreamId id) {
|
| headers_block_buffer_.clear();
|
|
|
| // Emit everything in the reference set that hasn't already been emitted.
|
| - for (size_t i = 1; i <= context_.GetMutableEntryCount(); ++i) {
|
| - if (context_.IsReferencedAt(i) &&
|
| - (context_.GetTouchCountAt(i) == HpackEncodingContext::kUntouched)) {
|
| - HandleHeaderRepresentation(context_.GetNameAt(i).as_string(),
|
| - context_.GetValueAt(i).as_string());
|
| + // Also clear entry state for the next decoded headers block.
|
| + // TODO(jgraettinger): We may need to revisit the order in which headers
|
| + // are emitted (b/14051713).
|
| + for (HpackEntry::OrderedSet::const_iterator it =
|
| + header_table_.reference_set().begin();
|
| + it != header_table_.reference_set().end(); ++it) {
|
| + HpackEntry* entry = *it;
|
| +
|
| + if (entry->state() == kNoState) {
|
| + HandleHeaderRepresentation(entry->name(), entry->value());
|
| + } else {
|
| + entry->set_state(kNoState);
|
| }
|
| - context_.ClearTouchesAt(i);
|
| }
|
| // Emit the Cookie header, if any crumbles were encountered.
|
| if (!cookie_name_.empty()) {
|
| @@ -117,14 +127,19 @@ bool HpackDecoder::DecodeNextOpcode(HpackInputStream* input_stream) {
|
|
|
| bool HpackDecoder::DecodeNextContextUpdate(HpackInputStream* input_stream) {
|
| if (input_stream->MatchPrefixAndConsume(kEncodingContextEmptyReferenceSet)) {
|
| - return context_.ProcessContextUpdateEmptyReferenceSet();
|
| + header_table_.ClearReferenceSet();
|
| + return true;
|
| }
|
| if (input_stream->MatchPrefixAndConsume(kEncodingContextNewMaximumSize)) {
|
| uint32 size = 0;
|
| if (!input_stream->DecodeNextUint32(&size)) {
|
| return false;
|
| }
|
| - return context_.ProcessContextUpdateNewMaximumSize(size);
|
| + if (size > header_table_.settings_size_bound()) {
|
| + return false;
|
| + }
|
| + header_table_.SetMaxSize(size);
|
| + return true;
|
| }
|
| // Unrecognized encoding context update.
|
| return false;
|
| @@ -138,26 +153,26 @@ bool HpackDecoder::DecodeNextIndexedHeader(HpackInputStream* input_stream) {
|
| // If index == 0, |kEncodingContextOpcode| would have matched.
|
| CHECK_NE(index, 0u);
|
|
|
| - if (index > context_.GetEntryCount())
|
| + HpackEntry* entry = header_table_.GetByIndex(index);
|
| + if (entry == NULL)
|
| return false;
|
|
|
| - bool emitted = false;
|
| - // The index will be put into the reference set.
|
| - if (!context_.IsReferencedAt(index)) {
|
| - HandleHeaderRepresentation(context_.GetNameAt(index).as_string(),
|
| - context_.GetValueAt(index).as_string());
|
| - emitted = true;
|
| - }
|
| + if (entry->IsStatic()) {
|
| + HandleHeaderRepresentation(entry->name(), entry->value());
|
|
|
| - uint32 new_index = 0;
|
| - std::vector<uint32> removed_referenced_indices;
|
| - if (!context_.ProcessIndexedHeader(
|
| - index, &new_index, &removed_referenced_indices)) {
|
| - return false;
|
| + HpackEntry* new_entry = header_table_.TryAddEntry(
|
| + entry->name(), entry->value());
|
| + if (new_entry) {
|
| + header_table_.Toggle(new_entry);
|
| + new_entry->set_state(kReferencedThisEncoding);
|
| + }
|
| + } else {
|
| + entry->set_state(kNoState);
|
| + if (header_table_.Toggle(entry)) {
|
| + HandleHeaderRepresentation(entry->name(), entry->value());
|
| + entry->set_state(kReferencedThisEncoding);
|
| + }
|
| }
|
| - if (emitted && new_index > 0)
|
| - context_.AddTouchesAt(new_index, 0);
|
| -
|
| return true;
|
| }
|
|
|
| @@ -176,16 +191,11 @@ bool HpackDecoder::DecodeNextLiteralHeader(HpackInputStream* input_stream,
|
| if (!should_index)
|
| return true;
|
|
|
| - uint32 new_index = 0;
|
| - std::vector<uint32> removed_referenced_indices;
|
| - if (!context_.ProcessLiteralHeaderWithIncrementalIndexing(
|
| - name, value, &new_index, &removed_referenced_indices)) {
|
| - return false;
|
| + HpackEntry* new_entry = header_table_.TryAddEntry(name, value);
|
| + if (new_entry) {
|
| + header_table_.Toggle(new_entry);
|
| + new_entry->set_state(kReferencedThisEncoding);
|
| }
|
| -
|
| - if (new_index > 0)
|
| - context_.AddTouchesAt(new_index, 0);
|
| -
|
| return true;
|
| }
|
|
|
| @@ -198,11 +208,16 @@ bool HpackDecoder::DecodeNextName(
|
| if (index_or_zero == 0)
|
| return DecodeNextStringLiteral(input_stream, true, next_name);
|
|
|
| - uint32 index = index_or_zero;
|
| - if (index > context_.GetEntryCount())
|
| + const HpackEntry* entry = header_table_.GetByIndex(index_or_zero);
|
| + if (entry == NULL) {
|
| return false;
|
| -
|
| - *next_name = context_.GetNameAt(index_or_zero);
|
| + } else if (entry->IsStatic()) {
|
| + *next_name = entry->name();
|
| + } else {
|
| + // |entry| could be evicted as part of this insertion. Preemptively copy.
|
| + key_buffer_.assign(entry->name());
|
| + *next_name = key_buffer_;
|
| + }
|
| return true;
|
| }
|
|
|
| @@ -210,7 +225,7 @@ bool HpackDecoder::DecodeNextStringLiteral(HpackInputStream* input_stream,
|
| bool is_key,
|
| StringPiece* output) {
|
| if (input_stream->MatchPrefixAndConsume(kStringLiteralHuffmanEncoded)) {
|
| - string* buffer = is_key ? &huffman_key_buffer_ : &huffman_value_buffer_;
|
| + string* buffer = is_key ? &key_buffer_ : &value_buffer_;
|
| bool result = input_stream->DecodeNextHuffmanString(huffman_table_, buffer);
|
| *output = StringPiece(*buffer);
|
| return result;
|
|
|