summaryrefslogtreecommitdiffstats
path: root/net/spdy/hpack_decoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'net/spdy/hpack_decoder.cc')
-rw-r--r--net/spdy/hpack_decoder.cc86
1 files changed, 86 insertions, 0 deletions
diff --git a/net/spdy/hpack_decoder.cc b/net/spdy/hpack_decoder.cc
new file mode 100644
index 0000000..060a88c
--- /dev/null
+++ b/net/spdy/hpack_decoder.cc
@@ -0,0 +1,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