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,