Adds a method to the Http2Adapter API to return the HPACK decompressor's dynamic table size.
PiperOrigin-RevId: 378913167
diff --git a/http2/adapter/http2_adapter.h b/http2/adapter/http2_adapter.h
index e346312..c1ee479 100644
--- a/http2/adapter/http2_adapter.h
+++ b/http2/adapter/http2_adapter.h
@@ -91,6 +91,10 @@
// per-entry overhead from the specification.
virtual int GetHpackEncoderDynamicTableSize() const = 0;
+ // Returns the size of the HPACK decoder's dynamic table, including the
+ // per-entry overhead from the specification.
+ virtual int GetHpackDecoderDynamicTableSize() const = 0;
+
// Gets the highest stream ID value seen in a frame received by this endpoint.
// This method is only guaranteed to work for server endpoints.
virtual Http2StreamId GetHighestReceivedStreamId() const = 0;
diff --git a/http2/adapter/nghttp2_adapter.cc b/http2/adapter/nghttp2_adapter.cc
index 41c5ec1..316fc40 100644
--- a/http2/adapter/nghttp2_adapter.cc
+++ b/http2/adapter/nghttp2_adapter.cc
@@ -129,6 +129,10 @@
return nghttp2_session_get_hd_deflate_dynamic_table_size(session_->raw_ptr());
}
+int NgHttp2Adapter::GetHpackDecoderDynamicTableSize() const {
+ return nghttp2_session_get_hd_inflate_dynamic_table_size(session_->raw_ptr());
+}
+
Http2StreamId NgHttp2Adapter::GetHighestReceivedStreamId() const {
return nghttp2_session_get_last_proc_stream_id(session_->raw_ptr());
}
diff --git a/http2/adapter/nghttp2_adapter.h b/http2/adapter/nghttp2_adapter.h
index d34a1ee..10573f2 100644
--- a/http2/adapter/nghttp2_adapter.h
+++ b/http2/adapter/nghttp2_adapter.h
@@ -57,6 +57,7 @@
int GetReceiveWindowSize() const override;
int GetHpackEncoderDynamicTableSize() const override;
+ int GetHpackDecoderDynamicTableSize() const override;
Http2StreamId GetHighestReceivedStreamId() const override;
diff --git a/http2/adapter/nghttp2_adapter_test.cc b/http2/adapter/nghttp2_adapter_test.cc
index 40f3e74..92ac949 100644
--- a/http2/adapter/nghttp2_adapter_test.cc
+++ b/http2/adapter/nghttp2_adapter_test.cc
@@ -164,6 +164,8 @@
EXPECT_EQ(kSentinel2, adapter->GetStreamUserData(stream_id2));
EXPECT_EQ(nullptr, adapter->GetStreamUserData(stream_id3));
+ EXPECT_EQ(0, adapter->GetHpackDecoderDynamicTableSize());
+
const std::string stream_frames =
TestFrameSequence()
.Headers(1,
@@ -213,6 +215,8 @@
EXPECT_EQ(kInitialFlowControlWindowSize,
adapter->GetStreamReceiveWindowLimit(stream_id1));
+ EXPECT_GT(adapter->GetHpackDecoderDynamicTableSize(), 0);
+
// Should be 3, but this method only works for server adapters.
EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
@@ -494,6 +498,7 @@
auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
+ EXPECT_EQ(0, adapter->GetHpackDecoderDynamicTableSize());
const std::string frames = TestFrameSequence()
.ClientPreface()
@@ -571,6 +576,8 @@
EXPECT_EQ(kInitialFlowControlWindowSize,
adapter->GetStreamReceiveWindowLimit(1));
+ EXPECT_GT(adapter->GetHpackDecoderDynamicTableSize(), 0);
+
// Because stream 3 has already been closed, it's not possible to set user
// data.
const char* kSentinel3 = "another arbitrary pointer";
diff --git a/http2/adapter/oghttp2_adapter.cc b/http2/adapter/oghttp2_adapter.cc
index 023c433..e87afa9 100644
--- a/http2/adapter/oghttp2_adapter.cc
+++ b/http2/adapter/oghttp2_adapter.cc
@@ -107,6 +107,10 @@
return session_->GetHpackEncoderDynamicTableSize();
}
+int OgHttp2Adapter::GetHpackDecoderDynamicTableSize() const {
+ return session_->GetHpackDecoderDynamicTableSize();
+}
+
Http2StreamId OgHttp2Adapter::GetHighestReceivedStreamId() const {
return session_->GetHighestReceivedStreamId();
}
diff --git a/http2/adapter/oghttp2_adapter.h b/http2/adapter/oghttp2_adapter.h
index 81189e0..03f7b69 100644
--- a/http2/adapter/oghttp2_adapter.h
+++ b/http2/adapter/oghttp2_adapter.h
@@ -41,6 +41,7 @@
int GetStreamReceiveWindowSize(Http2StreamId stream_id) const override;
int GetReceiveWindowSize() const override;
int GetHpackEncoderDynamicTableSize() const override;
+ int GetHpackDecoderDynamicTableSize() const override;
Http2StreamId GetHighestReceivedStreamId() const override;
void MarkDataConsumedForStream(Http2StreamId stream_id,
size_t num_bytes) override;
diff --git a/http2/adapter/oghttp2_session.cc b/http2/adapter/oghttp2_session.cc
index 80455b0..0ee64d7 100644
--- a/http2/adapter/oghttp2_session.cc
+++ b/http2/adapter/oghttp2_session.cc
@@ -99,6 +99,11 @@
return encoder == nullptr ? 0 : encoder->GetDynamicTableSize();
}
+int OgHttp2Session::GetHpackDecoderDynamicTableSize() const {
+ const spdy::HpackDecoderAdapter* decoder = decoder_.GetHpackDecoder();
+ return decoder == nullptr ? 0 : decoder->GetDynamicTableSize();
+}
+
ssize_t OgHttp2Session::ProcessBytes(absl::string_view bytes) {
ssize_t preface_consumed = 0;
if (!remaining_preface_.empty()) {
diff --git a/http2/adapter/oghttp2_session.h b/http2/adapter/oghttp2_session.h
index 6a9ada7..8e2a7ee 100644
--- a/http2/adapter/oghttp2_session.h
+++ b/http2/adapter/oghttp2_session.h
@@ -75,6 +75,10 @@
// per-entry overhead from the specification.
int GetHpackEncoderDynamicTableSize() const;
+ // Returns the size of the HPACK decoder's dynamic table, including the
+ // per-entry overhead from the specification.
+ int GetHpackDecoderDynamicTableSize() const;
+
// From Http2Session.
ssize_t ProcessBytes(absl::string_view bytes) override;
int Consume(Http2StreamId stream_id, size_t num_bytes) override;
diff --git a/http2/adapter/oghttp2_session_test.cc b/http2/adapter/oghttp2_session_test.cc
index e378a48..be53e47 100644
--- a/http2/adapter/oghttp2_session_test.cc
+++ b/http2/adapter/oghttp2_session_test.cc
@@ -70,6 +70,8 @@
// Connection has not yet received any data.
EXPECT_EQ(kInitialFlowControlWindowSize, session.GetReceiveWindowSize());
+ EXPECT_EQ(0, session.GetHpackDecoderDynamicTableSize());
+
// Should OgHttp2Session require that streams 1 and 3 have been created?
// Submit a request to ensure the first stream is created.
@@ -125,6 +127,8 @@
// Receive window upper bound is still the initial value.
EXPECT_EQ(kInitialFlowControlWindowSize,
session.GetStreamReceiveWindowLimit(stream_id));
+
+ EXPECT_GT(session.GetHpackDecoderDynamicTableSize(), 0);
}
// Verifies that a client session enqueues initial SETTINGS if Send() is called
@@ -379,6 +383,8 @@
OgHttp2Session session(
visitor, OgHttp2Session::Options{.perspective = Perspective::kServer});
+ EXPECT_EQ(0, session.GetHpackDecoderDynamicTableSize());
+
const std::string frames = TestFrameSequence()
.ClientPreface()
.Ping(42)
@@ -457,6 +463,8 @@
EXPECT_EQ(kInitialFlowControlWindowSize,
session.GetStreamReceiveWindowLimit(1));
+ EXPECT_GT(session.GetHpackDecoderDynamicTableSize(), 0);
+
// TODO(birenroy): drop stream state when streams are closed. It should no
// longer be possible to set user data.
const char* kSentinel3 = "another arbitrary pointer";
diff --git a/http2/hpack/decoder/hpack_decoder.h b/http2/hpack/decoder/hpack_decoder.h
index 6cffb3f..9217707 100644
--- a/http2/hpack/decoder/hpack_decoder.h
+++ b/http2/hpack/decoder/hpack_decoder.h
@@ -92,6 +92,10 @@
// detected.
bool DetectError();
+ size_t GetDynamicTableSize() const {
+ return decoder_state_.GetDynamicTableSize();
+ }
+
// Error code if an error has occurred, HpackDecodingError::kOk otherwise.
HpackDecodingError error() const { return error_; }
diff --git a/http2/hpack/decoder/hpack_decoder_state.h b/http2/hpack/decoder/hpack_decoder_state.h
index 14b4184..5dcdc40 100644
--- a/http2/hpack/decoder/hpack_decoder_state.h
+++ b/http2/hpack/decoder/hpack_decoder_state.h
@@ -83,6 +83,10 @@
// No further callbacks will be made to the listener.
HpackDecodingError error() const { return error_; }
+ size_t GetDynamicTableSize() const {
+ return decoder_tables_.current_header_table_size();
+ }
+
const HpackDecoderTables& decoder_tables_for_test() const {
return decoder_tables_;
}
diff --git a/spdy/core/hpack/hpack_decoder_adapter.h b/spdy/core/hpack/hpack_decoder_adapter.h
index cc54dca..43a762b 100644
--- a/spdy/core/hpack/hpack_decoder_adapter.h
+++ b/spdy/core/hpack/hpack_decoder_adapter.h
@@ -67,6 +67,12 @@
// a SpdyHeadersHandlerInterface.
const SpdyHeaderBlock& decoded_block() const;
+ // Returns the current dynamic table size, including the 32 bytes per entry
+ // overhead mentioned in RFC 7541 section 4.1.
+ size_t GetDynamicTableSize() const {
+ return hpack_decoder_.GetDynamicTableSize();
+ }
+
// Set how much encoded data this decoder is willing to buffer.
// TODO(jamessynge): Resolve definition of this value, as it is currently
// too tied to a single implementation. We probably want to limit one or more
diff --git a/spdy/core/http2_frame_decoder_adapter.h b/spdy/core/http2_frame_decoder_adapter.h
index eb038e3..0c105e5 100644
--- a/spdy/core/http2_frame_decoder_adapter.h
+++ b/spdy/core/http2_frame_decoder_adapter.h
@@ -154,6 +154,9 @@
bool probable_http_response() const;
spdy::HpackDecoderAdapter* GetHpackDecoder();
+ const spdy::HpackDecoderAdapter* GetHpackDecoder() const {
+ return hpack_decoder_.get();
+ }
bool HasError() const;