Move connectivity probing related code from QuicFramer to QuicPacketCreator.
QuicPacketCreator has access to debug_delegate_, which helps log on path challenge frames.
gfe-relnote: protected by disabled v99 flag.
PiperOrigin-RevId: 273405309
Change-Id: I5f7805e0254fcaa417cababc0af0681bf8901e26
diff --git a/quic/core/quic_packet_creator_test.cc b/quic/core/quic_packet_creator_test.cc
index 1e66667..75ea7f5 100644
--- a/quic/core/quic_packet_creator_test.cc
+++ b/quic/core/quic_packet_creator_test.cc
@@ -18,6 +18,7 @@
#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
@@ -39,6 +40,12 @@
namespace test {
namespace {
+const QuicPacketNumber kPacketNumber = QuicPacketNumber(UINT64_C(0x12345678));
+// Use fields in which each byte is distinct to ensure that every byte is
+// framed correctly. The values are otherwise arbitrary.
+const QuicConnectionId kTestConnectionId =
+ TestConnectionId(UINT64_C(0xFEDCBA9876543210));
+
// Run tests with combinations of {ParsedQuicVersion,
// ToggleVersionSerialization}.
struct TestParams {
@@ -585,8 +592,8 @@
}
TEST_P(QuicPacketCreatorTest, SerializeConnectionClose) {
- QuicConnectionCloseFrame frame(GetParam().version.transport_version,
- QUIC_NO_ERROR, "error",
+ QuicConnectionCloseFrame frame(creator_.transport_version(), QUIC_NO_ERROR,
+ "error",
/*transport_close_frame_type=*/0);
QuicFrames frames;
@@ -823,7 +830,7 @@
ParsedQuicVersionVector versions;
versions.push_back(test::QuicVersionMax());
const bool ietf_quic =
- VersionHasIetfInvariantHeader(GetParam().version.transport_version);
+ VersionHasIetfInvariantHeader(creator_.transport_version());
const bool has_length_prefix =
GetParam().version.HasLengthPrefixedConnectionIds();
std::unique_ptr<QuicEncryptedPacket> encrypted(
@@ -840,6 +847,340 @@
client_framer_.ProcessPacket(*encrypted);
}
+// Test that the path challenge connectivity probing packet is serialized
+// correctly as a padded PATH CHALLENGE packet.
+TEST_P(QuicPacketCreatorTest, BuildPathChallengePacket) {
+ if (!VersionHasIetfQuicFrames(creator_.transport_version())) {
+ // This frame is only for IETF QUIC.
+ return;
+ }
+
+ QuicPacketHeader header;
+ header.destination_connection_id = kTestConnectionId;
+ header.reset_flag = false;
+ header.version_flag = false;
+ header.packet_number = kPacketNumber;
+ QuicPathFrameBuffer payload;
+
+ // clang-format off
+ unsigned char packet[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // Path Challenge Frame type (IETF_PATH_CHALLENGE)
+ 0x1a,
+ // 8 "random" bytes, MockRandom makes lots of r's
+ 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r',
+ // frame type (padding frame)
+ 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ };
+ // clang-format on
+
+ std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
+ MockRandom randomizer;
+
+ size_t length = creator_.BuildPaddedPathChallengePacket(
+ header, buffer.get(), QUIC_ARRAYSIZE(packet), &payload, &randomizer,
+ ENCRYPTION_INITIAL);
+ EXPECT_EQ(length, QUIC_ARRAYSIZE(packet));
+
+ // Payload has the random bytes that were generated. Copy them into packet,
+ // above, before checking that the generated packet is correct.
+ EXPECT_EQ(kQuicPathFrameBufferSize, payload.size());
+
+ QuicPacket data(creator_.transport_version(), buffer.release(), length, true,
+ header);
+
+ test::CompareCharArraysWithHexError(
+ "constructed packet", data.data(), data.length(),
+ reinterpret_cast<char*>(packet), QUIC_ARRAYSIZE(packet));
+}
+
+TEST_P(QuicPacketCreatorTest, BuildConnectivityProbingPacket) {
+ QuicPacketHeader header;
+ header.destination_connection_id = kTestConnectionId;
+ header.reset_flag = false;
+ header.version_flag = false;
+ header.packet_number = kPacketNumber;
+
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (8 byte connection_id)
+ 0x2C,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (ping frame)
+ 0x07,
+ // frame type (padding frame)
+ 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ };
+
+ unsigned char packet46[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type
+ 0x07,
+ // frame type (padding frame)
+ 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ };
+
+ unsigned char packet99[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_PING frame)
+ 0x01,
+ // frame type (padding frame)
+ 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ };
+ // clang-format on
+
+ unsigned char* p = packet;
+ size_t packet_size = QUIC_ARRAYSIZE(packet);
+ if (VersionHasIetfQuicFrames(creator_.transport_version())) {
+ p = packet99;
+ packet_size = QUIC_ARRAYSIZE(packet99);
+ } else if (creator_.transport_version() >= QUIC_VERSION_46) {
+ p = packet46;
+ packet_size = QUIC_ARRAYSIZE(packet46);
+ }
+
+ std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
+
+ size_t length = creator_.BuildConnectivityProbingPacket(
+ header, buffer.get(), packet_size, ENCRYPTION_INITIAL);
+
+ EXPECT_NE(0u, length);
+ QuicPacket data(creator_.transport_version(), buffer.release(), length, true,
+ header);
+
+ test::CompareCharArraysWithHexError("constructed packet", data.data(),
+ data.length(), reinterpret_cast<char*>(p),
+ packet_size);
+}
+
+// Several tests that the path response connectivity probing packet is
+// serialized correctly as either a padded and unpadded PATH RESPONSE
+// packet. Also generates packets with 1 and 3 PATH_RESPONSES in them to
+// exercised the single- and multiple- payload cases.
+TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket1ResponseUnpadded) {
+ if (!VersionHasIetfQuicFrames(creator_.transport_version())) {
+ // This frame is only for IETF QUIC.
+ return;
+ }
+
+ QuicPacketHeader header;
+ header.destination_connection_id = kTestConnectionId;
+ header.reset_flag = false;
+ header.version_flag = false;
+ header.packet_number = kPacketNumber;
+ QuicPathFrameBuffer payload0 = {
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}};
+
+ // Build 1 PATH RESPONSE, not padded
+ // clang-format off
+ unsigned char packet[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // Path Response Frame type (IETF_PATH_RESPONSE)
+ 0x1b,
+ // 8 "random" bytes
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ };
+ // clang-format on
+ std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
+ QuicDeque<QuicPathFrameBuffer> payloads;
+ payloads.push_back(payload0);
+ size_t length = creator_.BuildPathResponsePacket(
+ header, buffer.get(), QUIC_ARRAYSIZE(packet), payloads,
+ /*is_padded=*/false, ENCRYPTION_INITIAL);
+ EXPECT_EQ(length, QUIC_ARRAYSIZE(packet));
+ QuicPacket data(creator_.transport_version(), buffer.release(), length, true,
+ header);
+
+ test::CompareCharArraysWithHexError(
+ "constructed packet", data.data(), data.length(),
+ reinterpret_cast<char*>(packet), QUIC_ARRAYSIZE(packet));
+}
+
+TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket1ResponsePadded) {
+ if (!VersionHasIetfQuicFrames(creator_.transport_version())) {
+ // This frame is only for IETF QUIC.
+ return;
+ }
+
+ QuicPacketHeader header;
+ header.destination_connection_id = kTestConnectionId;
+ header.reset_flag = false;
+ header.version_flag = false;
+ header.packet_number = kPacketNumber;
+ QuicPathFrameBuffer payload0 = {
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}};
+
+ // Build 1 PATH RESPONSE, padded
+ // clang-format off
+ unsigned char packet[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // Path Response Frame type (IETF_PATH_RESPONSE)
+ 0x1b,
+ // 8 "random" bytes
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ // Padding type and pad
+ 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ // clang-format on
+ std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
+ QuicDeque<QuicPathFrameBuffer> payloads;
+ payloads.push_back(payload0);
+ size_t length = creator_.BuildPathResponsePacket(
+ header, buffer.get(), QUIC_ARRAYSIZE(packet), payloads,
+ /*is_padded=*/true, ENCRYPTION_INITIAL);
+ EXPECT_EQ(length, QUIC_ARRAYSIZE(packet));
+ QuicPacket data(creator_.transport_version(), buffer.release(), length, true,
+ header);
+
+ test::CompareCharArraysWithHexError(
+ "constructed packet", data.data(), data.length(),
+ reinterpret_cast<char*>(packet), QUIC_ARRAYSIZE(packet));
+}
+
+TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket3ResponsesUnpadded) {
+ if (!VersionHasIetfQuicFrames(creator_.transport_version())) {
+ // This frame is only for IETF QUIC.
+ return;
+ }
+
+ QuicPacketHeader header;
+ header.destination_connection_id = kTestConnectionId;
+ header.reset_flag = false;
+ header.version_flag = false;
+ header.packet_number = kPacketNumber;
+ QuicPathFrameBuffer payload0 = {
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}};
+ QuicPathFrameBuffer payload1 = {
+ {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18}};
+ QuicPathFrameBuffer payload2 = {
+ {0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28}};
+
+ // Build one packet with 3 PATH RESPONSES, no padding
+ // clang-format off
+ unsigned char packet[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // 3 path response frames (IETF_PATH_RESPONSE type byte and payload)
+ 0x1b, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x1b, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x1b, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ };
+ // clang-format on
+
+ std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
+ QuicDeque<QuicPathFrameBuffer> payloads;
+ payloads.push_back(payload0);
+ payloads.push_back(payload1);
+ payloads.push_back(payload2);
+ size_t length = creator_.BuildPathResponsePacket(
+ header, buffer.get(), QUIC_ARRAYSIZE(packet), payloads,
+ /*is_padded=*/false, ENCRYPTION_INITIAL);
+ EXPECT_EQ(length, QUIC_ARRAYSIZE(packet));
+ QuicPacket data(creator_.transport_version(), buffer.release(), length, true,
+ header);
+
+ test::CompareCharArraysWithHexError(
+ "constructed packet", data.data(), data.length(),
+ reinterpret_cast<char*>(packet), QUIC_ARRAYSIZE(packet));
+}
+
+TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket3ResponsesPadded) {
+ if (!VersionHasIetfQuicFrames(creator_.transport_version())) {
+ // This frame is only for IETF QUIC.
+ return;
+ }
+
+ QuicPacketHeader header;
+ header.destination_connection_id = kTestConnectionId;
+ header.reset_flag = false;
+ header.version_flag = false;
+ header.packet_number = kPacketNumber;
+ QuicPathFrameBuffer payload0 = {
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}};
+ QuicPathFrameBuffer payload1 = {
+ {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18}};
+ QuicPathFrameBuffer payload2 = {
+ {0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28}};
+
+ // Build one packet with 3 PATH RESPONSES, with padding
+ // clang-format off
+ unsigned char packet[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // 3 path response frames (IETF_PATH_RESPONSE byte and payload)
+ 0x1b, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x1b, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x1b, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ // Padding
+ 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ // clang-format on
+
+ std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
+ QuicDeque<QuicPathFrameBuffer> payloads;
+ payloads.push_back(payload0);
+ payloads.push_back(payload1);
+ payloads.push_back(payload2);
+ size_t length = creator_.BuildPathResponsePacket(
+ header, buffer.get(), QUIC_ARRAYSIZE(packet), payloads,
+ /*is_padded=*/true, ENCRYPTION_INITIAL);
+ EXPECT_EQ(length, QUIC_ARRAYSIZE(packet));
+ QuicPacket data(creator_.transport_version(), buffer.release(), length, true,
+ header);
+
+ test::CompareCharArraysWithHexError(
+ "constructed packet", data.data(), data.length(),
+ reinterpret_cast<char*>(packet), QUIC_ARRAYSIZE(packet));
+}
+
TEST_P(QuicPacketCreatorTest, SerializeConnectivityProbingPacket) {
for (int i = ENCRYPTION_INITIAL; i < NUM_ENCRYPTION_LEVELS; ++i) {
EncryptionLevel level = static_cast<EncryptionLevel>(i);
@@ -847,7 +1188,7 @@
creator_.set_encryption_level(level);
OwningSerializedPacketPointer encrypted;
- if (VersionHasIetfQuicFrames(GetParam().version.transport_version)) {
+ if (VersionHasIetfQuicFrames(creator_.transport_version())) {
QuicPathFrameBuffer payload = {
{0xde, 0xad, 0xbe, 0xef, 0xba, 0xdc, 0x0f, 0xfe}};
encrypted =
@@ -862,7 +1203,7 @@
EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_));
EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- if (VersionHasIetfQuicFrames(GetParam().version.transport_version)) {
+ if (VersionHasIetfQuicFrames(creator_.transport_version())) {
EXPECT_CALL(framer_visitor_, OnPathChallengeFrame(_));
EXPECT_CALL(framer_visitor_, OnPaddingFrame(_));
} else {
@@ -878,7 +1219,7 @@
}
TEST_P(QuicPacketCreatorTest, SerializePathChallengeProbePacket) {
- if (!VersionHasIetfQuicFrames(GetParam().version.transport_version)) {
+ if (!VersionHasIetfQuicFrames(creator_.transport_version())) {
return;
}
QuicPathFrameBuffer payload = {
@@ -909,7 +1250,7 @@
}
TEST_P(QuicPacketCreatorTest, SerializePathResponseProbePacket1PayloadPadded) {
- if (!VersionHasIetfQuicFrames(GetParam().version.transport_version)) {
+ if (!VersionHasIetfQuicFrames(creator_.transport_version())) {
return;
}
QuicPathFrameBuffer payload0 = {
@@ -943,7 +1284,7 @@
TEST_P(QuicPacketCreatorTest,
SerializePathResponseProbePacket1PayloadUnPadded) {
- if (!VersionHasIetfQuicFrames(GetParam().version.transport_version)) {
+ if (!VersionHasIetfQuicFrames(creator_.transport_version())) {
return;
}
QuicPathFrameBuffer payload0 = {
@@ -975,7 +1316,7 @@
}
TEST_P(QuicPacketCreatorTest, SerializePathResponseProbePacket2PayloadsPadded) {
- if (!VersionHasIetfQuicFrames(GetParam().version.transport_version)) {
+ if (!VersionHasIetfQuicFrames(creator_.transport_version())) {
return;
}
QuicPathFrameBuffer payload0 = {
@@ -1012,7 +1353,7 @@
TEST_P(QuicPacketCreatorTest,
SerializePathResponseProbePacket2PayloadsUnPadded) {
- if (!VersionHasIetfQuicFrames(GetParam().version.transport_version)) {
+ if (!VersionHasIetfQuicFrames(creator_.transport_version())) {
return;
}
QuicPathFrameBuffer payload0 = {
@@ -1047,7 +1388,7 @@
}
TEST_P(QuicPacketCreatorTest, SerializePathResponseProbePacket3PayloadsPadded) {
- if (!VersionHasIetfQuicFrames(GetParam().version.transport_version)) {
+ if (!VersionHasIetfQuicFrames(creator_.transport_version())) {
return;
}
QuicPathFrameBuffer payload0 = {
@@ -1087,7 +1428,7 @@
TEST_P(QuicPacketCreatorTest,
SerializePathResponseProbePacket3PayloadsUnpadded) {
- if (!VersionHasIetfQuicFrames(GetParam().version.transport_version)) {
+ if (!VersionHasIetfQuicFrames(creator_.transport_version())) {
return;
}
QuicPathFrameBuffer payload0 = {
@@ -1124,7 +1465,7 @@
}
TEST_P(QuicPacketCreatorTest, UpdatePacketSequenceNumberLengthLeastAwaiting) {
- if (VersionHasIetfInvariantHeader(GetParam().version.transport_version) &&
+ if (VersionHasIetfInvariantHeader(creator_.transport_version()) &&
!GetParam().version.SendsVariableLengthPacketNumberInLongHeader()) {
EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_));
@@ -1162,7 +1503,7 @@
TEST_P(QuicPacketCreatorTest, UpdatePacketSequenceNumberLengthCwnd) {
QuicPacketCreatorPeer::SetPacketNumber(&creator_, 1);
- if (VersionHasIetfInvariantHeader(GetParam().version.transport_version) &&
+ if (VersionHasIetfInvariantHeader(creator_.transport_version()) &&
!GetParam().version.SendsVariableLengthPacketNumberInLongHeader()) {
EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_));
@@ -1196,7 +1537,7 @@
TEST_P(QuicPacketCreatorTest, SkipNPacketNumbers) {
QuicPacketCreatorPeer::SetPacketNumber(&creator_, 1);
- if (VersionHasIetfInvariantHeader(GetParam().version.transport_version) &&
+ if (VersionHasIetfInvariantHeader(creator_.transport_version()) &&
!GetParam().version.SendsVariableLengthPacketNumberInLongHeader()) {
EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_));
@@ -1862,7 +2203,7 @@
// Regression test for bugfix of GetPacketHeaderSize.
TEST_P(QuicPacketCreatorTest, GetGuaranteedLargestMessagePayload) {
- QuicTransportVersion version = GetParam().version.transport_version;
+ QuicTransportVersion version = creator_.transport_version();
if (!VersionSupportsMessageFrames(version)) {
return;
}