Handle HTTP/3 SETTINGS on 0-RTT client connection.

In IETF QUIC, if 0-RTT is enabled, the client will receive 2 SETTINGS, one from cache and one from the fresh server sent SETTINGS.
If 0-RTT is accepted, the server shouldn't change dynamic table capacity according to https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#name-maximum-dynamic-table-capac. For other settings, https://www.google.com/url?sa=D&q=https%3A%2F%2Fquicwg.org%2Fbase-drafts%2Fdraft-ietf-quic-http.html%23name-initialization specifies they shouldn't be decreased.
When 0-RTT is rejected, our current approach is to retransmit 0-RTT packets. If the server changes SETTINGS, our implementation doesn't have an easy way to comply with the new SETTINGS, thus we close the connection too.

Protected by quic_enable_zero_rtt_for_tls

PiperOrigin-RevId: 316128955
Change-Id: I84b277b3c57d6a8009aec5a547c6416542122ec6
diff --git a/quic/core/qpack/qpack_encoder.cc b/quic/core/qpack/qpack_encoder.cc
index db7ec79..67adf12 100644
--- a/quic/core/qpack/qpack_encoder.cc
+++ b/quic/core/qpack/qpack_encoder.cc
@@ -378,9 +378,10 @@
   return SecondPassEncode(std::move(instructions), required_insert_count);
 }
 
-void QpackEncoder::SetMaximumDynamicTableCapacity(
+bool QpackEncoder::SetMaximumDynamicTableCapacity(
     uint64_t maximum_dynamic_table_capacity) {
-  header_table_.SetMaximumDynamicTableCapacity(maximum_dynamic_table_capacity);
+  return header_table_.SetMaximumDynamicTableCapacity(
+      maximum_dynamic_table_capacity);
 }
 
 void QpackEncoder::SetDynamicTableCapacity(uint64_t dynamic_table_capacity) {
@@ -392,8 +393,12 @@
   DCHECK(success);
 }
 
-void QpackEncoder::SetMaximumBlockedStreams(uint64_t maximum_blocked_streams) {
+bool QpackEncoder::SetMaximumBlockedStreams(uint64_t maximum_blocked_streams) {
+  if (maximum_blocked_streams < maximum_blocked_streams_) {
+    return false;
+  }
   maximum_blocked_streams_ = maximum_blocked_streams;
+  return true;
 }
 
 void QpackEncoder::OnInsertCountIncrement(uint64_t increment) {
diff --git a/quic/core/qpack/qpack_encoder.h b/quic/core/qpack/qpack_encoder.h
index 0f1d14c..8b75097 100644
--- a/quic/core/qpack/qpack_encoder.h
+++ b/quic/core/qpack/qpack_encoder.h
@@ -63,7 +63,10 @@
   // measured in bytes.  Called when SETTINGS_QPACK_MAX_TABLE_CAPACITY is
   // received.  Encoder needs to know this value so that it can calculate
   // MaxEntries, used as a modulus to encode Required Insert Count.
-  void SetMaximumDynamicTableCapacity(uint64_t maximum_dynamic_table_capacity);
+  // Returns true if |maximum_dynamic_table_capacity| is set for the first time
+  // or if it doesn't change current value. The setting is not changed when
+  // returning false.
+  bool SetMaximumDynamicTableCapacity(uint64_t maximum_dynamic_table_capacity);
 
   // Set dynamic table capacity to |dynamic_table_capacity|.
   // |dynamic_table_capacity| must not exceed maximum dynamic table capacity.
@@ -72,7 +75,9 @@
 
   // Set maximum number of blocked streams.
   // Called when SETTINGS_QPACK_BLOCKED_STREAMS is received.
-  void SetMaximumBlockedStreams(uint64_t maximum_blocked_streams);
+  // Returns true if |maximum_blocked_streams| doesn't decrease current value.
+  // The setting is not changed when returning false.
+  bool SetMaximumBlockedStreams(uint64_t maximum_blocked_streams);
 
   // QpackDecoderStreamReceiver::Delegate implementation
   void OnInsertCountIncrement(uint64_t increment) override;
diff --git a/quic/core/qpack/qpack_header_table.cc b/quic/core/qpack/qpack_header_table.cc
index 472db89..29e7148 100644
--- a/quic/core/qpack/qpack_header_table.cc
+++ b/quic/core/qpack/qpack_header_table.cc
@@ -186,16 +186,15 @@
   return true;
 }
 
-void QpackHeaderTable::SetMaximumDynamicTableCapacity(
+bool QpackHeaderTable::SetMaximumDynamicTableCapacity(
     uint64_t maximum_dynamic_table_capacity) {
-  // This method can only be called once: in the decoding context, shortly after
-  // construction; in the encoding context, upon receiving the SETTINGS frame.
-  DCHECK_EQ(0u, dynamic_table_capacity_);
-  DCHECK_EQ(0u, maximum_dynamic_table_capacity_);
-  DCHECK_EQ(0u, max_entries_);
-
-  maximum_dynamic_table_capacity_ = maximum_dynamic_table_capacity;
-  max_entries_ = maximum_dynamic_table_capacity / 32;
+  if (maximum_dynamic_table_capacity_ == 0) {
+    maximum_dynamic_table_capacity_ = maximum_dynamic_table_capacity;
+    max_entries_ = maximum_dynamic_table_capacity / 32;
+    return true;
+  }
+  // If the value is already set, it should not be changed.
+  return maximum_dynamic_table_capacity == maximum_dynamic_table_capacity_;
 }
 
 void QpackHeaderTable::RegisterObserver(uint64_t required_insert_count,
diff --git a/quic/core/qpack/qpack_header_table.h b/quic/core/qpack/qpack_header_table.h
index e3fb975..bed1cc8 100644
--- a/quic/core/qpack/qpack_header_table.h
+++ b/quic/core/qpack/qpack_header_table.h
@@ -97,7 +97,10 @@
   // value can be set upon connection establishment, whereas in the encoding
   // context it can be set when the SETTINGS frame is received.
   // This method must only be called at most once.
-  void SetMaximumDynamicTableCapacity(uint64_t maximum_dynamic_table_capacity);
+  // Returns true if |maximum_dynamic_table_capacity| is set for the first time
+  // or if it doesn't change current value. The setting is not changed when
+  // returning false.
+  bool SetMaximumDynamicTableCapacity(uint64_t maximum_dynamic_table_capacity);
 
   // Get |maximum_dynamic_table_capacity_|.
   uint64_t maximum_dynamic_table_capacity() const {