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;