gfe-relnote: In QUIC, do not use framer object in QuicDispatcher. Protected by gfe2_restart_flag_quic_no_framer_object_in_dispatcher.
Also, dispatcher does not parse and validate packet number anymore.
PiperOrigin-RevId: 247959538
Change-Id: Ia0f7901428537f392b05ffd6beb2984bffd00232
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc
index 243529d..8d0dec2 100644
--- a/quic/core/quic_framer.cc
+++ b/quic/core/quic_framer.cc
@@ -449,6 +449,11 @@
"each time such a packet is dropped");
}
+PacketHeaderFormat GetIetfPacketHeaderFormat(uint8_t type_byte) {
+ return type_byte & FLAGS_LONG_HEADER ? IETF_QUIC_LONG_HEADER_PACKET
+ : IETF_QUIC_SHORT_HEADER_PACKET;
+}
+
} // namespace
QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions,
@@ -2511,8 +2516,7 @@
}
header->type_byte = type;
// Determine whether this is a long or short header.
- header->form = type & FLAGS_LONG_HEADER ? IETF_QUIC_LONG_HEADER_PACKET
- : IETF_QUIC_SHORT_HEADER_PACKET;
+ header->form = GetIetfPacketHeaderFormat(type);
if (header->form == IETF_QUIC_LONG_HEADER_PACKET) {
// Version is always present in long headers.
header->version_flag = true;
@@ -2610,13 +2614,19 @@
}
// static
-bool QuicFramer::ValidateIetfConnectionIdLength(
- uint8_t connection_id_lengths_byte,
+bool QuicFramer::ProcessAndValidateIetfConnectionIdLength(
+ QuicDataReader* reader,
ParsedQuicVersion version,
bool should_update_expected_connection_id_length,
uint8_t* expected_connection_id_length,
uint8_t* destination_connection_id_length,
- uint8_t* source_connection_id_length) {
+ uint8_t* source_connection_id_length,
+ std::string* detailed_error) {
+ uint8_t connection_id_lengths_byte;
+ if (!reader->ReadBytes(&connection_id_lengths_byte, 1)) {
+ *detailed_error = "Unable to read ConnectionId length.";
+ return false;
+ }
uint8_t dcil =
(connection_id_lengths_byte & kDestinationConnectionIdLengthMask) >> 4;
if (dcil != 0) {
@@ -2642,6 +2652,7 @@
// OnProtocolVersionMismatch call is moved to before this is run.
QUIC_DVLOG(1) << "dcil: " << static_cast<uint32_t>(dcil)
<< ", scil: " << static_cast<uint32_t>(scil);
+ *detailed_error = "Invalid ConnectionId length.";
return false;
}
*destination_connection_id_length = dcil;
@@ -2664,18 +2675,11 @@
? expected_connection_id_length_
: 0;
if (header->form == IETF_QUIC_LONG_HEADER_PACKET) {
- // Read and validate connection ID length.
- uint8_t connection_id_lengths_byte;
- if (!reader->ReadBytes(&connection_id_lengths_byte, 1)) {
- set_detailed_error("Unable to read ConnectionId length.");
- return false;
- }
- if (!ValidateIetfConnectionIdLength(
- connection_id_lengths_byte, header->version,
+ if (!ProcessAndValidateIetfConnectionIdLength(
+ reader, header->version,
should_update_expected_connection_id_length_,
&expected_connection_id_length_, &destination_connection_id_length,
- &source_connection_id_length)) {
- set_detailed_error("Invalid ConnectionId length.");
+ &source_connection_id_length, &detailed_error_)) {
return false;
}
}
@@ -6054,5 +6058,75 @@
supports_multiple_packet_number_spaces_ = true;
}
+// static
+QuicErrorCode QuicFramer::ProcessPacketDispatcher(
+ const QuicEncryptedPacket& packet,
+ uint8_t expected_connection_id_length,
+ PacketHeaderFormat* format,
+ bool* version_flag,
+ QuicVersionLabel* version_label,
+ uint8_t* destination_connection_id_length,
+ QuicConnectionId* destination_connection_id,
+ std::string* detailed_error) {
+ QuicDataReader reader(packet.data(), packet.length());
+
+ uint8_t first_byte;
+ if (!reader.ReadBytes(&first_byte, 1)) {
+ *detailed_error = "Unable to read first byte.";
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ if (!QuicUtils::IsIetfPacketHeader(first_byte)) {
+ *format = GOOGLE_QUIC_PACKET;
+ *version_flag = (first_byte & PACKET_PUBLIC_FLAGS_VERSION) != 0;
+ *destination_connection_id_length =
+ first_byte & PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID;
+ if (*destination_connection_id_length == 0 ||
+ !reader.ReadConnectionId(destination_connection_id,
+ *destination_connection_id_length)) {
+ *detailed_error = "Unable to read ConnectionId.";
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ if (*version_flag && !ProcessVersionLabel(&reader, version_label)) {
+ *detailed_error = "Unable to read protocol version.";
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ return QUIC_NO_ERROR;
+ }
+
+ *format = GetIetfPacketHeaderFormat(first_byte);
+ QUIC_DVLOG(1) << "Dispatcher: Processing IETF QUIC packet, format: "
+ << *format;
+ *version_flag = *format == IETF_QUIC_LONG_HEADER_PACKET;
+ if (*format == IETF_QUIC_LONG_HEADER_PACKET) {
+ if (!ProcessVersionLabel(&reader, version_label)) {
+ *detailed_error = "Unable to read protocol version.";
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ // Set should_update_expected_connection_id_length to true to bypass
+ // connection ID lengths validation.
+ uint8_t unused_source_connection_id_length = 0;
+ uint8_t unused_expected_connection_id_length = 0;
+ if (!ProcessAndValidateIetfConnectionIdLength(
+ &reader, ParseQuicVersionLabel(*version_label),
+ /*should_update_expected_connection_id_length=*/true,
+ &unused_expected_connection_id_length,
+ destination_connection_id_length,
+ &unused_source_connection_id_length, detailed_error)) {
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ } else {
+ // For short header packets, expected_connection_id_length is used to
+ // determine the destination_connection_id_length.
+ *destination_connection_id_length = expected_connection_id_length;
+ }
+ // Read destination connection ID.
+ if (!reader.ReadConnectionId(destination_connection_id,
+ *destination_connection_id_length)) {
+ *detailed_error = "Unable to read Destination ConnectionId.";
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ return QUIC_NO_ERROR;
+}
+
#undef ENDPOINT // undef for jumbo builds
} // namespace quic