Support 20byte connection IDs in QUIC v99 gfe-relnote: change max connection ID length, protected by disabled flag quic_enable_v99 PiperOrigin-RevId: 261237446 Change-Id: Iba22fe96d6a392c97f75f92f5c3b9ed7b11e3828
diff --git a/quic/core/quic_connection_id.cc b/quic/core/quic_connection_id.cc index 7d0f8d7..c6ef07b 100644 --- a/quic/core/quic_connection_id.cc +++ b/quic/core/quic_connection_id.cc
@@ -53,13 +53,13 @@ QuicConnectionId::QuicConnectionId() : QuicConnectionId(nullptr, 0) {} QuicConnectionId::QuicConnectionId(const char* data, uint8_t length) { - static_assert( - kQuicMaxConnectionIdLength <= std::numeric_limits<uint8_t>::max(), - "kQuicMaxConnectionIdLength too high"); - if (length > kQuicMaxConnectionIdLength) { + static_assert(kQuicMaxConnectionIdAllVersionsLength <= + std::numeric_limits<uint8_t>::max(), + "kQuicMaxConnectionIdAllVersionsLength too high"); + if (length > kQuicMaxConnectionIdAllVersionsLength) { QUIC_BUG << "Attempted to create connection ID of length " << static_cast<int>(length); - length = kQuicMaxConnectionIdLength; + length = kQuicMaxConnectionIdAllVersionsLength; } length_ = length; if (length_ == 0) { @@ -126,10 +126,10 @@ } void QuicConnectionId::set_length(uint8_t length) { - if (length > kQuicMaxConnectionIdLength) { + if (length > kQuicMaxConnectionIdAllVersionsLength) { QUIC_BUG << "Attempted to set connection ID length to " << static_cast<int>(length); - length = kQuicMaxConnectionIdLength; + length = kQuicMaxConnectionIdAllVersionsLength; } if (GetQuicRestartFlag(quic_use_allocated_connection_ids)) { QUIC_RESTART_FLAG_COUNT_N(quic_use_allocated_connection_ids, 5, 6); @@ -166,8 +166,8 @@ size_t QuicConnectionId::Hash() const { if (!GetQuicRestartFlag(quic_connection_id_use_siphash)) { uint64_t data_bytes[3] = {0, 0, 0}; - static_assert(sizeof(data_bytes) >= kQuicMaxConnectionIdLength, - "kQuicMaxConnectionIdLength changed"); + static_assert(sizeof(data_bytes) >= kQuicMaxConnectionIdAllVersionsLength, + "kQuicMaxConnectionIdAllVersionsLength changed"); memcpy(data_bytes, data(), length_); // This Hash function is designed to return the same value as the host byte // order representation when the connection ID length is 64 bits.
diff --git a/quic/core/quic_connection_id.h b/quic/core/quic_connection_id.h index f1861e0..0b8c06a 100644 --- a/quic/core/quic_connection_id.h +++ b/quic/core/quic_connection_id.h
@@ -26,7 +26,15 @@ }; // Maximum connection ID length that we support in any packet or version. -const uint8_t kQuicMaxConnectionIdLength = 18; +const uint8_t kQuicMaxConnectionIdAllVersionsLength = 20; + +// Maximum connection ID length supported by versions that use the encoding from +// draft-ietf-quic-invariants-06. +const uint8_t kQuicMaxConnectionIdWithLengthPrefixLength = 20; + +// Maximum connection ID length supported by versions that use the encoding from +// draft-ietf-quic-invariants-05. +const uint8_t kQuicMaxConnectionId4BitLength = 18; // kQuicDefaultConnectionIdLength is the only supported length for QUIC // versions < v99, and is the default picked for all versions. @@ -99,7 +107,7 @@ union { // When quic_use_allocated_connection_ids is false, the connection ID is // stored in the first |length_| bytes of |data_|. - char data_[kQuicMaxConnectionIdLength]; + char data_[kQuicMaxConnectionIdAllVersionsLength]; // When quic_use_allocated_connection_ids is true, if the connection ID // fits in |data_short_|, it is stored in the first |length_| bytes of // |data_short_|. Otherwise it is stored in |data_long_| which is
diff --git a/quic/core/quic_connection_id_test.cc b/quic/core/quic_connection_id_test.cc index 0d4b190..d80babb 100644 --- a/quic/core/quic_connection_id_test.cc +++ b/quic/core/quic_connection_id_test.cc
@@ -98,10 +98,10 @@ // 32bit platforms. return; } - const char connection_id_bytes[kQuicMaxConnectionIdLength] = {}; - for (uint8_t i = 0; i < kQuicMaxConnectionIdLength - 1; ++i) { + const char connection_id_bytes[kQuicMaxConnectionIdAllVersionsLength] = {}; + for (uint8_t i = 0; i < sizeof(connection_id_bytes) - 1; ++i) { QuicConnectionId connection_id_i(connection_id_bytes, i); - for (uint8_t j = i + 1; j < kQuicMaxConnectionIdLength; ++j) { + for (uint8_t j = i + 1; j < sizeof(connection_id_bytes); ++j) { QuicConnectionId connection_id_j(connection_id_bytes, j); EXPECT_NE(connection_id_i.Hash(), connection_id_j.Hash()); }
diff --git a/quic/core/quic_data_reader.cc b/quic/core/quic_data_reader.cc index 71395dd..d4f28a0 100644 --- a/quic/core/quic_data_reader.cc +++ b/quic/core/quic_data_reader.cc
@@ -136,7 +136,7 @@ bool QuicDataReader::ReadConnectionId(QuicConnectionId* connection_id, uint8_t length) { - if (length > kQuicMaxConnectionIdLength) { + if (length > kQuicMaxConnectionIdAllVersionsLength) { QUIC_BUG << "Attempted to read connection ID with length too high " << static_cast<int>(length); return false; @@ -172,7 +172,7 @@ if (!ReadUInt8(&connection_id_length)) { return false; } - if (connection_id_length > kQuicMaxConnectionIdLength) { + if (connection_id_length > kQuicMaxConnectionIdAllVersionsLength) { return false; } return ReadConnectionId(connection_id, connection_id_length);
diff --git a/quic/core/quic_data_writer_test.cc b/quic/core/quic_data_writer_test.cc index 352f27c..301bfa6 100644 --- a/quic/core/quic_data_writer_test.cc +++ b/quic/core/quic_data_writer_test.cc
@@ -262,8 +262,8 @@ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, }; EXPECT_EQ(connection_id.length(), QUIC_ARRAYSIZE(big_endian)); - ASSERT_LE(connection_id.length(), kQuicMaxConnectionIdLength); - char buffer[kQuicMaxConnectionIdLength]; + ASSERT_LE(connection_id.length(), 255); + char buffer[255]; QuicDataWriter writer(connection_id.length(), buffer, GetParam().endianness); EXPECT_TRUE(writer.WriteConnectionId(connection_id)); test::CompareCharArraysWithHexError("connection_id", buffer, @@ -285,7 +285,7 @@ }; EXPECT_EQ(QUIC_ARRAYSIZE(length_prefixed_connection_id), kConnectionIdLengthSize + connection_id.length()); - char buffer[kConnectionIdLengthSize + kQuicMaxConnectionIdLength] = {}; + char buffer[kConnectionIdLengthSize + 255] = {}; QuicDataWriter writer(QUIC_ARRAYSIZE(buffer), buffer); EXPECT_TRUE(writer.WriteLengthPrefixedConnectionId(connection_id)); test::CompareCharArraysWithHexError( @@ -1150,8 +1150,9 @@ TEST_P(QuicDataWriterTest, InvalidConnectionIdLengthRead) { static const uint8_t bad_connection_id_length = 200; - static_assert(bad_connection_id_length > kQuicMaxConnectionIdLength, - "bad lengths"); + static_assert( + bad_connection_id_length > kQuicMaxConnectionIdAllVersionsLength, + "bad lengths"); char buffer[255] = {}; QuicDataReader reader(buffer, sizeof(buffer)); QuicConnectionId connection_id;
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc index bd0a724..91d4a0a 100644 --- a/quic/core/quic_framer.cc +++ b/quic/core/quic_framer.cc
@@ -6611,7 +6611,7 @@ QUIC_BUG << "Invalid packet_length"; return false; } - if (destination_connection_id_length > kQuicMaxConnectionIdLength || + if (destination_connection_id_length > kQuicMaxConnectionId4BitLength || destination_connection_id_length < kQuicMinimumInitialConnectionIdLength) { QUIC_BUG << "Invalid connection_id_length";
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc index f6f5eda..32432fb 100644 --- a/quic/core/quic_framer_test.cc +++ b/quic/core/quic_framer_test.cc
@@ -14164,7 +14164,7 @@ }; // clang-format on char probe_payload_bytes[] = {0x56, 0x4e, 0x20, 0x70, 0x6c, 0x7a, 0x20, 0x21}; - char parsed_probe_payload_bytes[kQuicMaxConnectionIdLength] = {}; + char parsed_probe_payload_bytes[255] = {}; uint8_t parsed_probe_payload_length = 0; std::string parse_detailed_error = ""; EXPECT_TRUE(QuicFramer::ParseServerVersionNegotiationProbeResponse( @@ -14195,7 +14195,7 @@ }; // clang-format on char probe_payload_bytes[] = {0x56, 0x4e, 0x20, 0x70, 0x6c, 0x7a, 0x20, 0x21}; - char parsed_probe_payload_bytes[kQuicMaxConnectionIdLength] = {}; + char parsed_probe_payload_bytes[255] = {}; uint8_t parsed_probe_payload_length = 0; std::string parse_detailed_error = ""; EXPECT_TRUE(QuicFramer::ParseServerVersionNegotiationProbeResponse(
diff --git a/quic/core/quic_utils.cc b/quic/core/quic_utils.cc index 4ff7489..58996f6 100644 --- a/quic/core/quic_utils.cc +++ b/quic/core/quic_utils.cc
@@ -554,9 +554,9 @@ if (!VersionHasLengthPrefixedConnectionIds(transport_version)) { return connection_id_length8 == 0 || (connection_id_length8 >= 4 && - connection_id_length8 <= kQuicMaxConnectionIdLength); + connection_id_length8 <= kQuicMaxConnectionId4BitLength); } - return connection_id_length8 <= kQuicMaxConnectionIdLength; + return connection_id_length8 <= kQuicMaxConnectionIdWithLengthPrefixLength; } // static @@ -570,8 +570,8 @@ QuicUint128 QuicUtils::GenerateStatelessResetToken( QuicConnectionId connection_id) { uint64_t data_bytes[3] = {0, 0, 0}; - static_assert(sizeof(data_bytes) >= kQuicMaxConnectionIdLength, - "kQuicMaxConnectionIdLength changed"); + static_assert(sizeof(data_bytes) >= kQuicMaxConnectionIdAllVersionsLength, + "kQuicMaxConnectionIdAllVersionsLength changed"); memcpy(data_bytes, connection_id.data(), connection_id.length()); // This is designed so that the common case of 64bit connection IDs // produces a stateless reset token that is equal to the connection ID