Adds a method to the Http2Adapter API to fetch the flow control receive window upper bound for a given stream.

PiperOrigin-RevId: 378866810
diff --git a/http2/adapter/http2_adapter.h b/http2/adapter/http2_adapter.h
index e53918c..51edda3 100644
--- a/http2/adapter/http2_adapter.h
+++ b/http2/adapter/http2_adapter.h
@@ -72,6 +72,10 @@
   // Returns the connection-level flow control window advertised by the peer.
   virtual int GetSendWindowSize() const = 0;
 
+  // Returns the current upper bound on the flow control receive window for this
+  // stream. This value does not account for data received from the peer.
+  virtual int GetStreamReceiveWindowLimit(Http2StreamId stream_id) const = 0;
+
   // Returns the amount of data a peer could send on a given stream. This is
   // the outstanding stream receive window.
   virtual int GetStreamReceiveWindowSize(Http2StreamId stream_id) const = 0;
diff --git a/http2/adapter/nghttp2_adapter.cc b/http2/adapter/nghttp2_adapter.cc
index d4e3365..e932838 100644
--- a/http2/adapter/nghttp2_adapter.cc
+++ b/http2/adapter/nghttp2_adapter.cc
@@ -106,6 +106,11 @@
   return session_->GetRemoteWindowSize();
 }
 
+int NgHttp2Adapter::GetStreamReceiveWindowLimit(Http2StreamId stream_id) const {
+  return nghttp2_session_get_stream_effective_local_window_size(
+      session_->raw_ptr(), stream_id);
+}
+
 int NgHttp2Adapter::GetStreamReceiveWindowSize(Http2StreamId stream_id) const {
   return nghttp2_session_get_stream_local_window_size(session_->raw_ptr(),
                                                       stream_id);
diff --git a/http2/adapter/nghttp2_adapter.h b/http2/adapter/nghttp2_adapter.h
index 2fdf3ee..26b41e6 100644
--- a/http2/adapter/nghttp2_adapter.h
+++ b/http2/adapter/nghttp2_adapter.h
@@ -50,6 +50,7 @@
   void Send() override;
 
   int GetSendWindowSize() const override;
+  int GetStreamReceiveWindowLimit(Http2StreamId stream_id) const override;
   int GetStreamReceiveWindowSize(Http2StreamId stream_id) const override;
   int GetReceiveWindowSize() const override;
 
diff --git a/http2/adapter/nghttp2_adapter_test.cc b/http2/adapter/nghttp2_adapter_test.cc
index df5d186..59ec4ea 100644
--- a/http2/adapter/nghttp2_adapter_test.cc
+++ b/http2/adapter/nghttp2_adapter_test.cc
@@ -151,6 +151,10 @@
   EXPECT_EQ(kInitialFlowControlWindowSize,
             adapter->GetStreamReceiveWindowSize(stream_id3));
 
+  // Upper bound on the flow control receive window should be the initial value.
+  EXPECT_EQ(kInitialFlowControlWindowSize,
+            adapter->GetStreamReceiveWindowLimit(stream_id1));
+
   // Connection has not yet received any data.
   EXPECT_EQ(kInitialFlowControlWindowSize, adapter->GetReceiveWindowSize());
 
@@ -204,6 +208,11 @@
   EXPECT_EQ(adapter->GetReceiveWindowSize(),
             adapter->GetStreamReceiveWindowSize(stream_id1));
 
+  // Upper bound on the flow control receive window should still be the initial
+  // value.
+  EXPECT_EQ(kInitialFlowControlWindowSize,
+            adapter->GetStreamReceiveWindowLimit(stream_id1));
+
   // Should be 3, but this method only works for server adapters.
   EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
 
@@ -278,6 +287,8 @@
   EXPECT_EQ(kInitialFlowControlWindowSize,
             adapter->GetStreamReceiveWindowSize(stream_id));
   EXPECT_EQ(kInitialFlowControlWindowSize, adapter->GetReceiveWindowSize());
+  EXPECT_EQ(kInitialFlowControlWindowSize,
+            adapter->GetStreamReceiveWindowLimit(stream_id));
 
   EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::HEADERS,
                                             spdy::SpdyFrameType::DATA}));
@@ -522,6 +533,9 @@
             adapter->GetStreamReceiveWindowSize(1));
   EXPECT_EQ(adapter->GetStreamReceiveWindowSize(1),
             adapter->GetReceiveWindowSize());
+  // Upper bound should still be the original value.
+  EXPECT_EQ(kInitialFlowControlWindowSize,
+            adapter->GetStreamReceiveWindowLimit(1));
 
   // Because stream 3 has already been closed, it's not possible to set user
   // data.
diff --git a/http2/adapter/oghttp2_adapter.cc b/http2/adapter/oghttp2_adapter.cc
index 11aefb2..d507c0c 100644
--- a/http2/adapter/oghttp2_adapter.cc
+++ b/http2/adapter/oghttp2_adapter.cc
@@ -87,6 +87,10 @@
   return session_->GetRemoteWindowSize();
 }
 
+int OgHttp2Adapter::GetStreamReceiveWindowLimit(Http2StreamId stream_id) const {
+  return session_->GetStreamReceiveWindowLimit(stream_id);
+}
+
 int OgHttp2Adapter::GetStreamReceiveWindowSize(Http2StreamId stream_id) const {
   return session_->GetStreamReceiveWindowSize(stream_id);
 }
diff --git a/http2/adapter/oghttp2_adapter.h b/http2/adapter/oghttp2_adapter.h
index 477a6e0..7e9ee7b 100644
--- a/http2/adapter/oghttp2_adapter.h
+++ b/http2/adapter/oghttp2_adapter.h
@@ -36,6 +36,7 @@
   void SubmitMetadata(Http2StreamId stream_id, bool fin) override;
   void Send() override;
   int GetSendWindowSize() const override;
+  int GetStreamReceiveWindowLimit(Http2StreamId stream_id) const override;
   int GetStreamReceiveWindowSize(Http2StreamId stream_id) const override;
   int GetReceiveWindowSize() const override;
   Http2StreamId GetHighestReceivedStreamId() const override;
diff --git a/http2/adapter/oghttp2_session.cc b/http2/adapter/oghttp2_session.cc
index 853c374..27bca42 100644
--- a/http2/adapter/oghttp2_session.cc
+++ b/http2/adapter/oghttp2_session.cc
@@ -66,6 +66,14 @@
   return true;
 }
 
+int OgHttp2Session::GetStreamReceiveWindowLimit(Http2StreamId stream_id) const {
+  auto it = stream_map_.find(stream_id);
+  if (it != stream_map_.end()) {
+    return it->second.window_manager.WindowSizeLimit();
+  }
+  return -1;
+}
+
 int OgHttp2Session::GetStreamReceiveWindowSize(Http2StreamId stream_id) const {
   auto it = stream_map_.find(stream_id);
   if (it != stream_map_.end()) {
diff --git a/http2/adapter/oghttp2_session.h b/http2/adapter/oghttp2_session.h
index 9634400..f325f10 100644
--- a/http2/adapter/oghttp2_session.h
+++ b/http2/adapter/oghttp2_session.h
@@ -57,6 +57,10 @@
   // Resumes a stream that was previously blocked. Returns true on success.
   bool ResumeStream(Http2StreamId stream_id);
 
+  // Returns the current upper bound on the flow control receive window for this
+  // stream.
+  int GetStreamReceiveWindowLimit(Http2StreamId stream_id) const;
+
   // Returns the outstanding stream receive window, or -1 if the stream does not
   // exist.
   int GetStreamReceiveWindowSize(Http2StreamId stream_id) const;
diff --git a/http2/adapter/oghttp2_session_test.cc b/http2/adapter/oghttp2_session_test.cc
index cdaacdc..40f279d 100644
--- a/http2/adapter/oghttp2_session_test.cc
+++ b/http2/adapter/oghttp2_session_test.cc
@@ -122,6 +122,9 @@
   // Connection receive window is equivalent to the first stream's.
   EXPECT_EQ(session.GetReceiveWindowSize(),
             session.GetStreamReceiveWindowSize(stream_id));
+  // Receive window upper bound is still the initial value.
+  EXPECT_EQ(kInitialFlowControlWindowSize,
+            session.GetStreamReceiveWindowLimit(stream_id));
 }
 
 // Verifies that a client session enqueues initial SETTINGS if Send() is called
@@ -433,6 +436,9 @@
   // Connection receive window is equivalent to the first stream's.
   EXPECT_EQ(session.GetReceiveWindowSize(),
             session.GetStreamReceiveWindowSize(1));
+  // Receive window upper bound is still the initial value.
+  EXPECT_EQ(kInitialFlowControlWindowSize,
+            session.GetStreamReceiveWindowLimit(1));
 
   // TODO(birenroy): drop stream state when streams are closed. It should no
   // longer be possible to set user data.