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: Ie1e628a3f0da3916e8000d472d08178e5a4cc0d4
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,