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;