Grease HTTP/3 settings.

gfe-relnote: protected by disabled v99 flag.
PiperOrigin-RevId: 292233030
Change-Id: Iff6ae3490d5c10827b44159f7d8811bfb23deeef
diff --git a/quic/core/http/quic_send_control_stream.cc b/quic/core/http/quic_send_control_stream.cc
index eda0729..f7adc70 100644
--- a/quic/core/http/quic_send_control_stream.cc
+++ b/quic/core/http/quic_send_control_stream.cc
@@ -3,8 +3,10 @@
 // found in the LICENSE file.
 
 #include "net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h"
+#include <cstdint>
 #include <memory>
 
+#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
 #include "net/third_party/quiche/src/quic/core/http/http_constants.h"
 #include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h"
 #include "net/third_party/quiche/src/quic/core/quic_session.h"
@@ -57,6 +59,18 @@
       qpack_maximum_blocked_streams_;
   settings.values[SETTINGS_MAX_HEADER_LIST_SIZE] =
       max_inbound_header_list_size_;
+  // https://tools.ietf.org/html/draft-ietf-quic-http-25#section-7.2.4.1
+  // specifies that setting identifiers of 0x1f * N + 0x21 are reserved and
+  // greasing should be attempted.
+  if (GetQuicFlag(FLAGS_quic_disable_http3_settings_grease_randomness)) {
+    settings.values[0x40] = 20;
+  } else {
+    uint32_t result;
+    QuicRandom::GetInstance()->RandBytes(&result, sizeof(result));
+    uint64_t setting_id = 0x1fULL * static_cast<uint64_t>(result) + 0x21ULL;
+    QuicRandom::GetInstance()->RandBytes(&result, sizeof(result));
+    settings.values[setting_id] = result;
+  }
 
   std::unique_ptr<char[]> buffer;
   QuicByteCount frame_length =
diff --git a/quic/core/http/quic_send_control_stream_test.cc b/quic/core/http/quic_send_control_stream_test.cc
index 7a03ac3..507ccdc 100644
--- a/quic/core/http/quic_send_control_stream_test.cc
+++ b/quic/core/http/quic_send_control_stream_test.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
@@ -102,6 +103,7 @@
                          ::testing::PrintToStringParamName());
 
 TEST_P(QuicSendControlStreamTest, WriteSettings) {
+  SetQuicFlag(FLAGS_quic_disable_http3_settings_grease_randomness, true);
   session_.set_qpack_maximum_dynamic_table_capacity(255);
   session_.set_qpack_maximum_blocked_streams(16);
   session_.set_max_inbound_header_list_size(1024);
@@ -112,13 +114,15 @@
   std::string expected_write_data = quiche::QuicheTextUtils::HexDecode(
       "00"    // stream type: control stream
       "04"    // frame type: SETTINGS frame
-      "08"    // frame length
+      "0b"    // frame length
       "01"    // SETTINGS_QPACK_MAX_TABLE_CAPACITY
       "40ff"  // 255
       "06"    // SETTINGS_MAX_HEADER_LIST_SIZE
       "4400"  // 1024
       "07"    // SETTINGS_QPACK_BLOCKED_STREAMS
-      "10");  // 16
+      "10"    // 16
+      "4040"  // 0x40 as the reserved settings id
+      "14");  // 20
 
   auto buffer = std::make_unique<char[]>(expected_write_data.size());
   QuicDataWriter writer(expected_write_data.size(), buffer.get());