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;