Adds a method to the Http2Adapter API to retrieve the HPACK compressor's dynamic table size.

PiperOrigin-RevId: 378894428
diff --git a/http2/adapter/http2_adapter.h b/http2/adapter/http2_adapter.h
index 4f2b3f3..e346312 100644
--- a/http2/adapter/http2_adapter.h
+++ b/http2/adapter/http2_adapter.h
@@ -87,6 +87,10 @@
   // is the outstanding connection receive window.
   virtual int GetReceiveWindowSize() const = 0;
 
+  // Returns the size of the HPACK encoder's dynamic table, including the
+  // per-entry overhead from the specification.
+  virtual int GetHpackEncoderDynamicTableSize() 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 43d81cf..41c5ec1 100644
--- a/http2/adapter/nghttp2_adapter.cc
+++ b/http2/adapter/nghttp2_adapter.cc
@@ -125,6 +125,10 @@
   return nghttp2_session_get_local_window_size(session_->raw_ptr());
 }
 
+int NgHttp2Adapter::GetHpackEncoderDynamicTableSize() const {
+  return nghttp2_session_get_hd_deflate_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 6f8f703..d34a1ee 100644
--- a/http2/adapter/nghttp2_adapter.h
+++ b/http2/adapter/nghttp2_adapter.h
@@ -56,6 +56,8 @@
   int GetStreamReceiveWindowSize(Http2StreamId stream_id) const override;
   int GetReceiveWindowSize() const override;
 
+  int GetHpackEncoderDynamicTableSize() const override;
+
   Http2StreamId GetHighestReceivedStreamId() const override;
 
   void MarkDataConsumedForStream(Http2StreamId stream_id,
diff --git a/http2/adapter/nghttp2_adapter_test.cc b/http2/adapter/nghttp2_adapter_test.cc
index 0ff57af..40f3e74 100644
--- a/http2/adapter/nghttp2_adapter_test.cc
+++ b/http2/adapter/nghttp2_adapter_test.cc
@@ -270,6 +270,7 @@
   EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS}));
   visitor.Clear();
 
+  EXPECT_EQ(0, adapter->GetHpackEncoderDynamicTableSize());
   EXPECT_FALSE(adapter->session().want_write());
   const char* kSentinel = "";
   const absl::string_view kBody = "This is an example request body.";
@@ -290,6 +291,8 @@
   EXPECT_EQ(kInitialFlowControlWindowSize,
             adapter->GetStreamReceiveWindowLimit(stream_id));
 
+  EXPECT_GT(adapter->GetHpackEncoderDynamicTableSize(), 0);
+
   // Some data was sent, so the remaining send window size should be less than
   // the default.
   EXPECT_LT(adapter->GetStreamSendWindowSize(stream_id),
@@ -633,6 +636,8 @@
   EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS}));
   visitor.Clear();
 
+  EXPECT_EQ(0, adapter->GetHpackEncoderDynamicTableSize());
+
   EXPECT_FALSE(adapter->session().want_write());
   const absl::string_view kBody = "This is an example response body.";
   TestDataFrameSource body1(visitor, kBody, /*has_fin=*/false);
@@ -662,6 +667,8 @@
   EXPECT_GT(adapter->GetStreamSendWindowSize(1), 0);
   // Send window for a nonexistent stream is not available.
   EXPECT_EQ(adapter->GetStreamSendWindowSize(3), -1);
+
+  EXPECT_GT(adapter->GetHpackEncoderDynamicTableSize(), 0);
 }
 
 // Should also test: client attempts shutdown, server attempts shutdown after an
diff --git a/http2/adapter/oghttp2_adapter.cc b/http2/adapter/oghttp2_adapter.cc
index e5b89e5..023c433 100644
--- a/http2/adapter/oghttp2_adapter.cc
+++ b/http2/adapter/oghttp2_adapter.cc
@@ -103,6 +103,10 @@
   return session_->GetReceiveWindowSize();
 }
 
+int OgHttp2Adapter::GetHpackEncoderDynamicTableSize() const {
+  return session_->GetHpackEncoderDynamicTableSize();
+}
+
 Http2StreamId OgHttp2Adapter::GetHighestReceivedStreamId() const {
   return session_->GetHighestReceivedStreamId();
 }
diff --git a/http2/adapter/oghttp2_adapter.h b/http2/adapter/oghttp2_adapter.h
index c15f20e..81189e0 100644
--- a/http2/adapter/oghttp2_adapter.h
+++ b/http2/adapter/oghttp2_adapter.h
@@ -40,6 +40,7 @@
   int GetStreamReceiveWindowLimit(Http2StreamId stream_id) const override;
   int GetStreamReceiveWindowSize(Http2StreamId stream_id) const override;
   int GetReceiveWindowSize() const override;
+  int GetHpackEncoderDynamicTableSize() 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 e8b85fa..80455b0 100644
--- a/http2/adapter/oghttp2_session.cc
+++ b/http2/adapter/oghttp2_session.cc
@@ -94,6 +94,11 @@
   return connection_window_manager_.CurrentWindowSize();
 }
 
+int OgHttp2Session::GetHpackEncoderDynamicTableSize() const {
+  const spdy::HpackEncoder* encoder = framer_.GetHpackEncoder();
+  return encoder == nullptr ? 0 : encoder->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 68dca30..6a9ada7 100644
--- a/http2/adapter/oghttp2_session.h
+++ b/http2/adapter/oghttp2_session.h
@@ -71,6 +71,10 @@
   // Returns the outstanding connection receive window.
   int GetReceiveWindowSize() const;
 
+  // Returns the size of the HPACK encoder's dynamic table, including the
+  // per-entry overhead from the specification.
+  int GetHpackEncoderDynamicTableSize() 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 ae18323..e378a48 100644
--- a/http2/adapter/oghttp2_session_test.cc
+++ b/http2/adapter/oghttp2_session_test.cc
@@ -213,6 +213,8 @@
   EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
   visitor.Clear();
 
+  EXPECT_EQ(0, session.GetHpackEncoderDynamicTableSize());
+
   const char* kSentinel1 = "arbitrary pointer 1";
   TestDataFrameSource body1(visitor, "This is an example request body.");
   int stream_id =
@@ -238,11 +240,13 @@
   // Send window for a nonexistent stream is not available.
   EXPECT_EQ(-1, session.GetStreamSendWindowSize(stream_id + 2));
 
+  EXPECT_GT(session.GetHpackEncoderDynamicTableSize(), 0);
+
   stream_id =
       session.SubmitRequest(ToHeaders({{":method", "POST"},
                                        {":scheme", "http"},
                                        {":authority", "example.com"},
-                                       {":path", "/this/is/request/one"}}),
+                                       {":path", "/this/is/request/two"}}),
                             nullptr, nullptr);
   EXPECT_GT(stream_id, 0);
   EXPECT_TRUE(session.want_write());
@@ -541,6 +545,8 @@
 
   EXPECT_EQ(1, session.GetHighestReceivedStreamId());
 
+  EXPECT_EQ(0, session.GetHpackEncoderDynamicTableSize());
+
   // Server will want to send initial SETTINGS, and a SETTINGS ack.
   EXPECT_TRUE(session.want_write());
   session.Send();
@@ -574,6 +580,8 @@
   EXPECT_LT(session.GetStreamSendWindowSize(1), kInitialFlowControlWindowSize);
   // Send window for a nonexistent stream is not available.
   EXPECT_EQ(session.GetStreamSendWindowSize(3), -1);
+
+  EXPECT_GT(session.GetHpackEncoderDynamicTableSize(), 0);
 }
 
 TEST(OgHttp2SessionTest, ServerStartShutdown) {
diff --git a/spdy/core/spdy_framer.h b/spdy/core/spdy_framer.h
index c24c0a4..6f7a5dc 100644
--- a/spdy/core/spdy_framer.h
+++ b/spdy/core/spdy_framer.h
@@ -236,6 +236,10 @@
   // Get (and lazily initialize) the HPACK encoder state.
   HpackEncoder* GetHpackEncoder();
 
+  // Gets the HPACK encoder state. Returns nullptr if the encoder has not been
+  // initialized.
+  const HpackEncoder* GetHpackEncoder() const { return hpack_encoder_.get(); }
+
  protected:
   friend class test::SpdyFramerPeer;
   friend class test::SpdyFramerTest_MultipleContinuationFramesWithIterator_Test;