Add QpackEncoder::SetMaximumDynamicTableCapacity() and SetMaximumBlockedStreams() and call them when corresponding settings are received.

gfe-relnote: n/a, change to QUIC v99-only code.  Protected by existing disabled gfe2_reloadable_flag_quic_enable_version_99.
PiperOrigin-RevId: 261579634
Change-Id: Ice97e1d26210c622fbbf6c6894901ed6b44c01ca
diff --git a/quic/core/http/quic_spdy_session.cc b/quic/core/http/quic_spdy_session.cc
index 3c00c2b..2a83d24 100644
--- a/quic/core/http/quic_spdy_session.cc
+++ b/quic/core/http/quic_spdy_session.cc
@@ -647,7 +647,7 @@
         QUIC_DVLOG(1)
             << "SETTINGS_QPACK_MAX_TABLE_CAPACITY received with value "
             << value;
-        // TODO(b/112770235): implement.
+        qpack_encoder_->SetMaximumDynamicTableCapacity(value);
         break;
       case SETTINGS_MAX_HEADER_LIST_SIZE:
         QUIC_DVLOG(1) << "SETTINGS_MAX_HEADER_LIST_SIZE received with value "
@@ -657,7 +657,7 @@
       case SETTINGS_QPACK_BLOCKED_STREAMS:
         QUIC_DVLOG(1) << "SETTINGS_QPACK_BLOCKED_STREAMS received with value "
                       << value;
-        // TODO(b/112770235): implement.
+        qpack_encoder_->SetMaximumBlockedStreams(value);
         break;
       case SETTINGS_NUM_PLACEHOLDERS:
         QUIC_DVLOG(1) << "SETTINGS_NUM_PLACEHOLDERS received with value "
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc
index a2b4846..6a0b96e 100644
--- a/quic/core/http/quic_spdy_session_test.cc
+++ b/quic/core/http/quic_spdy_session_test.cc
@@ -25,6 +25,8 @@
 #include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack_encoder_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack_header_table_peer.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_flow_controller_peer.h"
@@ -2119,7 +2121,7 @@
   if (!VersionHasStreamType(transport_version())) {
     return;
   }
-  // Use a arbitrary stream id.
+  // Use an arbitrary stream id.
   QuicStreamId stream_id =
       GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3);
   char type[] = {kControlStream};
@@ -2130,14 +2132,27 @@
             QuicSpdySessionPeer::GetReceiveControlStream(&session_)->id());
 
   SettingsFrame settings;
-  settings.values[3] = 2;
+  settings.values[SETTINGS_QPACK_MAX_TABLE_CAPACITY] = 512;
   settings.values[SETTINGS_MAX_HEADER_LIST_SIZE] = 5;
+  settings.values[SETTINGS_QPACK_BLOCKED_STREAMS] = 42;
   std::string data = EncodeSettings(settings);
   QuicStreamFrame frame(stream_id, false, 1, QuicStringPiece(data));
 
+  QpackEncoder* qpack_encoder = session_.qpack_encoder();
+  QpackHeaderTable* header_table =
+      QpackEncoderPeer::header_table(qpack_encoder);
+
+  EXPECT_NE(512u,
+            QpackHeaderTablePeer::maximum_dynamic_table_capacity(header_table));
   EXPECT_NE(5u, session_.max_outbound_header_list_size());
+  EXPECT_NE(42u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
+
   session_.OnStreamFrame(frame);
+
+  EXPECT_EQ(512u,
+            QpackHeaderTablePeer::maximum_dynamic_table_capacity(header_table));
   EXPECT_EQ(5u, session_.max_outbound_header_list_size());
+  EXPECT_EQ(42u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
 }
 
 TEST_P(QuicSpdySessionTestServer, ReceiveControlStreamOutOfOrderDelivery) {
diff --git a/quic/core/qpack/qpack_encoder.cc b/quic/core/qpack/qpack_encoder.cc
index 4759e42..1daa572 100644
--- a/quic/core/qpack/qpack_encoder.cc
+++ b/quic/core/qpack/qpack_encoder.cc
@@ -20,7 +20,8 @@
     QpackStreamSenderDelegate* encoder_stream_sender_delegate)
     : decoder_stream_error_delegate_(decoder_stream_error_delegate),
       decoder_stream_receiver_(this),
-      encoder_stream_sender_(encoder_stream_sender_delegate) {
+      encoder_stream_sender_(encoder_stream_sender_delegate),
+      maximum_blocked_streams_(0) {
   DCHECK(decoder_stream_error_delegate_);
   DCHECK(encoder_stream_sender_delegate);
 }
@@ -103,6 +104,15 @@
   decoder_stream_receiver_.Decode(data);
 }
 
+void QpackEncoder::SetMaximumDynamicTableCapacity(
+    uint64_t maximum_dynamic_table_capacity) {
+  header_table_.SetMaximumDynamicTableCapacity(maximum_dynamic_table_capacity);
+}
+
+void QpackEncoder::SetMaximumBlockedStreams(uint64_t maximum_blocked_streams) {
+  maximum_blocked_streams_ = maximum_blocked_streams;
+}
+
 void QpackEncoder::OnInsertCountIncrement(uint64_t /*increment*/) {
   // TODO(bnc): Implement dynamic table management for encoding.
 }
diff --git a/quic/core/qpack/qpack_encoder.h b/quic/core/qpack/qpack_encoder.h
index 39600e8..e0bd8d4 100644
--- a/quic/core/qpack/qpack_encoder.h
+++ b/quic/core/qpack/qpack_encoder.h
@@ -20,10 +20,16 @@
 
 class SpdyHeaderBlock;
 
-}
+}  // namespace spdy
 
 namespace quic {
 
+namespace test {
+
+class QpackEncoderPeer;
+
+}  // namespace test
+
 // QPACK encoder class.  Exactly one instance should exist per QUIC connection.
 class QUIC_EXPORT_PRIVATE QpackEncoder
     : public QpackDecoderStreamReceiver::Delegate {
@@ -49,6 +55,14 @@
   // Decode data received on the decoder stream.
   void DecodeDecoderStreamData(QuicStringPiece data);
 
+  // Set maximum capacity of dynamic table, measured in bytes.
+  // Called when SETTINGS_QPACK_MAX_TABLE_CAPACITY is received.
+  void SetMaximumDynamicTableCapacity(uint64_t maximum_dynamic_table_capacity);
+
+  // Set maximum number of blocked streams.
+  // Called when SETTINGS_QPACK_BLOCKED_STREAMS is received.
+  void SetMaximumBlockedStreams(uint64_t maximum_blocked_streams);
+
   // QpackDecoderStreamReceiver::Delegate implementation
   void OnInsertCountIncrement(uint64_t increment) override;
   void OnHeaderAcknowledgement(QuicStreamId stream_id) override;
@@ -56,6 +70,8 @@
   void OnErrorDetected(QuicStringPiece error_message) override;
 
  private:
+  friend class test::QpackEncoderPeer;
+
   // TODO(bnc): Consider moving this class to QpackInstructionEncoder or
   // qpack_constants, adding factory methods, one for each instruction, and
   // changing QpackInstructionEncoder::Encoder() to take an
@@ -71,6 +87,7 @@
   QpackDecoderStreamReceiver decoder_stream_receiver_;
   QpackEncoderStreamSender encoder_stream_sender_;
   QpackHeaderTable header_table_;
+  uint64_t maximum_blocked_streams_;
 };
 
 }  // namespace quic
diff --git a/quic/core/qpack/qpack_header_table.h b/quic/core/qpack/qpack_header_table.h
index 4e3b77c..f251894 100644
--- a/quic/core/qpack/qpack_header_table.h
+++ b/quic/core/qpack/qpack_header_table.h
@@ -17,6 +17,12 @@
 
 namespace quic {
 
+namespace test {
+
+class QpackHeaderTablePeer;
+
+}  // namespace test
+
 using QpackEntry = spdy::HpackEntry;
 
 // This class manages the QPACK static and dynamic tables.  For dynamic entries,
@@ -114,6 +120,8 @@
   uint64_t draining_index(float draining_fraction) const;
 
  private:
+  friend class test::QpackHeaderTablePeer;
+
   // Evict entries from the dynamic table until table size is less than or equal
   // to current value of |dynamic_table_capacity_|.
   void EvictDownToCurrentCapacity();
diff --git a/quic/test_tools/qpack_encoder_peer.cc b/quic/test_tools/qpack_encoder_peer.cc
new file mode 100644
index 0000000..4e4bb52
--- /dev/null
+++ b/quic/test_tools/qpack_encoder_peer.cc
@@ -0,0 +1,24 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/test_tools/qpack_encoder_peer.h"
+
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h"
+
+namespace quic {
+namespace test {
+
+// static
+QpackHeaderTable* QpackEncoderPeer::header_table(QpackEncoder* encoder) {
+  return &encoder->header_table_;
+}
+
+// static
+uint64_t QpackEncoderPeer::maximum_blocked_streams(
+    const QpackEncoder* encoder) {
+  return encoder->maximum_blocked_streams_;
+}
+
+}  // namespace test
+}  // namespace quic
diff --git a/quic/test_tools/qpack_encoder_peer.h b/quic/test_tools/qpack_encoder_peer.h
new file mode 100644
index 0000000..b8a8cc7
--- /dev/null
+++ b/quic/test_tools/qpack_encoder_peer.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_TEST_TOOLS_QPACK_ENCODER_PEER_H_
+#define QUICHE_QUIC_TEST_TOOLS_QPACK_ENCODER_PEER_H_
+
+#include <cstdint>
+
+namespace quic {
+
+class QpackEncoder;
+class QpackHeaderTable;
+
+namespace test {
+
+class QpackEncoderPeer {
+ public:
+  QpackEncoderPeer() = delete;
+
+  static QpackHeaderTable* header_table(QpackEncoder* encoder);
+  static uint64_t maximum_blocked_streams(const QpackEncoder* encoder);
+};
+
+}  // namespace test
+
+}  // namespace quic
+
+#endif  // QUICHE_QUIC_TEST_TOOLS_QPACK_ENCODER_PEER_H_
diff --git a/quic/test_tools/qpack_header_table_peer.cc b/quic/test_tools/qpack_header_table_peer.cc
new file mode 100644
index 0000000..37c2961
--- /dev/null
+++ b/quic/test_tools/qpack_header_table_peer.cc
@@ -0,0 +1,19 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/test_tools/qpack_header_table_peer.h"
+
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h"
+
+namespace quic {
+namespace test {
+
+// static
+uint64_t QpackHeaderTablePeer::maximum_dynamic_table_capacity(
+    const QpackHeaderTable* header_table) {
+  return header_table->maximum_dynamic_table_capacity_;
+}
+
+}  // namespace test
+}  // namespace quic
diff --git a/quic/test_tools/qpack_header_table_peer.h b/quic/test_tools/qpack_header_table_peer.h
new file mode 100644
index 0000000..a73859c
--- /dev/null
+++ b/quic/test_tools/qpack_header_table_peer.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_TEST_TOOLS_QPACK_HEADER_TABLE_PEER_H_
+#define QUICHE_QUIC_TEST_TOOLS_QPACK_HEADER_TABLE_PEER_H_
+
+#include <cstdint>
+
+namespace quic {
+
+class QpackHeaderTable;
+
+namespace test {
+
+class QpackHeaderTablePeer {
+ public:
+  QpackHeaderTablePeer() = delete;
+
+  static uint64_t maximum_dynamic_table_capacity(
+      const QpackHeaderTable* header_table);
+};
+
+}  // namespace test
+
+}  // namespace quic
+
+#endif  // QUICHE_QUIC_TEST_TOOLS_QPACK_HEADER_TABLE_PEER_H_