Change Settings frame's setting id from 2 byte integer to variable length
integer.

gfe-relnote: n/a --under version 99, which is not turned on.
PiperOrigin-RevId: 244771758
Change-Id: I0e1b329ff0696255f5ca0c10087bf39090b81e76
diff --git a/quic/core/http/http_decoder.cc b/quic/core/http/http_decoder.cc
index eff9efc..e0c7383 100644
--- a/quic/core/http/http_decoder.cc
+++ b/quic/core/http/http_decoder.cc
@@ -308,10 +308,6 @@
       break;
     }
     case 0x4: {  // SETTINGS
-      // TODO(rch): Handle overly large SETTINGS frames. Either:
-      // 1. Impose a limit on SETTINGS frame size, and close the connection if
-      //    exceeded
-      // 2. Implement a streaming parsing mode.
       SettingsFrame frame;
       QuicDataReader reader(buffer_.data(), current_frame_length_);
       if (!ParseSettingsFrame(&reader, &frame)) {
@@ -480,8 +476,8 @@
 bool HttpDecoder::ParseSettingsFrame(QuicDataReader* reader,
                                      SettingsFrame* frame) {
   while (!reader->IsDoneReading()) {
-    uint16_t id;
-    if (!reader->ReadUInt16(&id)) {
+    uint64_t id;
+    if (!reader->ReadVarInt62(&id)) {
       RaiseError(QUIC_INTERNAL_ERROR,
                  "Unable to read settings frame identifier");
       return false;
diff --git a/quic/core/http/http_decoder_test.cc b/quic/core/http/http_decoder_test.cc
index 614e4f9..a4903b5 100644
--- a/quic/core/http/http_decoder_test.cc
+++ b/quic/core/http/http_decoder_test.cc
@@ -304,26 +304,29 @@
       // type (SETTINGS)
       0x04,
       // length
-      0x06,
+      0x07,
       // identifier (SETTINGS_NUM_PLACEHOLDERS)
-      0x00,
       0x03,
       // content
       0x02,
       // identifier (SETTINGS_MAX_HEADER_LIST_SIZE)
-      0x00,
       0x06,
       // content
       0x05,
-  };
+      // identifier (256 in variable length integer)
+      0x40 + 0x01,
+      0x00,
+      // content
+      0x04};
   // clang-format on
 
   SettingsFrame frame;
   frame.values[3] = 2;
   frame.values[6] = 5;
+  frame.values[256] = 4;
 
   // Process the full frame.
-  EXPECT_CALL(visitor_, OnSettingsFrameStart(Http3FrameLengths(2, 6)));
+  EXPECT_CALL(visitor_, OnSettingsFrameStart(Http3FrameLengths(2, 7)));
   EXPECT_CALL(visitor_, OnSettingsFrame(frame));
   EXPECT_EQ(QUIC_ARRAYSIZE(input),
             decoder_.ProcessInput(input, QUIC_ARRAYSIZE(input)));
@@ -331,7 +334,7 @@
   EXPECT_EQ("", decoder_.error_detail());
 
   // Process the frame incremently.
-  EXPECT_CALL(visitor_, OnSettingsFrameStart(Http3FrameLengths(2, 6)));
+  EXPECT_CALL(visitor_, OnSettingsFrameStart(Http3FrameLengths(2, 7)));
   EXPECT_CALL(visitor_, OnSettingsFrame(frame));
   for (char c : input) {
     EXPECT_EQ(1u, decoder_.ProcessInput(&c, 1));
diff --git a/quic/core/http/http_encoder.cc b/quic/core/http/http_encoder.cc
index 9de1571..01f9c10 100644
--- a/quic/core/http/http_encoder.cc
+++ b/quic/core/http/http_encoder.cc
@@ -48,8 +48,6 @@
 static const size_t kPriorityWeightLength = 1;
 // Length of a priority frame's first byte.
 static const size_t kPriorityFirstByteLength = 1;
-// Length of a key in the map of a settings frame.
-static const size_t kSettingsMapKeyLength = 2;
 
 }  // namespace
 
@@ -71,6 +69,8 @@
   if (WriteFrameHeader(payload_length, HttpFrameType::DATA, &writer)) {
     return header_length;
   }
+  QUIC_DLOG(ERROR)
+      << "Http encoder failed when attempting to serialize data frame header.";
   return 0;
 }
 
@@ -89,6 +89,9 @@
   if (WriteFrameHeader(payload_length, HttpFrameType::HEADERS, &writer)) {
     return header_length;
   }
+  QUIC_DLOG(ERROR)
+      << "Http encoder failed when attempting to serialize headers "
+         "frame header.";
   return 0;
 }
 
@@ -107,6 +110,8 @@
   QuicDataWriter writer(total_length, output->get());
 
   if (!WriteFrameHeader(payload_length, HttpFrameType::PRIORITY, &writer)) {
+    QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
+                        "priority frame header.";
     return 0;
   }
 
@@ -124,6 +129,8 @@
       writer.WriteUInt8(priority.weight)) {
     return total_length;
   }
+  QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
+                      "priority frame payload.";
   return 0;
 }
 
@@ -142,16 +149,18 @@
       writer.WriteVarInt62(cancel_push.push_id)) {
     return total_length;
   }
+  QUIC_DLOG(ERROR)
+      << "Http encoder failed when attempting to serialize cancel push frame.";
   return 0;
 }
 
 QuicByteCount HttpEncoder::SerializeSettingsFrame(
     const SettingsFrame& settings,
     std::unique_ptr<char[]>* output) {
-  // Calculate the key sizes.
-  QuicByteCount payload_length = settings.values.size() * kSettingsMapKeyLength;
-  // Calculate the value sizes.
+  QuicByteCount payload_length = 0;
+  // Calculate the payload length.
   for (auto it = settings.values.begin(); it != settings.values.end(); ++it) {
+    payload_length += QuicDataWriter::GetVarInt62Len(it->first);
     payload_length += QuicDataWriter::GetVarInt62Len(it->second);
   }
 
@@ -162,11 +171,15 @@
   QuicDataWriter writer(total_length, output->get());
 
   if (!WriteFrameHeader(payload_length, HttpFrameType::SETTINGS, &writer)) {
+    QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
+                        "settings frame header.";
     return 0;
   }
 
   for (auto it = settings.values.begin(); it != settings.values.end(); ++it) {
-    if (!writer.WriteUInt16(it->first) || !writer.WriteVarInt62(it->second)) {
+    if (!writer.WriteVarInt62(it->first) || !writer.WriteVarInt62(it->second)) {
+      QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
+                          "settings frame payload.";
       return 0;
     }
   }
@@ -194,6 +207,8 @@
       writer.WriteVarInt62(push_promise.push_id)) {
     return total_length;
   }
+  QUIC_DLOG(ERROR)
+      << "Http encoder failed when attempting to serialize push promise frame.";
   return 0;
 }
 
@@ -212,6 +227,8 @@
       writer.WriteVarInt62(goaway.stream_id)) {
     return total_length;
   }
+  QUIC_DLOG(ERROR)
+      << "Http encoder failed when attempting to serialize goaway frame.";
   return 0;
 }
 
@@ -230,6 +247,8 @@
       writer.WriteVarInt62(max_push_id.push_id)) {
     return total_length;
   }
+  QUIC_DLOG(ERROR)
+      << "Http encoder failed when attempting to serialize max push id frame.";
   return 0;
 }
 
@@ -249,6 +268,8 @@
       writer.WriteVarInt62(duplicate_push.push_id)) {
     return total_length;
   }
+  QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
+                      "duplicate push frame.";
   return 0;
 }
 
diff --git a/quic/core/http/http_encoder_test.cc b/quic/core/http/http_encoder_test.cc
index 9088fb5..1ff5d89 100644
--- a/quic/core/http/http_encoder_test.cc
+++ b/quic/core/http/http_encoder_test.cc
@@ -92,22 +92,23 @@
   SettingsFrame settings;
   settings.values[3] = 2;
   settings.values[6] = 5;
-  char output[] = {
-      // type (SETTINGS)
-      0x04,
-      // length
-      0x06,
-      // identifier (SETTINGS_NUM_PLACEHOLDERS)
-      0x00,
-      0x03,
-      // content
-      0x02,
-      // identifier (SETTINGS_MAX_HEADER_LIST_SIZE)
-      0x00,
-      0x06,
-      // content
-      0x05,
-  };
+  settings.values[256] = 4;
+  char output[] = {// type (SETTINGS)
+                   0x04,
+                   // length
+                   0x07,
+                   // identifier (SETTINGS_NUM_PLACEHOLDERS)
+                   0x03,
+                   // content
+                   0x02,
+                   // identifier (SETTINGS_MAX_HEADER_LIST_SIZE)
+                   0x06,
+                   // content
+                   0x05,
+                   // identifier (256 in variable length integer)
+                   0x40 + 0x01, 0x00,
+                   // content
+                   0x04};
   std::unique_ptr<char[]> buffer;
   uint64_t length = encoder_.SerializeSettingsFrame(settings, &buffer);
   EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
diff --git a/quic/core/http/http_frames.h b/quic/core/http/http_frames.h
index ea11557..f1aa7ff 100644
--- a/quic/core/http/http_frames.h
+++ b/quic/core/http/http_frames.h
@@ -90,8 +90,7 @@
 //   affect how endpoints communicate, such as preferences and constraints
 //   on peer behavior
 
-using SettingsId = uint16_t;
-using SettingsMap = std::map<SettingsId, uint64_t>;
+using SettingsMap = std::map<uint64_t, uint64_t>;
 
 struct SettingsFrame {
   SettingsMap values;