void CheckStreamFrameBoundaries(unsigned char* packet,
size_t stream_id_size,
bool include_version) {
- // Now test framing boundaries
+ // Now test framing boundaries.
for (size_t i = kQuicFrameTypeSize; i < GetMinStreamFrameSize(); ++i) {
string expected_error;
if (i < kQuicFrameTypeSize + stream_id_size) {
EXPECT_EQ(NOT_IN_FEC_GROUP, visitor_.header_->is_in_fec_group);
EXPECT_EQ(0x00u, visitor_.header_->fec_group);
- // Now test framing boundaries
+ // Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
EXPECT_EQ(NOT_IN_FEC_GROUP, visitor_.header_->is_in_fec_group);
EXPECT_EQ(0x00u, visitor_.header_->fec_group);
- // Now test framing boundaries
+ // Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_4BYTE_CONNECTION_ID, !kIncludeVersion,
PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
EXPECT_EQ(NOT_IN_FEC_GROUP, visitor_.header_->is_in_fec_group);
EXPECT_EQ(0x00u, visitor_.header_->fec_group);
- // Now test framing boundaries
+ // Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_1BYTE_CONNECTION_ID, !kIncludeVersion,
PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
EXPECT_EQ(NOT_IN_FEC_GROUP, visitor_.header_->is_in_fec_group);
EXPECT_EQ(0x00u, visitor_.header_->fec_group);
- // Now test framing boundaries
+ // Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_0BYTE_CONNECTION_ID, !kIncludeVersion,
PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
EXPECT_EQ(NOT_IN_FEC_GROUP, visitor_.header_->is_in_fec_group);
EXPECT_EQ(0x00u, visitor_.header_->fec_group);
- // Now test framing boundaries
+ // Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, kIncludeVersion,
PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
EXPECT_EQ(NOT_IN_FEC_GROUP, visitor_.header_->is_in_fec_group);
EXPECT_EQ(0x00u, visitor_.header_->fec_group);
- // Now test framing boundaries
+ // Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
PACKET_4BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
EXPECT_EQ(NOT_IN_FEC_GROUP, visitor_.header_->is_in_fec_group);
EXPECT_EQ(0x00u, visitor_.header_->fec_group);
- // Now test framing boundaries
+ // Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
PACKET_2BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
EXPECT_EQ(NOT_IN_FEC_GROUP, visitor_.header_->is_in_fec_group);
EXPECT_EQ(0x00u, visitor_.header_->fec_group);
- // Now test framing boundaries
+ // Now test framing boundaries.
for (size_t i = 0;
i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
PACKET_1BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
visitor_.stream_frames_[0]->offset);
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]);
- // Now test framing boundaries
+ // Now test framing boundaries.
CheckStreamFrameBoundaries(packet, kQuicMaxStreamIdSize, !kIncludeVersion);
}
visitor_.stream_frames_[0]->offset);
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]);
- // Now test framing boundaries
+ // Now test framing boundaries.
const size_t stream_id_size = 3;
CheckStreamFrameBoundaries(packet, stream_id_size, !kIncludeVersion);
}
visitor_.stream_frames_[0]->offset);
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]);
- // Now test framing boundaries
+ // Now test framing boundaries.
const size_t stream_id_size = 2;
CheckStreamFrameBoundaries(packet, stream_id_size, !kIncludeVersion);
}
visitor_.stream_frames_[0]->offset);
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]);
- // Now test framing boundaries
+ // Now test framing boundaries.
const size_t stream_id_size = 1;
CheckStreamFrameBoundaries(packet, stream_id_size, !kIncludeVersion);
}
visitor_.stream_frames_[0]->offset);
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]);
- // Now test framing boundaries
+ // Now test framing boundaries.
CheckStreamFrameBoundaries(packet, kQuicMaxStreamIdSize, kIncludeVersion);
}
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]);
}
+TEST_P(QuicFramerTest, AckFramev22) {
+ if (version_ > QUIC_VERSION_22) {
+ return;
+ }
+ unsigned char packet[] = {
+ // public flags (8 byte connection_id)
+ 0x3C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet sequence number
+ 0xA8, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // private flags (entropy)
+ 0x01,
+
+ // frame type (ack frame)
+ // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
+ 0x6C,
+ // entropy hash of all received packets.
+ 0xBA,
+ // largest observed packet sequence number
+ 0xBF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // Zero delta time.
+ 0x0, 0x0,
+ // num missing packets
+ 0x01,
+ // missing packet delta
+ 0x01,
+ // 0 more missing packets in range.
+ 0x00,
+ // Number of revived packets.
+ 0x00,
+ };
+
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+
+ EXPECT_EQ(0u, visitor_.stream_frames_.size());
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ const QuicAckFrame& frame = *visitor_.ack_frames_[0];
+ EXPECT_EQ(0xBA, frame.entropy_hash);
+ EXPECT_EQ(GG_UINT64_C(0x0123456789ABF), frame.largest_observed);
+ ASSERT_EQ(1u, frame.missing_packets.size());
+ SequenceNumberSet::const_iterator missing_iter =
+ frame.missing_packets.begin();
+ EXPECT_EQ(GG_UINT64_C(0x0123456789ABE), *missing_iter);
+
+ const size_t kReceivedEntropyOffset = kQuicFrameTypeSize;
+ const size_t kLargestObservedOffset = kReceivedEntropyOffset +
+ kQuicEntropyHashSize;
+ const size_t kMissingDeltaTimeOffset = kLargestObservedOffset +
+ PACKET_6BYTE_SEQUENCE_NUMBER;
+ const size_t kNumMissingPacketOffset = kMissingDeltaTimeOffset +
+ kQuicDeltaTimeLargestObservedSize;
+ const size_t kMissingPacketsOffset = kNumMissingPacketOffset +
+ kNumberOfNackRangesSize;
+ const size_t kMissingPacketsRange = kMissingPacketsOffset +
+ PACKET_1BYTE_SEQUENCE_NUMBER;
+ const size_t kRevivedPacketsLength = kMissingPacketsRange +
+ PACKET_1BYTE_SEQUENCE_NUMBER;
+ // Now test framing boundaries.
+ const size_t ack_frame_size = kRevivedPacketsLength +
+ PACKET_1BYTE_SEQUENCE_NUMBER;
+ for (size_t i = kQuicFrameTypeSize; i < ack_frame_size; ++i) {
+ string expected_error;
+ if (i < kLargestObservedOffset) {
+ expected_error = "Unable to read entropy hash for received packets.";
+ } else if (i < kMissingDeltaTimeOffset) {
+ expected_error = "Unable to read largest observed.";
+ } else if (i < kNumMissingPacketOffset) {
+ expected_error = "Unable to read delta time largest observed.";
+ } else if (i < kMissingPacketsOffset) {
+ expected_error = "Unable to read num missing packet ranges.";
+ } else if (i < kMissingPacketsRange) {
+ expected_error = "Unable to read missing sequence number delta.";
+ } else if (i < kRevivedPacketsLength) {
+ expected_error = "Unable to read missing sequence number range.";
+ } else {
+ expected_error = "Unable to read num revived packets.";
+ }
+ CheckProcessingFails(
+ packet,
+ i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+ PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP),
+ expected_error, QUIC_INVALID_ACK_DATA);
+ }
+}
+
+
+TEST_P(QuicFramerTest, AckFrameTwoTimestamp) {
+ if (version_ <= QUIC_VERSION_22) {
+ return;
+ }
+ unsigned char packet[] = {
+ // public flags (8 byte connection_id)
+ 0x3C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet sequence number
+ 0xA8, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // private flags (entropy)
+ 0x01,
+
+ // frame type (ack frame)
+ // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
+ 0x6C,
+ // entropy hash of all received packets.
+ 0xBA,
+ // largest observed packet sequence number
+ 0xBF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // Zero delta time.
+ 0x0, 0x0,
+ // Number of timestamps.
+ 0x02,
+ // Delta from largest observed.
+ 0x01,
+ // Delta time.
+ 0x10, 0x32, 0x54, 0x76,
+ // Delta from largest observed.
+ 0x02,
+ // Delta time.
+ 0x10, 0x32,
+ // num missing packets
+ 0x01,
+ // missing packet delta
+ 0x01,
+ // 0 more missing packets in range.
+ 0x00,
+ // Number of revived packets.
+ 0x00,
+ };
+
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+
+ EXPECT_EQ(0u, visitor_.stream_frames_.size());
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ const QuicAckFrame& frame = *visitor_.ack_frames_[0];
+ EXPECT_EQ(0xBA, frame.entropy_hash);
+ EXPECT_EQ(GG_UINT64_C(0x0123456789ABF), frame.largest_observed);
+ ASSERT_EQ(1u, frame.missing_packets.size());
+ ASSERT_EQ(2u, frame.received_packet_times.size());
+ SequenceNumberSet::const_iterator missing_iter =
+ frame.missing_packets.begin();
+ EXPECT_EQ(GG_UINT64_C(0x0123456789ABE), *missing_iter);
+
+ const size_t kReceivedEntropyOffset = kQuicFrameTypeSize;
+ const size_t kLargestObservedOffset = kReceivedEntropyOffset +
+ kQuicEntropyHashSize;
+ const size_t kMissingDeltaTimeOffset = kLargestObservedOffset +
+ PACKET_6BYTE_SEQUENCE_NUMBER;
+ const size_t kNumTimestampsOffset = kMissingDeltaTimeOffset +
+ kQuicDeltaTimeLargestObservedSize;
+ const size_t kTimestampDeltaLargestObserved1 = kNumTimestampsOffset +
+ kQuicNumTimestampsSize;
+ const size_t kTimestampTimeDeltaLargestObserved1 =
+ kTimestampDeltaLargestObserved1 + 1;
+ const size_t kTimestampDeltaLargestObserved2 =
+ kTimestampTimeDeltaLargestObserved1 + 4;
+ const size_t kTimestampTimeDeltaLargestObserved2 =
+ kTimestampDeltaLargestObserved2 + 1;
+ const size_t kNumMissingPacketOffset =
+ kTimestampTimeDeltaLargestObserved2 + 2;
+ const size_t kMissingPacketsOffset = kNumMissingPacketOffset +
+ kNumberOfNackRangesSize;
+ const size_t kMissingPacketsRange = kMissingPacketsOffset +
+ PACKET_1BYTE_SEQUENCE_NUMBER;
+ const size_t kRevivedPacketsLength = kMissingPacketsRange +
+ PACKET_1BYTE_SEQUENCE_NUMBER;
+ // Now test framing boundaries.
+ const size_t ack_frame_size = kRevivedPacketsLength +
+ PACKET_1BYTE_SEQUENCE_NUMBER;
+ for (size_t i = kQuicFrameTypeSize; i < ack_frame_size; ++i) {
+ string expected_error;
+ if (i < kLargestObservedOffset) {
+ expected_error = "Unable to read entropy hash for received packets.";
+ } else if (i < kMissingDeltaTimeOffset) {
+ expected_error = "Unable to read largest observed.";
+ } else if (i < kNumTimestampsOffset) {
+ expected_error = "Unable to read delta time largest observed.";
+ } else if (i < kTimestampDeltaLargestObserved1) {
+ expected_error = "Unable to read num received packets.";
+ } else if (i < kTimestampTimeDeltaLargestObserved1) {
+ expected_error = "Unable to read sequence delta in received packets.";
+ } else if (i < kTimestampDeltaLargestObserved2) {
+ expected_error = "Unable to read time delta in received packets.";
+ } else if (i < kTimestampTimeDeltaLargestObserved2) {
+ expected_error = "Unable to read sequence delta in received packets.";
+ } else if (i < kNumMissingPacketOffset) {
+ expected_error =
+ "Unable to read incremental time delta in received packets.";
+ } else if (i < kMissingPacketsOffset) {
+ expected_error = "Unable to read num missing packet ranges.";
+ } else if (i < kMissingPacketsRange) {
+ expected_error = "Unable to read missing sequence number delta.";
+ } else if (i < kRevivedPacketsLength) {
+ expected_error = "Unable to read missing sequence number range.";
+ } else {
+ expected_error = "Unable to read num revived packets.";
+ }
+ CheckProcessingFails(
+ packet,
+ i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+ PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP),
+ expected_error, QUIC_INVALID_ACK_DATA);
+ }
+}
+
+
+TEST_P(QuicFramerTest, AckFrameOneTimestamp) {
+ if (version_ <= QUIC_VERSION_22) {
+ return;
+ }
+ unsigned char packet[] = {
+ // public flags (8 byte connection_id)
+ 0x3C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet sequence number
+ 0xA8, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // private flags (entropy)
+ 0x01,
+
+ // frame type (ack frame)
+ // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
+ 0x6C,
+ // entropy hash of all received packets.
+ 0xBA,
+ // largest observed packet sequence number
+ 0xBF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // Zero delta time.
+ 0x0, 0x0,
+ // Number of timestamps.
+ 0x01,
+ // Delta from largest observed.
+ 0x01,
+ // Delta time.
+ 0x10, 0x32, 0x54, 0x76,
+ // num missing packets
+ 0x01,
+ // missing packet delta
+ 0x01,
+ // 0 more missing packets in range.
+ 0x00,
+ // Number of revived packets.
+ 0x00,
+ };
+
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+
+ EXPECT_EQ(0u, visitor_.stream_frames_.size());
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ const QuicAckFrame& frame = *visitor_.ack_frames_[0];
+ EXPECT_EQ(0xBA, frame.entropy_hash);
+ EXPECT_EQ(GG_UINT64_C(0x0123456789ABF), frame.largest_observed);
+ ASSERT_EQ(1u, frame.missing_packets.size());
+ ASSERT_EQ(1u, frame.received_packet_times.size());
+ SequenceNumberSet::const_iterator missing_iter =
+ frame.missing_packets.begin();
+ EXPECT_EQ(GG_UINT64_C(0x0123456789ABE), *missing_iter);
+
+ const size_t kReceivedEntropyOffset = kQuicFrameTypeSize;
+ const size_t kLargestObservedOffset = kReceivedEntropyOffset +
+ kQuicEntropyHashSize;
+ const size_t kMissingDeltaTimeOffset = kLargestObservedOffset +
+ PACKET_6BYTE_SEQUENCE_NUMBER;
+ const size_t kNumTimestampsOffset = kMissingDeltaTimeOffset +
+ kQuicDeltaTimeLargestObservedSize;
+ const size_t kTimestampDeltaLargestObserved = kNumTimestampsOffset +
+ kQuicNumTimestampsSize;
+ const size_t kTimestampTimeDeltaLargestObserved =
+ kTimestampDeltaLargestObserved + 1;
+ const size_t kNumMissingPacketOffset = kTimestampTimeDeltaLargestObserved + 4;
+ const size_t kMissingPacketsOffset = kNumMissingPacketOffset +
+ kNumberOfNackRangesSize;
+ const size_t kMissingPacketsRange = kMissingPacketsOffset +
+ PACKET_1BYTE_SEQUENCE_NUMBER;
+ const size_t kRevivedPacketsLength = kMissingPacketsRange +
+ PACKET_1BYTE_SEQUENCE_NUMBER;
+ // Now test framing boundaries.
+ const size_t ack_frame_size = kRevivedPacketsLength +
+ PACKET_1BYTE_SEQUENCE_NUMBER;
+ for (size_t i = kQuicFrameTypeSize; i < ack_frame_size; ++i) {
+ string expected_error;
+ if (i < kLargestObservedOffset) {
+ expected_error = "Unable to read entropy hash for received packets.";
+ } else if (i < kMissingDeltaTimeOffset) {
+ expected_error = "Unable to read largest observed.";
+ } else if (i < kNumTimestampsOffset) {
+ expected_error = "Unable to read delta time largest observed.";
+ } else if (i < kTimestampDeltaLargestObserved) {
+ expected_error = "Unable to read num received packets.";
+ } else if (i < kTimestampTimeDeltaLargestObserved) {
+ expected_error = "Unable to read sequence delta in received packets.";
+ } else if (i < kNumMissingPacketOffset) {
+ expected_error = "Unable to read time delta in received packets.";
+ } else if (i < kMissingPacketsOffset) {
+ expected_error = "Unable to read num missing packet ranges.";
+ } else if (i < kMissingPacketsRange) {
+ expected_error = "Unable to read missing sequence number delta.";
+ } else if (i < kRevivedPacketsLength) {
+ expected_error = "Unable to read missing sequence number range.";
+ } else {
+ expected_error = "Unable to read num revived packets.";
+ }
+ CheckProcessingFails(
+ packet,
+ i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+ PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP),
+ expected_error, QUIC_INVALID_ACK_DATA);
+ }
+}
+
+
TEST_P(QuicFramerTest, AckFrame) {
+ if (version_ <= QUIC_VERSION_22) {
+ return;
+ }
+ unsigned char packet[] = {
+ // public flags (8 byte connection_id)
+ 0x3C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet sequence number
+ 0xA8, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // private flags (entropy)
+ 0x01,
+
+ // frame type (ack frame)
+ // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
+ 0x6C,
+ // entropy hash of all received packets.
+ 0xBA,
+ // largest observed packet sequence number
+ 0xBF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // Zero delta time.
+ 0x0, 0x0,
+ // Number of timestamps.
+ 0x00,
+ // num missing packets
+ 0x01,
+ // missing packet delta
+ 0x01,
+ // 0 more missing packets in range.
+ 0x00,
+ // Number of revived packets.
+ 0x00,
+ };
+
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+
+ EXPECT_EQ(0u, visitor_.stream_frames_.size());
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ const QuicAckFrame& frame = *visitor_.ack_frames_[0];
+ EXPECT_EQ(0xBA, frame.entropy_hash);
+ EXPECT_EQ(GG_UINT64_C(0x0123456789ABF), frame.largest_observed);
+ ASSERT_EQ(1u, frame.missing_packets.size());
+ SequenceNumberSet::const_iterator missing_iter =
+ frame.missing_packets.begin();
+ EXPECT_EQ(GG_UINT64_C(0x0123456789ABE), *missing_iter);
+
+ const size_t kReceivedEntropyOffset = kQuicFrameTypeSize;
+ const size_t kLargestObservedOffset = kReceivedEntropyOffset +
+ kQuicEntropyHashSize;
+ const size_t kMissingDeltaTimeOffset = kLargestObservedOffset +
+ PACKET_6BYTE_SEQUENCE_NUMBER;
+ const size_t kNumTimestampsOffset = kMissingDeltaTimeOffset +
+ kQuicDeltaTimeLargestObservedSize;
+ const size_t kNumMissingPacketOffset = kNumTimestampsOffset +
+ kQuicNumTimestampsSize;
+ const size_t kMissingPacketsOffset = kNumMissingPacketOffset +
+ kNumberOfNackRangesSize;
+ const size_t kMissingPacketsRange = kMissingPacketsOffset +
+ PACKET_1BYTE_SEQUENCE_NUMBER;
+ const size_t kRevivedPacketsLength = kMissingPacketsRange +
+ PACKET_1BYTE_SEQUENCE_NUMBER;
+ // Now test framing boundaries.
+ const size_t ack_frame_size = kRevivedPacketsLength +
+ PACKET_1BYTE_SEQUENCE_NUMBER;
+ for (size_t i = kQuicFrameTypeSize; i < ack_frame_size; ++i) {
+ string expected_error;
+ if (i < kLargestObservedOffset) {
+ expected_error = "Unable to read entropy hash for received packets.";
+ } else if (i < kMissingDeltaTimeOffset) {
+ expected_error = "Unable to read largest observed.";
+ } else if (i < kNumTimestampsOffset) {
+ expected_error = "Unable to read delta time largest observed.";
+ } else if (i < kNumMissingPacketOffset) {
+ expected_error = "Unable to read num received packets.";
+ } else if (i < kMissingPacketsOffset) {
+ expected_error = "Unable to read num missing packet ranges.";
+ } else if (i < kMissingPacketsRange) {
+ expected_error = "Unable to read missing sequence number delta.";
+ } else if (i < kRevivedPacketsLength) {
+ expected_error = "Unable to read missing sequence number range.";
+ } else {
+ expected_error = "Unable to read num revived packets.";
+ }
+ CheckProcessingFails(
+ packet,
+ i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+ PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP),
+ expected_error, QUIC_INVALID_ACK_DATA);
+ }
+}
+
+TEST_P(QuicFramerTest, AckFrameRevivedPackets) {
+ if (version_ <= QUIC_VERSION_22) {
+ return;
+ }
unsigned char packet[] = {
// public flags (8 byte connection_id)
0x3C,
0x34, 0x12,
// Zero delta time.
0x0, 0x0,
+ // num received packets.
+ 0x00,
// num missing packets
0x01,
// missing packet delta
// 0 more missing packets in range.
0x00,
// Number of revived packets.
+ 0x01,
+ // Revived packet sequence number.
+ 0xBE, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // Number of revived packets.
0x00,
};
kQuicEntropyHashSize;
const size_t kMissingDeltaTimeOffset = kLargestObservedOffset +
PACKET_6BYTE_SEQUENCE_NUMBER;
- const size_t kNumMissingPacketOffset = kMissingDeltaTimeOffset +
+ const size_t kNumTimestampsOffset = kMissingDeltaTimeOffset +
kQuicDeltaTimeLargestObservedSize;
+ const size_t kNumMissingPacketOffset = kNumTimestampsOffset +
+ kQuicNumTimestampsSize;
const size_t kMissingPacketsOffset = kNumMissingPacketOffset +
kNumberOfNackRangesSize;
const size_t kMissingPacketsRange = kMissingPacketsOffset +
PACKET_1BYTE_SEQUENCE_NUMBER;
const size_t kRevivedPacketsLength = kMissingPacketsRange +
PACKET_1BYTE_SEQUENCE_NUMBER;
- // Now test framing boundaries
- const size_t ack_frame_size = kRevivedPacketsLength +
+ const size_t kRevivedPacketSequenceNumberLength = kRevivedPacketsLength +
PACKET_1BYTE_SEQUENCE_NUMBER;
+ // Now test framing boundaries.
+ const size_t ack_frame_size = kRevivedPacketSequenceNumberLength +
+ PACKET_6BYTE_SEQUENCE_NUMBER;
for (size_t i = kQuicFrameTypeSize; i < ack_frame_size; ++i) {
string expected_error;
- if (i < kLargestObservedOffset) {
+ if (i < kReceivedEntropyOffset) {
+ expected_error = "Unable to read least unacked delta.";
+ } else if (i < kLargestObservedOffset) {
expected_error = "Unable to read entropy hash for received packets.";
} else if (i < kMissingDeltaTimeOffset) {
expected_error = "Unable to read largest observed.";
- } else if (i < kNumMissingPacketOffset) {
+ } else if (i < kNumTimestampsOffset) {
expected_error = "Unable to read delta time largest observed.";
+ } else if (i < kNumMissingPacketOffset) {
+ expected_error = "Unable to read num received packets.";
} else if (i < kMissingPacketsOffset) {
expected_error = "Unable to read num missing packet ranges.";
} else if (i < kMissingPacketsRange) {
expected_error = "Unable to read missing sequence number delta.";
} else if (i < kRevivedPacketsLength) {
expected_error = "Unable to read missing sequence number range.";
- } else {
+ } else if (i < kRevivedPacketSequenceNumberLength) {
expected_error = "Unable to read num revived packets.";
+ } else {
+ expected_error = "Unable to read revived packet.";
}
CheckProcessingFails(
packet,
}
}
-TEST_P(QuicFramerTest, AckFrameRevivedPackets) {
+TEST_P(QuicFramerTest, AckFrameRevivedPacketsv22) {
+ if (version_ > QUIC_VERSION_22) {
+ return;
+ }
unsigned char packet[] = {
// public flags (8 byte connection_id)
0x3C,
// Revived packet sequence number.
0xBE, 0x9A, 0x78, 0x56,
0x34, 0x12,
+ // Number of revived packets.
+ 0x00,
};
QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
PACKET_1BYTE_SEQUENCE_NUMBER;
const size_t kRevivedPacketSequenceNumberLength = kRevivedPacketsLength +
PACKET_1BYTE_SEQUENCE_NUMBER;
- // Now test framing boundaries
+ // Now test framing boundaries.
const size_t ack_frame_size = kRevivedPacketSequenceNumberLength +
PACKET_6BYTE_SEQUENCE_NUMBER;
for (size_t i = kQuicFrameTypeSize; i < ack_frame_size; ++i) {
}
}
+TEST_P(QuicFramerTest, AckFrameNoNacksv22) {
+ if (version_ > QUIC_VERSION_22) {
+ return;
+ }
+ unsigned char packet[] = {
+ // public flags (8 byte connection_id)
+ 0x3C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet sequence number
+ 0xA8, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // private flags (entropy)
+ 0x01,
+
+ // frame type (ack frame)
+ // (no nacks, not truncated, 6 byte largest observed, 1 byte delta)
+ 0x4C,
+ // entropy hash of all received packets.
+ 0xBA,
+ // largest observed packet sequence number
+ 0xBF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // Zero delta time.
+ 0x0, 0x0,
+ };
+
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+
+ EXPECT_EQ(0u, visitor_.stream_frames_.size());
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ QuicAckFrame* frame = visitor_.ack_frames_[0];
+ EXPECT_EQ(0xBA, frame->entropy_hash);
+ EXPECT_EQ(GG_UINT64_C(0x0123456789ABF), frame->largest_observed);
+ ASSERT_EQ(0u, frame->missing_packets.size());
+
+ // Verify that the packet re-serializes identically.
+ QuicFrames frames;
+ frames.push_back(QuicFrame(frame));
+ scoped_ptr<QuicPacket> data(BuildDataPacket(*visitor_.header_, frames));
+ ASSERT_TRUE(data != NULL);
+
+ test::CompareCharArraysWithHexError("constructed packet",
+ data->data(), data->length(),
+ AsChars(packet), arraysize(packet));
+}
+
TEST_P(QuicFramerTest, AckFrameNoNacks) {
+ if (version_ <= QUIC_VERSION_22) {
+ return;
+ }
unsigned char packet[] = {
// public flags (8 byte connection_id)
0x3C,
0x34, 0x12,
// Zero delta time.
0x0, 0x0,
+ // Number of received packets.
+ 0x00,
};
QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
AsChars(packet), arraysize(packet));
}
+TEST_P(QuicFramerTest, AckFrame500Nacksv22) {
+ if (version_ > QUIC_VERSION_22) {
+ return;
+ }
+ unsigned char packet[] = {
+ // public flags (8 byte connection_id)
+ 0x3C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet sequence number
+ 0xA8, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // private flags (entropy)
+ 0x01,
+
+ // frame type (ack frame)
+ // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
+ 0x6C,
+ // entropy hash of all received packets.
+ 0xBA,
+ // largest observed packet sequence number
+ 0xBF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // Zero delta time.
+ 0x0, 0x0,
+ // num missing packet ranges
+ 0x02,
+ // missing packet delta
+ 0x01,
+ // 243 more missing packets in range.
+ // The ranges are listed in this order so the re-constructed packet matches.
+ 0xF3,
+ // No gap between ranges
+ 0x00,
+ // 255 more missing packets in range.
+ 0xFF,
+ // No revived packets.
+ 0x00,
+ };
+
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion));
+
+ EXPECT_EQ(0u, visitor_.stream_frames_.size());
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ QuicAckFrame* frame = visitor_.ack_frames_[0];
+ EXPECT_EQ(0xBA, frame->entropy_hash);
+ EXPECT_EQ(GG_UINT64_C(0x0123456789ABF), frame->largest_observed);
+ EXPECT_EQ(0u, frame->revived_packets.size());
+ ASSERT_EQ(500u, frame->missing_packets.size());
+ SequenceNumberSet::const_iterator first_missing_iter =
+ frame->missing_packets.begin();
+ EXPECT_EQ(GG_UINT64_C(0x0123456789ABE) - 499, *first_missing_iter);
+ SequenceNumberSet::const_reverse_iterator last_missing_iter =
+ frame->missing_packets.rbegin();
+ EXPECT_EQ(GG_UINT64_C(0x0123456789ABE), *last_missing_iter);
+
+ // Verify that the packet re-serializes identically.
+ QuicFrames frames;
+ frames.push_back(QuicFrame(frame));
+ scoped_ptr<QuicPacket> data(BuildDataPacket(*visitor_.header_, frames));
+ ASSERT_TRUE(data != NULL);
+
+ test::CompareCharArraysWithHexError("constructed packet",
+ data->data(), data->length(),
+ AsChars(packet), arraysize(packet));
+}
+
TEST_P(QuicFramerTest, AckFrame500Nacks) {
+ if (version_ <= QUIC_VERSION_22) {
+ return;
+ }
unsigned char packet[] = {
// public flags (8 byte connection_id)
0x3C,
0x34, 0x12,
// Zero delta time.
0x0, 0x0,
+ // No received packets.
+ 0x00,
// num missing packet ranges
0x02,
// missing packet delta
ASSERT_EQ(kTCP, frame.type);
EXPECT_EQ(0x4030u, frame.tcp.receive_window);
- // Now test framing boundaries
+ // Now test framing boundaries.
for (size_t i = kQuicFrameTypeSize; i < 4; ++i) {
string expected_error;
if (i < 2) {
EXPECT_EQ(GG_UINT64_C(0x0807060504030201),
visitor_.rst_stream_frame_.byte_offset);
- // Now test framing boundaries
+ // Now test framing boundaries.
for (size_t i = kQuicFrameTypeSize;
i < QuicFramer::GetMinRstStreamFrameSize(); ++i) {
string expected_error;
ASSERT_EQ(0u, visitor_.ack_frames_.size());
- // Now test framing boundaries
+ // Now test framing boundaries.
for (size_t i = kQuicFrameTypeSize;
i < QuicFramer::GetMinConnectionCloseFrameSize(); ++i) {
string expected_error;
EXPECT_EQ("because I can", visitor_.goaway_frame_.reason_phrase);
const size_t reason_size = arraysize("because I can") - 1;
- // Now test framing boundaries
+ // Now test framing boundaries.
for (size_t i = kQuicFrameTypeSize;
i < QuicFramer::GetMinGoAwayFrameSize() + reason_size; ++i) {
string expected_error;
EXPECT_EQ(GG_UINT64_C(0x0c0b0a0908070605),
visitor_.window_update_frame_.byte_offset);
- // Now test framing boundaries
+ // Now test framing boundaries.
for (size_t i = kQuicFrameTypeSize;
i < QuicFramer::GetWindowUpdateFrameSize(); ++i) {
string expected_error;
EXPECT_EQ(GG_UINT64_C(0x01020304),
visitor_.blocked_frame_.stream_id);
- // Now test framing boundaries
+ // Now test framing boundaries.
for (size_t i = kQuicFrameTypeSize; i < QuicFramer::GetBlockedFrameSize();
++i) {
string expected_error = "Unable to read stream_id.";
EXPECT_TRUE(
visitor_.public_reset_packet_->client_address.address().empty());
- // Now test framing boundaries
+ // Now test framing boundaries.
for (size_t i = 0; i < arraysize(packet); ++i) {
string expected_error;
DVLOG(1) << "iteration: " << i;
client_address.address()));
EXPECT_EQ(443, visitor_.public_reset_packet_->client_address.port());
- // Now test framing boundaries
+ // Now test framing boundaries.
for (size_t i = 0; i < arraysize(packet); ++i) {
string expected_error;
DVLOG(1) << "iteration: " << i;
'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(),
};
- QuicVersionVector versions;
- versions.push_back(GetParam());
- scoped_ptr<QuicEncryptedPacket> data(
- framer_.BuildVersionNegotiationPacket(header, versions));
+ QuicVersionVector versions;
+ versions.push_back(GetParam());
+ scoped_ptr<QuicEncryptedPacket> data(
+ framer_.BuildVersionNegotiationPacket(header, versions));
+
+ test::CompareCharArraysWithHexError("constructed packet",
+ data->data(), data->length(),
+ AsChars(packet), arraysize(packet));
+}
+
+TEST_P(QuicFramerTest, BuildAckFramePacketv22) {
+ if (version_ > QUIC_VERSION_22) {
+ return;
+ }
+ QuicPacketHeader header;
+ header.public_header.connection_id = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.reset_flag = false;
+ header.public_header.version_flag = false;
+ header.fec_flag = false;
+ header.entropy_flag = true;
+ header.packet_sequence_number = GG_UINT64_C(0x770123456789AA8);
+ header.fec_group = 0;
+
+ QuicAckFrame ack_frame;
+ ack_frame.entropy_hash = 0x43;
+ ack_frame.largest_observed = GG_UINT64_C(0x770123456789ABF);
+ ack_frame.delta_time_largest_observed = QuicTime::Delta::Zero();
+ ack_frame.missing_packets.insert(
+ GG_UINT64_C(0x770123456789ABE));
+
+ QuicFrames frames;
+ frames.push_back(QuicFrame(&ack_frame));
+
+ unsigned char packet[] = {
+ // public flags (8 byte connection_id)
+ 0x3C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet sequence number
+ 0xA8, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // private flags (entropy)
+ 0x01,
+
+ // frame type (ack frame)
+ // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
+ 0x6C,
+ // entropy hash of all received packets.
+ 0x43,
+ // largest observed packet sequence number
+ 0xBF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // Zero delta time.
+ 0x0, 0x0,
+ // num missing packet ranges
+ 0x01,
+ // missing packet delta
+ 0x01,
+ // 0 more missing packets in range.
+ 0x00,
+ // 0 revived packets.
+ 0x00,
+ };
+
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
+ ASSERT_TRUE(data != NULL);
test::CompareCharArraysWithHexError("constructed packet",
data->data(), data->length(),
}
TEST_P(QuicFramerTest, BuildAckFramePacket) {
+ if (version_ <= QUIC_VERSION_22) {
+ return;
+ }
QuicPacketHeader header;
header.public_header.connection_id = GG_UINT64_C(0xFEDCBA9876543210);
header.public_header.reset_flag = false;
0x34, 0x12,
// Zero delta time.
0x0, 0x0,
+ // num received packets.
+ 0x00,
// num missing packet ranges
0x01,
// missing packet delta
// TODO(jri): Add test for tuncated packets in which the original ack frame had
// revived packets. (In both the large and small packet cases below).
+
+TEST_P(QuicFramerTest, BuildTruncatedAckFrameLargePacketv22) {
+ if (version_ > QUIC_VERSION_22) {
+ return;
+ }
+ QuicPacketHeader header;
+ header.public_header.connection_id = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.reset_flag = false;
+ header.public_header.version_flag = false;
+ header.fec_flag = false;
+ header.entropy_flag = true;
+ header.packet_sequence_number = GG_UINT64_C(0x770123456789AA8);
+ header.fec_group = 0;
+
+ QuicAckFrame ack_frame;
+ // This entropy hash is different from what shows up in the packet below,
+ // since entropy is recomputed by the framer on ack truncation (by
+ // TestEntropyCalculator for this test.)
+ ack_frame.entropy_hash = 0x43;
+ ack_frame.largest_observed = 2 * 300;
+ ack_frame.delta_time_largest_observed = QuicTime::Delta::Zero();
+ for (size_t i = 1; i < 2 * 300; i += 2) {
+ ack_frame.missing_packets.insert(i);
+ }
+
+ QuicFrames frames;
+ frames.push_back(QuicFrame(&ack_frame));
+
+ unsigned char packet[] = {
+ // public flags (8 byte connection_id)
+ 0x3C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet sequence number
+ 0xA8, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // private flags (entropy)
+ 0x01,
+
+ // frame type (ack frame)
+ // (has nacks, is truncated, 2 byte largest observed, 1 byte delta)
+ 0x74,
+ // entropy hash of all received packets, set to 1 by TestEntropyCalculator
+ // since ack is truncated.
+ 0x01,
+ // 2-byte largest observed packet sequence number.
+ // Expected to be 510 (0x1FE), since only 255 nack ranges can fit.
+ 0xFE, 0x01,
+ // Zero delta time.
+ 0x0, 0x0,
+ // num missing packet ranges (limited to 255 by size of this field).
+ 0xFF,
+ // {missing packet delta, further missing packets in range}
+ // 6 nack ranges x 42 + 3 nack ranges
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+
+ // 0 revived packets.
+ 0x00,
+ };
+
+ scoped_ptr<QuicPacket> data(
+ framer_.BuildDataPacket(header, frames, kMaxPacketSize).packet);
+ ASSERT_TRUE(data != NULL);
+
+ test::CompareCharArraysWithHexError("constructed packet",
+ data->data(), data->length(),
+ AsChars(packet), arraysize(packet));
+}
+
TEST_P(QuicFramerTest, BuildTruncatedAckFrameLargePacket) {
+ if (version_ <= QUIC_VERSION_22) {
+ return;
+ }
QuicPacketHeader header;
header.public_header.connection_id = GG_UINT64_C(0xFEDCBA9876543210);
header.public_header.reset_flag = false;
}
+TEST_P(QuicFramerTest, BuildTruncatedAckFrameSmallPacketv22) {
+ if (version_ > QUIC_VERSION_22) {
+ return;
+ }
+ QuicPacketHeader header;
+ header.public_header.connection_id = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.reset_flag = false;
+ header.public_header.version_flag = false;
+ header.fec_flag = false;
+ header.entropy_flag = true;
+ header.packet_sequence_number = GG_UINT64_C(0x770123456789AA8);
+ header.fec_group = 0;
+
+ QuicAckFrame ack_frame;
+ // This entropy hash is different from what shows up in the packet below,
+ // since entropy is recomputed by the framer on ack truncation (by
+ // TestEntropyCalculator for this test.)
+ ack_frame.entropy_hash = 0x43;
+ ack_frame.largest_observed = 2 * 300;
+ ack_frame.delta_time_largest_observed = QuicTime::Delta::Zero();
+ for (size_t i = 1; i < 2 * 300; i += 2) {
+ ack_frame.missing_packets.insert(i);
+ }
+
+ QuicFrames frames;
+ frames.push_back(QuicFrame(&ack_frame));
+
+ unsigned char packet[] = {
+ // public flags (8 byte connection_id)
+ 0x3C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet sequence number
+ 0xA8, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // private flags (entropy)
+ 0x01,
+
+ // frame type (ack frame)
+ // (has nacks, is truncated, 2 byte largest observed, 1 byte delta)
+ 0x74,
+ // entropy hash of all received packets, set to 1 by TestEntropyCalculator
+ // since ack is truncated.
+ 0x01,
+ // 2-byte largest observed packet sequence number.
+ // Expected to be 12 (0x0C), since only 6 nack ranges can fit.
+ 0x0C, 0x00,
+ // Zero delta time.
+ 0x0, 0x0,
+ // num missing packet ranges (limited to 6 by packet size of 37).
+ 0x06,
+ // {missing packet delta, further missing packets in range}
+ // 6 nack ranges
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ // 0 revived packets.
+ 0x00,
+ };
+
+ scoped_ptr<QuicPacket> data(
+ framer_.BuildDataPacket(header, frames, 37u).packet);
+ ASSERT_TRUE(data != NULL);
+ // Expect 1 byte unused since at least 2 bytes are needed to fit more nacks.
+ EXPECT_EQ(36u, data->length());
+ test::CompareCharArraysWithHexError("constructed packet",
+ data->data(), data->length(),
+ AsChars(packet), arraysize(packet));
+}
+
TEST_P(QuicFramerTest, BuildTruncatedAckFrameSmallPacket) {
+ if (version_ <= QUIC_VERSION_22) {
+ return;
+ }
QuicPacketHeader header;
header.public_header.connection_id = GG_UINT64_C(0xFEDCBA9876543210);
header.public_header.reset_flag = false;
QuicCongestionFeedbackFrame congestion_feedback_frame;
congestion_feedback_frame.type =
- static_cast<CongestionFeedbackType>(kTimestamp + 1);
+ static_cast<CongestionFeedbackType>(kTCP + 1);
QuicFrames frames;
frames.push_back(QuicFrame(&congestion_feedback_frame));
EXPECT_EQ(509u, *last_missing_iter);
}
+TEST_P(QuicFramerTest, AckTruncationSmallPacketv22) {
+ if (version_ > QUIC_VERSION_22) {
+ return;
+ }
+ QuicPacketHeader header;
+ header.public_header.connection_id = GG_UINT64_C(0xFEDCBA9876543210);
+ header.public_header.reset_flag = false;
+ header.public_header.version_flag = false;
+ header.fec_flag = false;
+ header.entropy_flag = false;
+ header.packet_sequence_number = GG_UINT64_C(0x123456789ABC);
+ header.fec_group = 0;
+
+ // Create a packet with just the ack.
+ QuicAckFrame ack_frame = MakeAckFrameWithNackRanges(300, 0u);
+ QuicFrame frame;
+ frame.type = ACK_FRAME;
+ frame.ack_frame = &ack_frame;
+ QuicFrames frames;
+ frames.push_back(frame);
+
+ // Build an ack packet with truncation due to limit in number of nack ranges.
+ scoped_ptr<QuicPacket> raw_ack_packet(
+ framer_.BuildDataPacket(header, frames, 500).packet);
+ ASSERT_TRUE(raw_ack_packet != NULL);
+ scoped_ptr<QuicEncryptedPacket> ack_packet(
+ framer_.EncryptPacket(ENCRYPTION_NONE, header.packet_sequence_number,
+ *raw_ack_packet));
+ // Now make sure we can turn our ack packet back into an ack frame.
+ ASSERT_TRUE(framer_.ProcessPacket(*ack_packet));
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ QuicAckFrame& processed_ack_frame = *visitor_.ack_frames_[0];
+ EXPECT_TRUE(processed_ack_frame.is_truncated);
+ EXPECT_EQ(476u, processed_ack_frame.largest_observed);
+ ASSERT_EQ(238u, processed_ack_frame.missing_packets.size());
+ SequenceNumberSet::const_iterator missing_iter =
+ processed_ack_frame.missing_packets.begin();
+ EXPECT_EQ(1u, *missing_iter);
+ SequenceNumberSet::const_reverse_iterator last_missing_iter =
+ processed_ack_frame.missing_packets.rbegin();
+ EXPECT_EQ(475u, *last_missing_iter);
+}
+
+
TEST_P(QuicFramerTest, AckTruncationSmallPacket) {
+ if (version_ <= QUIC_VERSION_22) {
+ return;
+ }
QuicPacketHeader header;
header.public_header.connection_id = GG_UINT64_C(0xFEDCBA9876543210);
header.public_header.reset_flag = false;