IETF CONNECTION CLOSE code is varint encoded

In the recent (-22) version of the IETF QUIC Internet Draft, the
encoding of the close code in the Connection Close frames was changed
from uint16_t to varint62.

NOTE WELL, this just changes the serialization of the code. The error
code is stored as a uint16_t. A separate CL will change the base type
for the Transport Error Code and Application Error Code.

gfe-relnote: N/A is IETF QUIC/v99 code only.
PiperOrigin-RevId: 258377932
Change-Id: I0be6068b1a2194d4c45d464b393698389a73cb75
diff --git a/quic/core/frames/quic_connection_close_frame.h b/quic/core/frames/quic_connection_close_frame.h
index 8025fbe..aba67b9 100644
--- a/quic/core/frames/quic_connection_close_frame.h
+++ b/quic/core/frames/quic_connection_close_frame.h
@@ -51,13 +51,15 @@
   QuicConnectionCloseType close_type;
 
   // This is the error field in the frame.
-  // The CONNECTION_CLOSE frame reports a 16-bit error code:
+  // The CONNECTION_CLOSE frame reports an error code:
   // - The transport error code as reported in a CONNECTION_CLOSE/Transport
-  //   frame,
-  // - An opaque 16-bit code as reported in CONNECTION_CLOSE/Application frames,
-  // - A QuicErrorCode, which is used in Google QUIC.
+  //   frame (serialized as a VarInt),
+  // - An opaque 64-bit code as reported in CONNECTION_CLOSE/Application frames
+  //  (serialized as a VarInt),,
+  // - A 16 bit QuicErrorCode, which is used in Google QUIC.
   union {
     QuicIetfTransportErrorCodes transport_error_code;
+    // TODO(fkastenholz): Change this to uint64_t to reflect -22 of the ID.
     uint16_t application_error_code;
     QuicErrorCode quic_error_code;
   };
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc
index 6c089c1..5324206 100644
--- a/quic/core/quic_framer.cc
+++ b/quic/core/quic_framer.cc
@@ -578,10 +578,16 @@
   // extend the error string to include " QuicErrorCode: #"
   const size_t truncated_error_string_size =
       TruncatedErrorStringSize(frame.error_details);
+  uint64_t close_code = 0;
+  if (frame.close_type == IETF_QUIC_TRANSPORT_CONNECTION_CLOSE) {
+    close_code = static_cast<uint64_t>(frame.transport_error_code);
+  } else if (frame.close_type == IETF_QUIC_APPLICATION_CONNECTION_CLOSE) {
+    close_code = static_cast<uint64_t>(frame.application_error_code);
+  }
   const size_t frame_size =
       truncated_error_string_size +
       QuicDataWriter::GetVarInt62Len(truncated_error_string_size) +
-      kQuicFrameTypeSize + kQuicIetfQuicErrorCodeSize;
+      kQuicFrameTypeSize + QuicDataWriter::GetVarInt62Len(close_code);
   if (frame.close_type == IETF_QUIC_APPLICATION_CONNECTION_CLOSE) {
     return frame_size;
   }
@@ -5667,7 +5673,14 @@
     return false;
   }
 
-  if (!writer->WriteUInt16(frame.application_error_code)) {
+  uint64_t close_code = 0;
+  if (frame.close_type == IETF_QUIC_TRANSPORT_CONNECTION_CLOSE) {
+    close_code = static_cast<uint64_t>(frame.transport_error_code);
+  } else if (frame.close_type == IETF_QUIC_APPLICATION_CONNECTION_CLOSE) {
+    close_code = static_cast<uint64_t>(frame.application_error_code);
+  }
+
+  if (!writer->WriteVarInt62(close_code)) {
     set_detailed_error("Can not write connection close frame error code");
     return false;
   }
@@ -5698,13 +5711,30 @@
     QuicConnectionCloseType type,
     QuicConnectionCloseFrame* frame) {
   frame->close_type = type;
-  uint16_t code;
-  if (!reader->ReadUInt16(&code)) {
+  uint64_t error_code;
+  if (!reader->ReadVarInt62(&error_code)) {
     set_detailed_error("Unable to read connection close error code.");
     return false;
   }
-  frame->transport_error_code = static_cast<QuicIetfTransportErrorCodes>(code);
 
+  if (frame->close_type == IETF_QUIC_TRANSPORT_CONNECTION_CLOSE) {
+    if (error_code > 0xffff) {
+      frame->transport_error_code =
+          static_cast<QuicIetfTransportErrorCodes>(0xffff);
+      QUIC_DLOG(ERROR) << "Transport error code " << error_code << " > 0xffff";
+    } else {
+      frame->transport_error_code =
+          static_cast<QuicIetfTransportErrorCodes>(error_code);
+    }
+  } else if (frame->close_type == IETF_QUIC_APPLICATION_CONNECTION_CLOSE) {
+    if (error_code > 0xffff) {
+      frame->application_error_code = 0xffff;
+      QUIC_DLOG(ERROR) << "Application error code " << error_code
+                       << " > 0xffff";
+    } else {
+      frame->application_error_code = static_cast<uint16_t>(error_code);
+    }
+  }
   if (type == IETF_QUIC_TRANSPORT_CONNECTION_CLOSE) {
     // The frame-type of the frame causing the error is present only
     // if it's a CONNECTION_CLOSE/Transport.
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc
index 0009470..29ae36f 100644
--- a/quic/core/quic_framer_test.cc
+++ b/quic/core/quic_framer_test.cc
@@ -4676,7 +4676,7 @@
        {0x1c}},
       // error code
       {"Unable to read connection close error code.",
-       {0x00, 0x11}},
+       {kVarInt62TwoBytes + 0x00, 0x11}},
       {"Unable to read connection close frame type.",
        {kVarInt62TwoBytes + 0x12, 0x34 }},
       {"Unable to read connection close error details.",
@@ -4747,7 +4747,7 @@
        {0x1d}},
       // error code
       {"Unable to read connection close error code.",
-       {0x00, 0x11}},
+       {kVarInt62TwoBytes + 0x00, 0x11}},
       {"Unable to read connection close error details.",
        {
          // error details length
@@ -7927,7 +7927,7 @@
     // frame type (IETF_CONNECTION_CLOSE frame)
     0x1c,
     // error code
-    0x00, 0x11,
+    kVarInt62OneByte + 0x11,
     // Frame type within the CONNECTION_CLOSE frame
     kVarInt62OneByte + 0x05,
     // error details length
@@ -8138,7 +8138,7 @@
     // frame type (IETF_CONNECTION_CLOSE frame)
     0x1c,
     // error code
-    0x00, 0x0a,
+    kVarInt62OneByte + 0x0a,
     // Frame type within the CONNECTION_CLOSE frame
     kVarInt62OneByte + 0x00,
     // error details length
@@ -8212,7 +8212,8 @@
   header.packet_number = kPacketNumber;
 
   QuicConnectionCloseFrame app_close_frame;
-  app_close_frame.quic_error_code = static_cast<QuicErrorCode>(0x11);
+  app_close_frame.application_error_code =
+      static_cast<uint64_t>(QUIC_INVALID_STREAM_ID);
   app_close_frame.error_details = "because I can";
   app_close_frame.close_type = IETF_QUIC_APPLICATION_CONNECTION_CLOSE;
 
@@ -8231,7 +8232,7 @@
     // frame type (IETF_APPLICATION_CLOSE frame)
     0x1d,
     // error code
-    0x00, 0x11,
+    kVarInt62OneByte + 0x11,
     // error details length
     kVarInt62OneByte + 0x0d,
     // error details
@@ -8263,7 +8264,8 @@
   header.packet_number = kPacketNumber;
 
   QuicConnectionCloseFrame app_close_frame;
-  app_close_frame.quic_error_code = static_cast<QuicErrorCode>(0x11);
+  app_close_frame.application_error_code =
+      static_cast<uint64_t>(QUIC_INVALID_STREAM_ID);
   app_close_frame.error_details = std::string(2048, 'A');
   app_close_frame.close_type = IETF_QUIC_APPLICATION_CONNECTION_CLOSE;
 
@@ -8281,7 +8283,7 @@
     // frame type (IETF_APPLICATION_CLOSE frame)
     0x1d,
     // error code
-    0x00, 0x11,
+    kVarInt62OneByte + 0x11,
     // error details length
     kVarInt62TwoBytes + 0x01, 0x00,
     // error details (truncated to 256 bytes)
diff --git a/quic/core/quic_types.h b/quic/core/quic_types.h
index 97707b5..c3f70e7 100644
--- a/quic/core/quic_types.h
+++ b/quic/core/quic_types.h
@@ -504,6 +504,7 @@
 // A vector of lost packets.
 typedef std::vector<LostPacket> LostPacketVector;
 
+// TODO(fkastenholz): Change this to uint64_t to reflect -22 of the ID.
 enum QuicIetfTransportErrorCodes : uint16_t {
   NO_IETF_QUIC_ERROR = 0x0,
   INTERNAL_ERROR = 0x1,