X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fnet%2Fquic%2Fquic_framer_test.cc;h=2c3d2749d3b59bacc2e2942f73fc40a86ddac639;hb=3545e9f2671f595d2a2f3ee75ca0393b01e35ef6;hp=d14e673f85e1fb4c93d4a7cbb33a10af82f70556;hpb=7d210d4c7e9ba36e635eabc5b5780495f8a63292;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/net/quic/quic_framer_test.cc b/src/net/quic/quic_framer_test.cc index d14e673..2c3d274 100644 --- a/src/net/quic/quic_framer_test.cc +++ b/src/net/quic/quic_framer_test.cc @@ -460,7 +460,7 @@ class QuicFramerTest : public ::testing::TestWithParam { 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) { @@ -682,7 +682,7 @@ TEST_P(QuicFramerTest, PacketHeader) { 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); @@ -735,7 +735,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith4ByteConnectionId) { 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); @@ -791,7 +791,7 @@ TEST_P(QuicFramerTest, PacketHeader1ByteConnectionId) { 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); @@ -846,7 +846,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) { 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); @@ -903,7 +903,7 @@ TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) { 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); @@ -958,7 +958,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith4ByteSequenceNumber) { 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); @@ -1013,7 +1013,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith2ByteSequenceNumber) { 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); @@ -1068,7 +1068,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith1ByteSequenceNumber) { 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); @@ -1307,7 +1307,7 @@ TEST_P(QuicFramerTest, StreamFrame) { visitor_.stream_frames_[0]->offset); CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]); - // Now test framing boundaries + // Now test framing boundaries. CheckStreamFrameBoundaries(packet, kQuicMaxStreamIdSize, !kIncludeVersion); } @@ -1355,7 +1355,7 @@ TEST_P(QuicFramerTest, StreamFrame3ByteStreamId) { 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); } @@ -1404,7 +1404,7 @@ TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) { 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); } @@ -1453,7 +1453,7 @@ TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) { 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); } @@ -1506,7 +1506,7 @@ TEST_P(QuicFramerTest, StreamFrameWithVersion) { visitor_.stream_frames_[0]->offset); CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]); - // Now test framing boundaries + // Now test framing boundaries. CheckStreamFrameBoundaries(packet, kQuicMaxStreamIdSize, kIncludeVersion); } @@ -1682,7 +1682,445 @@ TEST_P(QuicFramerTest, StreamFrameInFecGroup) { 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, @@ -1705,6 +2143,8 @@ TEST_P(QuicFramerTest, AckFrame) { 0x34, 0x12, // Zero delta time. 0x0, 0x0, + // num received packets. + 0x00, // num missing packets 0x01, // missing packet delta @@ -1712,6 +2152,11 @@ TEST_P(QuicFramerTest, AckFrame) { // 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, }; @@ -1737,33 +2182,43 @@ TEST_P(QuicFramerTest, AckFrame) { 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, @@ -1773,7 +2228,10 @@ TEST_P(QuicFramerTest, AckFrame) { } } -TEST_P(QuicFramerTest, AckFrameRevivedPackets) { +TEST_P(QuicFramerTest, AckFrameRevivedPacketsv22) { + if (version_ > QUIC_VERSION_22) { + return; + } unsigned char packet[] = { // public flags (8 byte connection_id) 0x3C, @@ -1807,6 +2265,8 @@ TEST_P(QuicFramerTest, AckFrameRevivedPackets) { // Revived packet sequence number. 0xBE, 0x9A, 0x78, 0x56, 0x34, 0x12, + // Number of revived packets. + 0x00, }; QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false); @@ -1841,7 +2301,7 @@ TEST_P(QuicFramerTest, AckFrameRevivedPackets) { 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) { @@ -1873,7 +2333,63 @@ TEST_P(QuicFramerTest, AckFrameRevivedPackets) { } } +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 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, @@ -1896,6 +2412,8 @@ TEST_P(QuicFramerTest, AckFrameNoNacks) { 0x34, 0x12, // Zero delta time. 0x0, 0x0, + // Number of received packets. + 0x00, }; QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false); @@ -1923,7 +2441,83 @@ TEST_P(QuicFramerTest, AckFrameNoNacks) { 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 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, @@ -1946,6 +2540,8 @@ TEST_P(QuicFramerTest, AckFrame500Nacks) { 0x34, 0x12, // Zero delta time. 0x0, 0x0, + // No received packets. + 0x00, // num missing packet ranges 0x02, // missing packet delta @@ -2028,7 +2624,7 @@ TEST_P(QuicFramerTest, CongestionFeedbackFrameTCP) { 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) { @@ -2170,7 +2766,7 @@ TEST_P(QuicFramerTest, RstStreamFrameQuic) { 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; @@ -2234,7 +2830,7 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) { 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; @@ -2292,7 +2888,7 @@ TEST_P(QuicFramerTest, GoAwayFrame) { 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; @@ -2347,7 +2943,7 @@ TEST_P(QuicFramerTest, WindowUpdateFrame) { 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; @@ -2394,7 +2990,7 @@ TEST_P(QuicFramerTest, BlockedFrame) { 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."; @@ -2481,7 +3077,7 @@ TEST_P(QuicFramerTest, PublicResetPacket) { 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; @@ -2587,7 +3183,7 @@ TEST_P(QuicFramerTest, PublicResetPacketWithClientAddress) { 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; @@ -3042,10 +3638,73 @@ TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) { 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(), }; - QuicVersionVector versions; - versions.push_back(GetParam()); - scoped_ptr data( - framer_.BuildVersionNegotiationPacket(header, versions)); + QuicVersionVector versions; + versions.push_back(GetParam()); + scoped_ptr 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 data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != NULL); test::CompareCharArraysWithHexError("constructed packet", data->data(), data->length(), @@ -3053,6 +3712,9 @@ TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) { } 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; @@ -3094,6 +3756,8 @@ TEST_P(QuicFramerTest, BuildAckFramePacket) { 0x34, 0x12, // Zero delta time. 0x0, 0x0, + // num received packets. + 0x00, // num missing packet ranges 0x01, // missing packet delta @@ -3114,7 +3778,126 @@ TEST_P(QuicFramerTest, BuildAckFramePacket) { // 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 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; @@ -3227,7 +4010,79 @@ TEST_P(QuicFramerTest, BuildTruncatedAckFrameLargePacket) { } +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 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; @@ -3396,7 +4251,7 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketInvalidFeedback) { QuicCongestionFeedbackFrame congestion_feedback_frame; congestion_feedback_frame.type = - static_cast(kTimestamp + 1); + static_cast(kTCP + 1); QuicFrames frames; frames.push_back(QuicFrame(&congestion_feedback_frame)); @@ -3953,7 +4808,54 @@ TEST_P(QuicFramerTest, AckTruncationLargePacket) { 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 raw_ack_packet( + framer_.BuildDataPacket(header, frames, 500).packet); + ASSERT_TRUE(raw_ack_packet != NULL); + scoped_ptr 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;