blob: 060a88ca130e7a169f82da7f7665c06670cbc3fd (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/spdy/hpack_decoder.h"
#include "base/basictypes.h"
#include "net/spdy/hpack_constants.h"
#include "net/spdy/hpack_output_stream.h"
namespace net {
using base::StringPiece;
HpackDecoder::HpackDecoder(uint32 max_string_literal_size)
: max_string_literal_size_(max_string_literal_size) {}
HpackDecoder::~HpackDecoder() {}
bool HpackDecoder::DecodeHeaderSet(StringPiece input,
HpackHeaderPairVector* header_list) {
HpackInputStream input_stream(max_string_literal_size_, input);
while (input_stream.HasMoreData()) {
// May add to |header_list|.
if (!ProcessNextHeaderRepresentation(&input_stream, header_list))
return false;
}
// After processing opcodes, 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)) {
header_list->push_back(
HpackHeaderPair(context_.GetNameAt(i).as_string(),
context_.GetValueAt(i).as_string()));
}
context_.ClearTouchesAt(i);
}
return true;
}
bool HpackDecoder::ProcessNextHeaderRepresentation(
HpackInputStream* input_stream, HpackHeaderPairVector* header_list) {
// Implements 4.3.1. Literal Header Field without Indexing.
if (input_stream->MatchPrefixAndConsume(kLiteralNoIndexOpcode)) {
StringPiece name;
if (!DecodeNextName(input_stream, &name))
return false;
StringPiece value;
if (!DecodeNextValue(input_stream, &value))
return false;
header_list->push_back(
HpackHeaderPair(name.as_string(), value.as_string()));
return true;
}
return false;
}
bool HpackDecoder::DecodeNextName(
HpackInputStream* input_stream, StringPiece* next_name) {
uint32 index_or_zero = 0;
if (!input_stream->DecodeNextUint32(&index_or_zero))
return false;
if (index_or_zero == 0)
return input_stream->DecodeNextStringLiteral(next_name);
uint32 index = index_or_zero;
if (index > context_.GetEntryCount())
return false;
*next_name = context_.GetNameAt(index_or_zero);
return true;
}
bool HpackDecoder::DecodeNextValue(
HpackInputStream* input_stream, StringPiece* next_name) {
return input_stream->DecodeNextStringLiteral(next_name);
}
} // namespace net
|