Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1993)

Unified Diff: net/http2/hpack/decoder/hpack_decoder_string_buffer.cc

Issue 2293613002: Add new HTTP/2 and HPACK decoder in net/http2/. (Closed)
Patch Set: Replace LOG(INFO) by VLOG(2) in DecodeBufferTest.SlowDecodeTestStruct so that trybots do not fail. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/http2/hpack/decoder/hpack_decoder_string_buffer.cc
diff --git a/net/http2/hpack/decoder/hpack_decoder_string_buffer.cc b/net/http2/hpack/decoder/hpack_decoder_string_buffer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..90d03365422bfd6c2a833eba2d5a4cbdb2076385
--- /dev/null
+++ b/net/http2/hpack/decoder/hpack_decoder_string_buffer.cc
@@ -0,0 +1,215 @@
+// Copyright 2016 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/http2/hpack/decoder/hpack_decoder_string_buffer.h"
+
+#include "base/logging.h"
+
+using base::StringPiece;
+
+namespace net {
+
+std::ostream& operator<<(std::ostream& out,
+ const HpackDecoderStringBuffer::State v) {
+ switch (v) {
+ case HpackDecoderStringBuffer::State::RESET:
+ return out << "RESET";
+ case HpackDecoderStringBuffer::State::COLLECTING:
+ return out << "COLLECTING";
+ case HpackDecoderStringBuffer::State::COMPLETE:
+ return out << "COMPLETE";
+ default:
+ return out << "Unknown HpackDecoderStringBuffer::State!";
+ }
+}
+
+std::ostream& operator<<(std::ostream& out,
+ const HpackDecoderStringBuffer::Backing v) {
+ switch (v) {
+ case HpackDecoderStringBuffer::Backing::RESET:
+ return out << "RESET";
+ case HpackDecoderStringBuffer::Backing::UNBUFFERED:
+ return out << "UNBUFFERED";
+ case HpackDecoderStringBuffer::Backing::BUFFERED:
+ return out << "BUFFERED";
+ case HpackDecoderStringBuffer::Backing::STATIC:
+ return out << "STATIC";
+ default:
+ return out << "Unknown HpackDecoderStringBuffer::Backing!";
+ }
+}
+
+HpackDecoderStringBuffer::HpackDecoderStringBuffer() {
+ Reset();
+}
+HpackDecoderStringBuffer::~HpackDecoderStringBuffer() {}
+
+// TODO(jamessynge): Consider eliminating most of Reset (i.e. do less); in
+// particular, if a variable won't be read again until after it is next set
+// (e.g. is_huffman_encoded_ or remaining_len_), then it doesn't need to be
+// cleared here. This will be easier when not supporting both HpackDecoder2
+// (in net/spdy/hpack) and HpackWholeEntryDecoder, so we can eliminate
+// the Set() and str() methods.
+void HpackDecoderStringBuffer::Reset() {
+ DVLOG(3) << "HpackDecoderStringBuffer::Reset";
+ buffer_.clear();
+ value_.clear();
+ remaining_len_ = 0;
+ is_huffman_encoded_ = false;
+ state_ = State::RESET;
+ backing_ = Backing::RESET;
+}
+
+void HpackDecoderStringBuffer::Set(StringPiece value, bool is_static) {
+ DVLOG(2) << "HpackDecoderStringBuffer::Set";
+ DCHECK_EQ(state_, State::RESET);
+ DCHECK_EQ(backing_, Backing::RESET);
+ value_ = value;
+ state_ = State::COMPLETE;
+ backing_ = is_static ? Backing::STATIC : Backing::UNBUFFERED;
+}
+
+void HpackDecoderStringBuffer::OnStart(bool huffman_encoded, size_t len) {
+ DVLOG(2) << "HpackDecoderStringBuffer::OnStart";
+ DCHECK_EQ(state_, State::RESET);
+ DCHECK_EQ(backing_, Backing::RESET);
+ buffer_.clear();
+ value_.clear();
+
+ remaining_len_ = len;
+ is_huffman_encoded_ = huffman_encoded;
+
+ state_ = State::COLLECTING;
+
+ if (huffman_encoded) {
+ decoder_.Reset();
+ backing_ = Backing::BUFFERED;
+
+ // Reserve space in buffer_ for the uncompressed string, assuming the
+ // maximum expansion. The shortest Huffman codes in the RFC are 5 bits long,
+ // which then expand to 8 bits during decoding (i.e. each code is for one
+ // plain text octet, aka byte), so the maximum size is 60% longer than the
+ // encoded size.
+ len = len * 8 / 5;
+ if (buffer_.capacity() < len) {
+ buffer_.reserve(len);
+ }
+ } else {
+ // Assume for now that we won't need to use buffer_, so don't reserve space
+ // in it.
+ backing_ = Backing::RESET;
+ }
+}
+
+bool HpackDecoderStringBuffer::OnData(const char* data, size_t len) {
+ DVLOG(2) << "HpackDecoderStringBuffer::OnData state=" << state_
+ << ", backing=" << backing_;
+ DCHECK_EQ(state_, State::COLLECTING);
+ DCHECK_LE(len, remaining_len_);
+ remaining_len_ -= len;
+
+ if (is_huffman_encoded_) {
+ DCHECK_EQ(backing_, Backing::BUFFERED);
+ // We don't set value_ for buffered strings until OnEnd,
+ // so it should be empty.
+ DCHECK_EQ(0u, value_.size());
+ return decoder_.Decode(StringPiece(data, len), &buffer_);
+ }
+
+ if (backing_ == Backing::RESET) {
+ // This is the first call to OnData.
+ DCHECK_EQ(0u, buffer_.size());
+ DCHECK_EQ(0u, value_.size());
+ // If data contains the entire string, don't copy the string. If we later
+ // find that the HPACK entry is split across input buffers, then we'll
+ // copy the string into buffer_.
+ if (remaining_len_ == 0) {
+ value_ = StringPiece(data, len);
+ backing_ = Backing::UNBUFFERED;
+ return true;
+ }
+
+ // We need to buffer the string because it is split across input buffers.
+ backing_ = Backing::BUFFERED;
+ buffer_.assign(data, len);
+ return true;
+ }
+
+ // This is not the first call to OnData for this string, so it should be
+ // buffered.
+ DCHECK_EQ(backing_, Backing::BUFFERED);
+ // We don't set value_ for buffered strings until OnEnd, so it should be
+ // empty.
+ DCHECK_EQ(0u, value_.size());
+
+ // Append to the current contents of the buffer.
+ buffer_.append(data, len);
+ return true;
+}
+
+bool HpackDecoderStringBuffer::OnEnd() {
+ DVLOG(2) << "HpackDecoderStringBuffer::OnEnd";
+ DCHECK_EQ(state_, State::COLLECTING);
+ DCHECK_EQ(0u, remaining_len_);
+
+ if (is_huffman_encoded_) {
+ DCHECK_EQ(backing_, Backing::BUFFERED);
+ // Did the Huffman encoding of the string end properly?
+ if (!decoder_.InputProperlyTerminated()) {
+ return false; // No, it didn't.
+ }
+ }
+ state_ = State::COMPLETE;
+ if (backing_ == Backing::BUFFERED) {
+ value_ = buffer_;
+ }
+ return true;
+}
+
+void HpackDecoderStringBuffer::BufferStringIfUnbuffered() {
+ DVLOG(3) << "HpackDecoderStringBuffer::BufferStringIfUnbuffered state="
+ << state_ << ", backing=" << backing_;
+ if (state_ != State::RESET && backing_ == Backing::UNBUFFERED) {
+ DVLOG(2) << "HpackDecoderStringBuffer buffering string of length "
+ << value_.size();
+ value_.CopyToString(&buffer_);
+ if (state_ == State::COMPLETE) {
+ value_ = buffer_;
+ }
+ backing_ = Backing::BUFFERED;
+ }
+}
+
+size_t HpackDecoderStringBuffer::BufferedLength() const {
+ DVLOG(3) << "HpackDecoderStringBuffer::BufferedLength";
+ return backing_ == Backing::BUFFERED ? buffer_.size() : 0;
+}
+
+StringPiece HpackDecoderStringBuffer::str() const {
+ DVLOG(3) << "HpackDecoderStringBuffer::str";
+ DCHECK_EQ(state_, State::COMPLETE);
+ return value_;
+}
+
+void HpackDecoderStringBuffer::OutputDebugStringTo(std::ostream& out) const {
+ out << "{state=" << state_;
+ if (state_ != State::RESET) {
+ out << ", backing=" << backing_;
+ out << ", remaining_len=" << remaining_len_;
+ out << ", is_huffman_encoded=" << is_huffman_encoded_;
+ if (backing_ == Backing::BUFFERED) {
+ out << ", buffer: " << buffer_;
+ } else {
+ out << ", value: " << value_;
+ }
+ }
+ out << "}";
+}
+
+std::ostream& operator<<(std::ostream& out, const HpackDecoderStringBuffer& v) {
+ v.OutputDebugStringTo(out);
+ return out;
+}
+
+} // namespace net
« no previous file with comments | « net/http2/hpack/decoder/hpack_decoder_string_buffer.h ('k') | net/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698