diff options
Diffstat (limited to 'chromium/net/quic/quic_framer_test.cc')
-rw-r--r-- | chromium/net/quic/quic_framer_test.cc | 2172 |
1 files changed, 1812 insertions, 360 deletions
diff --git a/chromium/net/quic/quic_framer_test.cc b/chromium/net/quic/quic_framer_test.cc index eef4a5894c1..fd206e18620 100644 --- a/chromium/net/quic/quic_framer_test.cc +++ b/chromium/net/quic/quic_framer_test.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "net/quic/quic_framer.h" + #include <algorithm> #include <map> #include <string> @@ -14,11 +16,11 @@ #include "base/stl_util.h" #include "net/quic/crypto/quic_decrypter.h" #include "net/quic/crypto/quic_encrypter.h" -#include "net/quic/quic_framer.h" #include "net/quic/quic_protocol.h" #include "net/quic/quic_utils.h" #include "net/quic/test_tools/quic_framer_peer.h" #include "net/quic/test_tools/quic_test_utils.h" +#include "net/test/gtest_util.h" using base::hash_set; using base::StringPiece; @@ -37,46 +39,54 @@ namespace test { const QuicPacketSequenceNumber kEpoch = GG_UINT64_C(1) << 48; const QuicPacketSequenceNumber kMask = kEpoch - 1; -// Index into the guid offset in the header. -const size_t kGuidOffset = kPublicFlagsSize; +// Index into the connection_id offset in the header. +const size_t kConnectionIdOffset = kPublicFlagsSize; // Index into the version string in the header. (if present). -const size_t kVersionOffset = kGuidOffset + PACKET_8BYTE_GUID; +const size_t kVersionOffset = kConnectionIdOffset + PACKET_8BYTE_CONNECTION_ID; + +// Size in bytes of the stream frame fields for an arbitrary StreamID and +// offset and the last frame in a packet. +size_t GetMinStreamFrameSize(QuicVersion version) { + return kQuicFrameTypeSize + kQuicMaxStreamIdSize + kQuicMaxStreamOffsetSize; +} // Index into the sequence number offset in the header. -size_t GetSequenceNumberOffset(QuicGuidLength guid_length, +size_t GetSequenceNumberOffset(QuicConnectionIdLength connection_id_length, bool include_version) { - return kGuidOffset + guid_length + + return kConnectionIdOffset + connection_id_length + (include_version ? kQuicVersionSize : 0); } size_t GetSequenceNumberOffset(bool include_version) { - return GetSequenceNumberOffset(PACKET_8BYTE_GUID, include_version); + return GetSequenceNumberOffset(PACKET_8BYTE_CONNECTION_ID, include_version); } // Index into the private flags offset in the data packet header. -size_t GetPrivateFlagsOffset(QuicGuidLength guid_length, bool include_version) { - return GetSequenceNumberOffset(guid_length, include_version) + +size_t GetPrivateFlagsOffset(QuicConnectionIdLength connection_id_length, + bool include_version) { + return GetSequenceNumberOffset(connection_id_length, include_version) + PACKET_6BYTE_SEQUENCE_NUMBER; } size_t GetPrivateFlagsOffset(bool include_version) { - return GetPrivateFlagsOffset(PACKET_8BYTE_GUID, include_version); + return GetPrivateFlagsOffset(PACKET_8BYTE_CONNECTION_ID, include_version); } size_t GetPrivateFlagsOffset(bool include_version, QuicSequenceNumberLength sequence_number_length) { - return GetSequenceNumberOffset(PACKET_8BYTE_GUID, include_version) + + return GetSequenceNumberOffset(PACKET_8BYTE_CONNECTION_ID, include_version) + sequence_number_length; } // Index into the fec group offset in the header. -size_t GetFecGroupOffset(QuicGuidLength guid_length, bool include_version) { - return GetPrivateFlagsOffset(guid_length, include_version) + +size_t GetFecGroupOffset(QuicConnectionIdLength connection_id_length, + bool include_version) { + return GetPrivateFlagsOffset(connection_id_length, include_version) + kPrivateFlagsSize; } size_t GetFecGroupOffset(bool include_version) { - return GetPrivateFlagsOffset(PACKET_8BYTE_GUID, include_version) + + return GetPrivateFlagsOffset(PACKET_8BYTE_CONNECTION_ID, include_version) + kPrivateFlagsSize; } @@ -86,14 +96,10 @@ size_t GetFecGroupOffset(bool include_version, kPrivateFlagsSize; } -// Index into the nonce proof of the public reset packet. -// Public resets always have full guids. -const size_t kPublicResetPacketNonceProofOffset = - kGuidOffset + PACKET_8BYTE_GUID; - -// Index into the rejected sequence number of the public reset packet. -const size_t kPublicResetPacketRejectedSequenceNumberOffset = - kPublicResetPacketNonceProofOffset + kPublicResetNonceSize; +// Index into the message tag of the public reset packet. +// Public resets always have full connection_ids. +const size_t kPublicResetPacketMessageTagOffset = + kConnectionIdOffset + PACKET_8BYTE_CONNECTION_ID; class TestEncrypter : public QuicEncrypter { public: @@ -188,20 +194,23 @@ class TestQuicVisitor : public ::net::QuicFramerVisitorInterface { fec_count_(0), complete_packets_(0), revived_packets_(0), - accept_packet_(true) { + accept_packet_(true), + accept_public_header_(true) { } virtual ~TestQuicVisitor() { STLDeleteElements(&stream_frames_); STLDeleteElements(&ack_frames_); STLDeleteElements(&congestion_feedback_frames_); + STLDeleteElements(&stop_waiting_frames_); + STLDeleteElements(&ping_frames_); STLDeleteElements(&fec_data_); } virtual void OnError(QuicFramer* f) OVERRIDE { - DLOG(INFO) << "QuicFramer Error: " << QuicUtils::ErrorToString(f->error()) - << " (" << f->error() << ")"; - error_count_++; + DVLOG(1) << "QuicFramer Error: " << QuicUtils::ErrorToString(f->error()) + << " (" << f->error() << ")"; + ++error_count_; } virtual void OnPacket() OVERRIDE {} @@ -217,19 +226,19 @@ class TestQuicVisitor : public ::net::QuicFramerVisitorInterface { } virtual void OnRevivedPacket() OVERRIDE { - revived_packets_++; + ++revived_packets_; } virtual bool OnProtocolVersionMismatch(QuicVersion version) OVERRIDE { - DLOG(INFO) << "QuicFramer Version Mismatch, version: " << version; - version_mismatch_++; + DVLOG(1) << "QuicFramer Version Mismatch, version: " << version; + ++version_mismatch_; return true; } - virtual bool OnPacketHeader(const QuicPacketHeader& header) OVERRIDE { - packet_count_++; - header_.reset(new QuicPacketHeader(header)); - return accept_packet_; + virtual bool OnUnauthenticatedPublicHeader( + const QuicPacketPublicHeader& header) OVERRIDE { + public_header_.reset(new QuicPacketPublicHeader(header)); + return accept_public_header_; } virtual bool OnUnauthenticatedHeader( @@ -237,8 +246,16 @@ class TestQuicVisitor : public ::net::QuicFramerVisitorInterface { return true; } + virtual void OnDecryptedPacket(EncryptionLevel level) OVERRIDE {} + + virtual bool OnPacketHeader(const QuicPacketHeader& header) OVERRIDE { + ++packet_count_; + header_.reset(new QuicPacketHeader(header)); + return accept_packet_; + } + virtual bool OnStreamFrame(const QuicStreamFrame& frame) OVERRIDE { - frame_count_++; + ++frame_count_; stream_frames_.push_back(new QuicStreamFrame(frame)); return true; } @@ -248,26 +265,38 @@ class TestQuicVisitor : public ::net::QuicFramerVisitorInterface { } virtual bool OnAckFrame(const QuicAckFrame& frame) OVERRIDE { - frame_count_++; + ++frame_count_; ack_frames_.push_back(new QuicAckFrame(frame)); return true; } virtual bool OnCongestionFeedbackFrame( const QuicCongestionFeedbackFrame& frame) OVERRIDE { - frame_count_++; + ++frame_count_; congestion_feedback_frames_.push_back( new QuicCongestionFeedbackFrame(frame)); return true; } + virtual bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) OVERRIDE { + ++frame_count_; + stop_waiting_frames_.push_back(new QuicStopWaitingFrame(frame)); + return true; + } + + virtual bool OnPingFrame(const QuicPingFrame& frame) OVERRIDE { + ++frame_count_; + ping_frames_.push_back(new QuicPingFrame(frame)); + return true; + } + virtual void OnFecData(const QuicFecData& fec) OVERRIDE { - fec_count_++; + ++fec_count_; fec_data_.push_back(new QuicFecData(fec)); } virtual void OnPacketComplete() OVERRIDE { - complete_packets_++; + ++complete_packets_; } virtual bool OnRstStreamFrame(const QuicRstStreamFrame& frame) OVERRIDE { @@ -286,6 +315,17 @@ class TestQuicVisitor : public ::net::QuicFramerVisitorInterface { return true; } + virtual bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) + OVERRIDE { + window_update_frame_ = frame; + return true; + } + + virtual bool OnBlockedFrame(const QuicBlockedFrame& frame) OVERRIDE { + blocked_frame_ = frame; + return true; + } + // Counters from the visitor_ callbacks. int error_count_; int version_mismatch_; @@ -295,18 +335,24 @@ class TestQuicVisitor : public ::net::QuicFramerVisitorInterface { int complete_packets_; int revived_packets_; bool accept_packet_; + bool accept_public_header_; scoped_ptr<QuicPacketHeader> header_; + scoped_ptr<QuicPacketPublicHeader> public_header_; scoped_ptr<QuicPublicResetPacket> public_reset_packet_; scoped_ptr<QuicVersionNegotiationPacket> version_negotiation_packet_; vector<QuicStreamFrame*> stream_frames_; vector<QuicAckFrame*> ack_frames_; vector<QuicCongestionFeedbackFrame*> congestion_feedback_frames_; + vector<QuicStopWaitingFrame*> stop_waiting_frames_; + vector<QuicPingFrame*> ping_frames_; vector<QuicFecData*> fec_data_; string fec_protected_payload_; QuicRstStreamFrame rst_stream_frame_; QuicConnectionCloseFrame connection_close_frame_; QuicGoAwayFrame goaway_frame_; + QuicWindowUpdateFrame window_update_frame_; + QuicBlockedFrame blocked_frame_; }; class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> { @@ -318,7 +364,7 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> { framer_(QuicSupportedVersions(), start_, true) { version_ = GetParam(); framer_.set_version(version_); - framer_.SetDecrypter(decrypter_); + framer_.SetDecrypter(decrypter_, ENCRYPTION_NONE); framer_.SetEncrypter(ENCRYPTION_NONE, encrypter_); framer_.set_visitor(&visitor_); framer_.set_received_entropy_calculator(&entropy_calculator_); @@ -369,18 +415,18 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> { return false; } if (QuicFramer::GetAssociatedDataFromEncryptedPacket( - encrypted, PACKET_8BYTE_GUID, + encrypted, PACKET_8BYTE_CONNECTION_ID, includes_version, PACKET_6BYTE_SEQUENCE_NUMBER) != decrypter_->associated_data_) { LOG(ERROR) << "Decrypted incorrect associated data. expected " << QuicFramer::GetAssociatedDataFromEncryptedPacket( - encrypted, PACKET_8BYTE_GUID, + encrypted, PACKET_8BYTE_CONNECTION_ID, includes_version, PACKET_6BYTE_SEQUENCE_NUMBER) << " actual: " << decrypter_->associated_data_; return false; } StringPiece ciphertext(encrypted.AsStringPiece().substr( - GetStartOfEncryptedData(PACKET_8BYTE_GUID, includes_version, + GetStartOfEncryptedData(PACKET_8BYTE_CONNECTION_ID, includes_version, PACKET_6BYTE_SEQUENCE_NUMBER))); if (ciphertext != decrypter_->ciphertext_) { LOG(ERROR) << "Decrypted incorrect ciphertext data. expected " @@ -428,7 +474,7 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> { } CheckProcessingFails( packet, - i + GetPacketHeaderSize(PACKET_8BYTE_GUID, include_version, + i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, include_version, PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP), expected_error, QUIC_INVALID_STREAM_DATA); @@ -448,6 +494,11 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> { << " wire_sequence_number: " << wire_sequence_number; } + QuicPacket* BuildDataPacket(const QuicPacketHeader& header, + const QuicFrames& frames) { + return BuildUnsizedDataPacket(&framer_, header, frames).packet; + } + test::TestEncrypter* encrypter_; test::TestDecrypter* decrypter_; QuicVersion version_; @@ -572,9 +623,9 @@ TEST_P(QuicFramerTest, EmptyPacket) { TEST_P(QuicFramerTest, LargePacket) { unsigned char packet[kMaxPacketSize + 1] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -585,10 +636,10 @@ TEST_P(QuicFramerTest, LargePacket) { }; memset(packet + GetPacketHeaderSize( - PACKET_8BYTE_GUID, !kIncludeVersion, + PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP), 0, kMaxPacketSize - GetPacketHeaderSize( - PACKET_8BYTE_GUID, !kIncludeVersion, + PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP) + 1); QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false); @@ -597,16 +648,16 @@ TEST_P(QuicFramerTest, LargePacket) { ASSERT_TRUE(visitor_.header_.get()); // Make sure we've parsed the packet header, so we can send an error. EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210), - visitor_.header_->public_header.guid); + visitor_.header_->public_header.connection_id); // Make sure the correct error is propagated. EXPECT_EQ(QUIC_PACKET_TOO_LARGE, framer_.error()); } TEST_P(QuicFramerTest, PacketHeader) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -621,7 +672,7 @@ TEST_P(QuicFramerTest, PacketHeader) { EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error()); ASSERT_TRUE(visitor_.header_.get()); EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210), - visitor_.header_->public_header.guid); + visitor_.header_->public_header.connection_id); EXPECT_FALSE(visitor_.header_->public_header.reset_flag); EXPECT_FALSE(visitor_.header_->public_header.version_flag); EXPECT_FALSE(visitor_.header_->fec_flag); @@ -634,14 +685,14 @@ TEST_P(QuicFramerTest, PacketHeader) { // Now test framing boundaries for (size_t i = 0; - i < GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, + i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); ++i) { string expected_error; - if (i < kGuidOffset) { + if (i < kConnectionIdOffset) { expected_error = "Unable to read public flags."; } else if (i < GetSequenceNumberOffset(!kIncludeVersion)) { - expected_error = "Unable to read GUID."; + expected_error = "Unable to read ConnectionId."; } else if (i < GetPrivateFlagsOffset(!kIncludeVersion)) { expected_error = "Unable to read sequence number."; } else if (i < GetFecGroupOffset(!kIncludeVersion)) { @@ -653,14 +704,14 @@ TEST_P(QuicFramerTest, PacketHeader) { } } -TEST_P(QuicFramerTest, PacketHeaderWith4ByteGuid) { - QuicFramerPeer::SetLastSerializedGuid(&framer_, - GG_UINT64_C(0xFEDCBA9876543210)); +TEST_P(QuicFramerTest, PacketHeaderWith4ByteConnectionId) { + QuicFramerPeer::SetLastSerializedConnectionId( + &framer_, GG_UINT64_C(0xFEDCBA9876543210)); unsigned char packet[] = { - // public flags (4 byte guid) + // public flags (4 byte connection_id) 0x38, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, // packet sequence number 0xBC, 0x9A, 0x78, 0x56, @@ -674,7 +725,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith4ByteGuid) { EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error()); ASSERT_TRUE(visitor_.header_.get()); EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210), - visitor_.header_->public_header.guid); + visitor_.header_->public_header.connection_id); EXPECT_FALSE(visitor_.header_->public_header.reset_flag); EXPECT_FALSE(visitor_.header_->public_header.version_flag); EXPECT_FALSE(visitor_.header_->fec_flag); @@ -687,19 +738,20 @@ TEST_P(QuicFramerTest, PacketHeaderWith4ByteGuid) { // Now test framing boundaries for (size_t i = 0; - i < GetPacketHeaderSize(PACKET_4BYTE_GUID, !kIncludeVersion, + i < GetPacketHeaderSize(PACKET_4BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); ++i) { string expected_error; - if (i < kGuidOffset) { + if (i < kConnectionIdOffset) { expected_error = "Unable to read public flags."; - } else if (i < GetSequenceNumberOffset(PACKET_4BYTE_GUID, + } else if (i < GetSequenceNumberOffset(PACKET_4BYTE_CONNECTION_ID, !kIncludeVersion)) { - expected_error = "Unable to read GUID."; - } else if (i < GetPrivateFlagsOffset(PACKET_4BYTE_GUID, + expected_error = "Unable to read ConnectionId."; + } else if (i < GetPrivateFlagsOffset(PACKET_4BYTE_CONNECTION_ID, !kIncludeVersion)) { expected_error = "Unable to read sequence number."; - } else if (i < GetFecGroupOffset(PACKET_4BYTE_GUID, !kIncludeVersion)) { + } else if (i < GetFecGroupOffset(PACKET_4BYTE_CONNECTION_ID, + !kIncludeVersion)) { expected_error = "Unable to read private flags."; } else { expected_error = "Unable to read first fec protected packet offset."; @@ -708,14 +760,14 @@ TEST_P(QuicFramerTest, PacketHeaderWith4ByteGuid) { } } -TEST_P(QuicFramerTest, PacketHeader1ByteGuid) { - QuicFramerPeer::SetLastSerializedGuid(&framer_, - GG_UINT64_C(0xFEDCBA9876543210)); +TEST_P(QuicFramerTest, PacketHeader1ByteConnectionId) { + QuicFramerPeer::SetLastSerializedConnectionId( + &framer_, GG_UINT64_C(0xFEDCBA9876543210)); unsigned char packet[] = { - // public flags (1 byte guid) + // public flags (1 byte connection_id) 0x34, - // guid + // connection_id 0x10, // packet sequence number 0xBC, 0x9A, 0x78, 0x56, @@ -729,7 +781,7 @@ TEST_P(QuicFramerTest, PacketHeader1ByteGuid) { EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error()); ASSERT_TRUE(visitor_.header_.get()); EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210), - visitor_.header_->public_header.guid); + visitor_.header_->public_header.connection_id); EXPECT_FALSE(visitor_.header_->public_header.reset_flag); EXPECT_FALSE(visitor_.header_->public_header.version_flag); EXPECT_FALSE(visitor_.header_->fec_flag); @@ -742,18 +794,20 @@ TEST_P(QuicFramerTest, PacketHeader1ByteGuid) { // Now test framing boundaries for (size_t i = 0; - i < GetPacketHeaderSize(PACKET_1BYTE_GUID, !kIncludeVersion, + i < GetPacketHeaderSize(PACKET_1BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); ++i) { string expected_error; - if (i < kGuidOffset) { + if (i < kConnectionIdOffset) { expected_error = "Unable to read public flags."; - } else if (i < GetSequenceNumberOffset(PACKET_1BYTE_GUID, + } else if (i < GetSequenceNumberOffset(PACKET_1BYTE_CONNECTION_ID, !kIncludeVersion)) { - expected_error = "Unable to read GUID."; - } else if (i < GetPrivateFlagsOffset(PACKET_1BYTE_GUID, !kIncludeVersion)) { + expected_error = "Unable to read ConnectionId."; + } else if (i < GetPrivateFlagsOffset(PACKET_1BYTE_CONNECTION_ID, + !kIncludeVersion)) { expected_error = "Unable to read sequence number."; - } else if (i < GetFecGroupOffset(PACKET_1BYTE_GUID, !kIncludeVersion)) { + } else if (i < GetFecGroupOffset(PACKET_1BYTE_CONNECTION_ID, + !kIncludeVersion)) { expected_error = "Unable to read private flags."; } else { expected_error = "Unable to read first fec protected packet offset."; @@ -762,14 +816,14 @@ TEST_P(QuicFramerTest, PacketHeader1ByteGuid) { } } -TEST_P(QuicFramerTest, PacketHeaderWith0ByteGuid) { - QuicFramerPeer::SetLastSerializedGuid(&framer_, - GG_UINT64_C(0xFEDCBA9876543210)); +TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) { + QuicFramerPeer::SetLastSerializedConnectionId( + &framer_, GG_UINT64_C(0xFEDCBA9876543210)); unsigned char packet[] = { - // public flags (0 byte guid) + // public flags (0 byte connection_id) 0x30, - // guid + // connection_id // packet sequence number 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, @@ -782,7 +836,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith0ByteGuid) { EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error()); ASSERT_TRUE(visitor_.header_.get()); EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210), - visitor_.header_->public_header.guid); + visitor_.header_->public_header.connection_id); EXPECT_FALSE(visitor_.header_->public_header.reset_flag); EXPECT_FALSE(visitor_.header_->public_header.version_flag); EXPECT_FALSE(visitor_.header_->fec_flag); @@ -795,18 +849,20 @@ TEST_P(QuicFramerTest, PacketHeaderWith0ByteGuid) { // Now test framing boundaries for (size_t i = 0; - i < GetPacketHeaderSize(PACKET_0BYTE_GUID, !kIncludeVersion, + i < GetPacketHeaderSize(PACKET_0BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); ++i) { string expected_error; - if (i < kGuidOffset) { + if (i < kConnectionIdOffset) { expected_error = "Unable to read public flags."; - } else if (i < GetSequenceNumberOffset(PACKET_0BYTE_GUID, + } else if (i < GetSequenceNumberOffset(PACKET_0BYTE_CONNECTION_ID, !kIncludeVersion)) { - expected_error = "Unable to read GUID."; - } else if (i < GetPrivateFlagsOffset(PACKET_0BYTE_GUID, !kIncludeVersion)) { + expected_error = "Unable to read ConnectionId."; + } else if (i < GetPrivateFlagsOffset(PACKET_0BYTE_CONNECTION_ID, + !kIncludeVersion)) { expected_error = "Unable to read sequence number."; - } else if (i < GetFecGroupOffset(PACKET_0BYTE_GUID, !kIncludeVersion)) { + } else if (i < GetFecGroupOffset(PACKET_0BYTE_CONNECTION_ID, + !kIncludeVersion)) { expected_error = "Unable to read private flags."; } else { expected_error = "Unable to read first fec protected packet offset."; @@ -819,7 +875,7 @@ TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) { unsigned char packet[] = { // public flags (version) 0x3D, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // version tag @@ -836,7 +892,7 @@ TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) { EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error()); ASSERT_TRUE(visitor_.header_.get()); EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210), - visitor_.header_->public_header.guid); + visitor_.header_->public_header.connection_id); EXPECT_FALSE(visitor_.header_->public_header.reset_flag); EXPECT_TRUE(visitor_.header_->public_header.version_flag); EXPECT_EQ(GetParam(), visitor_.header_->public_header.versions[0]); @@ -850,14 +906,14 @@ TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) { // Now test framing boundaries for (size_t i = 0; - i < GetPacketHeaderSize(PACKET_8BYTE_GUID, kIncludeVersion, + i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); ++i) { string expected_error; - if (i < kGuidOffset) { + if (i < kConnectionIdOffset) { expected_error = "Unable to read public flags."; } else if (i < kVersionOffset) { - expected_error = "Unable to read GUID."; + expected_error = "Unable to read ConnectionId."; } else if (i < GetSequenceNumberOffset(kIncludeVersion)) { expected_error = "Unable to read protocol version."; } else if (i < GetPrivateFlagsOffset(kIncludeVersion)) { @@ -876,9 +932,9 @@ TEST_P(QuicFramerTest, PacketHeaderWith4ByteSequenceNumber) { GG_UINT64_C(0x123456789ABA)); unsigned char packet[] = { - // public flags (8 byte guid and 4 byte sequence number) + // public flags (8 byte connection_id and 4 byte sequence number) 0x2C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -892,7 +948,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith4ByteSequenceNumber) { EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error()); ASSERT_TRUE(visitor_.header_.get()); EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210), - visitor_.header_->public_header.guid); + visitor_.header_->public_header.connection_id); EXPECT_FALSE(visitor_.header_->public_header.reset_flag); EXPECT_FALSE(visitor_.header_->public_header.version_flag); EXPECT_FALSE(visitor_.header_->fec_flag); @@ -905,14 +961,14 @@ TEST_P(QuicFramerTest, PacketHeaderWith4ByteSequenceNumber) { // Now test framing boundaries for (size_t i = 0; - i < GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, + i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_4BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); ++i) { string expected_error; - if (i < kGuidOffset) { + if (i < kConnectionIdOffset) { expected_error = "Unable to read public flags."; } else if (i < GetSequenceNumberOffset(!kIncludeVersion)) { - expected_error = "Unable to read GUID."; + expected_error = "Unable to read ConnectionId."; } else if (i < GetPrivateFlagsOffset(!kIncludeVersion, PACKET_4BYTE_SEQUENCE_NUMBER)) { expected_error = "Unable to read sequence number."; @@ -931,9 +987,9 @@ TEST_P(QuicFramerTest, PacketHeaderWith2ByteSequenceNumber) { GG_UINT64_C(0x123456789ABA)); unsigned char packet[] = { - // public flags (8 byte guid and 2 byte sequence number) + // public flags (8 byte connection_id and 2 byte sequence number) 0x1C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -947,7 +1003,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith2ByteSequenceNumber) { EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error()); ASSERT_TRUE(visitor_.header_.get()); EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210), - visitor_.header_->public_header.guid); + visitor_.header_->public_header.connection_id); EXPECT_FALSE(visitor_.header_->public_header.reset_flag); EXPECT_FALSE(visitor_.header_->public_header.version_flag); EXPECT_FALSE(visitor_.header_->fec_flag); @@ -960,14 +1016,14 @@ TEST_P(QuicFramerTest, PacketHeaderWith2ByteSequenceNumber) { // Now test framing boundaries for (size_t i = 0; - i < GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, + i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_2BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); ++i) { string expected_error; - if (i < kGuidOffset) { + if (i < kConnectionIdOffset) { expected_error = "Unable to read public flags."; } else if (i < GetSequenceNumberOffset(!kIncludeVersion)) { - expected_error = "Unable to read GUID."; + expected_error = "Unable to read ConnectionId."; } else if (i < GetPrivateFlagsOffset(!kIncludeVersion, PACKET_2BYTE_SEQUENCE_NUMBER)) { expected_error = "Unable to read sequence number."; @@ -986,9 +1042,9 @@ TEST_P(QuicFramerTest, PacketHeaderWith1ByteSequenceNumber) { GG_UINT64_C(0x123456789ABA)); unsigned char packet[] = { - // public flags (8 byte guid and 1 byte sequence number) + // public flags (8 byte connection_id and 1 byte sequence number) 0x0C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -1002,7 +1058,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith1ByteSequenceNumber) { EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error()); ASSERT_TRUE(visitor_.header_.get()); EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210), - visitor_.header_->public_header.guid); + visitor_.header_->public_header.connection_id); EXPECT_FALSE(visitor_.header_->public_header.reset_flag); EXPECT_FALSE(visitor_.header_->public_header.version_flag); EXPECT_FALSE(visitor_.header_->fec_flag); @@ -1015,14 +1071,14 @@ TEST_P(QuicFramerTest, PacketHeaderWith1ByteSequenceNumber) { // Now test framing boundaries for (size_t i = 0; - i < GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, + i < GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_1BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); ++i) { string expected_error; - if (i < kGuidOffset) { + if (i < kConnectionIdOffset) { expected_error = "Unable to read public flags."; } else if (i < GetSequenceNumberOffset(!kIncludeVersion)) { - expected_error = "Unable to read GUID."; + expected_error = "Unable to read ConnectionId."; } else if (i < GetPrivateFlagsOffset(!kIncludeVersion, PACKET_1BYTE_SEQUENCE_NUMBER)) { expected_error = "Unable to read sequence number."; @@ -1038,9 +1094,9 @@ TEST_P(QuicFramerTest, PacketHeaderWith1ByteSequenceNumber) { TEST_P(QuicFramerTest, InvalidPublicFlag) { unsigned char packet[] = { - // public flags, unknown flag at bit 6 - 0x40, - // guid + // public flags: all flags set but the public reset flag and version flag. + 0xFC, + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -1057,13 +1113,18 @@ TEST_P(QuicFramerTest, InvalidPublicFlag) { arraysize(packet), "Illegal public flags value.", QUIC_INVALID_PACKET_HEADER); + + // Now turn off validation. + framer_.set_validate_flags(false); + QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false); + EXPECT_TRUE(framer_.ProcessPacket(encrypted)); }; TEST_P(QuicFramerTest, InvalidPublicFlagWithMatchingVersions) { unsigned char packet[] = { - // public flags (8 byte guid and version flag and an unknown flag) + // public flags (8 byte connection_id and version flag and an unknown flag) 0x4D, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // version tag @@ -1086,9 +1147,9 @@ TEST_P(QuicFramerTest, InvalidPublicFlagWithMatchingVersions) { TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) { unsigned char packet[] = { - // public flags (8 byte guid, version flag and an unknown flag) + // public flags (8 byte connection_id, version flag and an unknown flag) 0x7D, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // version tag @@ -1113,9 +1174,9 @@ TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) { TEST_P(QuicFramerTest, InvalidPrivateFlag) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -1136,9 +1197,9 @@ TEST_P(QuicFramerTest, InvalidPrivateFlag) { TEST_P(QuicFramerTest, InvalidFECGroupOffset) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -1158,9 +1219,9 @@ TEST_P(QuicFramerTest, InvalidFECGroupOffset) { TEST_P(QuicFramerTest, PaddingFrame) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -1198,16 +1259,16 @@ TEST_P(QuicFramerTest, PaddingFrame) { // A packet with no frames is not acceptable. CheckProcessingFails( packet, - GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP), "Packet has no frames.", QUIC_MISSING_PAYLOAD); } TEST_P(QuicFramerTest, StreamFrame) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -1253,9 +1314,9 @@ TEST_P(QuicFramerTest, StreamFrame) { TEST_P(QuicFramerTest, StreamFrame3ByteStreamId) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -1302,9 +1363,9 @@ TEST_P(QuicFramerTest, StreamFrame3ByteStreamId) { TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -1351,9 +1412,9 @@ TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) { TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -1400,9 +1461,9 @@ TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) { TEST_P(QuicFramerTest, StreamFrameWithVersion) { unsigned char packet[] = { - // public flags (version, 8 byte guid) + // public flags (version, 8 byte connection_id) 0x3D, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // version tag @@ -1433,8 +1494,8 @@ TEST_P(QuicFramerTest, StreamFrameWithVersion) { EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); ASSERT_TRUE(visitor_.header_.get()); - EXPECT_TRUE(visitor_.header_.get()->public_header.version_flag); - EXPECT_EQ(GetParam(), visitor_.header_.get()->public_header.versions[0]); + EXPECT_TRUE(visitor_.header_->public_header.version_flag); + EXPECT_EQ(GetParam(), visitor_.header_->public_header.versions[0]); EXPECT_TRUE(CheckDecryption(encrypted, kIncludeVersion)); ASSERT_EQ(1u, visitor_.stream_frames_.size()); @@ -1454,9 +1515,9 @@ TEST_P(QuicFramerTest, RejectPacket) { visitor_.accept_packet_ = false; unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -1491,6 +1552,25 @@ TEST_P(QuicFramerTest, RejectPacket) { EXPECT_EQ(0u, visitor_.ack_frames_.size()); } +TEST_P(QuicFramerTest, RejectPublicHeader) { + visitor_.accept_public_header_ = false; + + unsigned char packet[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + }; + + QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false); + EXPECT_TRUE(framer_.ProcessPacket(encrypted)); + + EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); + ASSERT_TRUE(visitor_.public_header_.get()); + ASSERT_FALSE(visitor_.header_.get()); +} + TEST_P(QuicFramerTest, RevivedStreamFrame) { unsigned char payload[] = { // frame type (stream frame with fin) @@ -1509,7 +1589,7 @@ TEST_P(QuicFramerTest, RevivedStreamFrame) { }; QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + header.public_header.connection_id = GG_UINT64_C(0xFEDCBA9876543210); header.public_header.reset_flag = false; header.public_header.version_flag = false; header.fec_flag = true; @@ -1526,7 +1606,7 @@ TEST_P(QuicFramerTest, RevivedStreamFrame) { ASSERT_EQ(1, visitor_.revived_packets_); ASSERT_TRUE(visitor_.header_.get()); EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210), - visitor_.header_->public_header.guid); + visitor_.header_->public_header.connection_id); EXPECT_FALSE(visitor_.header_->public_header.reset_flag); EXPECT_FALSE(visitor_.header_->public_header.version_flag); EXPECT_TRUE(visitor_.header_->fec_flag); @@ -1549,9 +1629,9 @@ TEST_P(QuicFramerTest, RevivedStreamFrame) { TEST_P(QuicFramerTest, StreamFrameInFecGroup) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -1586,8 +1666,10 @@ TEST_P(QuicFramerTest, StreamFrameInFecGroup) { EXPECT_EQ(IN_FEC_GROUP, visitor_.header_->is_in_fec_group); EXPECT_EQ(GG_UINT64_C(0x341256789ABA), visitor_.header_->fec_group); - const size_t fec_offset = GetStartOfFecProtectedData( - PACKET_8BYTE_GUID, !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER); + const size_t fec_offset = + GetStartOfFecProtectedData(PACKET_8BYTE_CONNECTION_ID, + !kIncludeVersion, + PACKET_6BYTE_SEQUENCE_NUMBER); EXPECT_EQ( string(AsChars(packet) + fec_offset, arraysize(packet) - fec_offset), visitor_.fec_protected_payload_); @@ -1601,11 +1683,15 @@ TEST_P(QuicFramerTest, StreamFrameInFecGroup) { CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]); } -TEST_P(QuicFramerTest, AckFrame) { +TEST_P(QuicFramerTest, AckFrame15) { + if (framer_.version() != QUIC_VERSION_15) { + return; + } + unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -1635,6 +1721,8 @@ TEST_P(QuicFramerTest, AckFrame) { 0x01, // 0 more missing packets in range. 0x00, + // Number of revived packets. + 0x00, }; QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false); @@ -1667,11 +1755,13 @@ TEST_P(QuicFramerTest, AckFrame) { const size_t kNumMissingPacketOffset = kMissingDeltaTimeOffset + kQuicDeltaTimeLargestObservedSize; const size_t kMissingPacketsOffset = kNumMissingPacketOffset + - kNumberOfMissingPacketsSize; + 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 = kMissingPacketsRange + + const size_t ack_frame_size = kRevivedPacketsLength + PACKET_1BYTE_SEQUENCE_NUMBER; for (size_t i = kQuicFrameTypeSize; i < ack_frame_size; ++i) { string expected_error; @@ -1689,22 +1779,396 @@ TEST_P(QuicFramerTest, AckFrame) { 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 (framer_.version() <= QUIC_VERSION_15) { + 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.received_info.entropy_hash); + EXPECT_EQ(GG_UINT64_C(0x0123456789ABF), frame.received_info.largest_observed); + ASSERT_EQ(1u, frame.received_info.missing_packets.size()); + SequenceNumberSet::const_iterator missing_iter = + frame.received_info.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, AckFrameRevivedPackets) { + if (framer_.version() <= QUIC_VERSION_15) { + 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. + 0x01, + // Revived packet sequence number. + 0xBE, 0x9A, 0x78, 0x56, + 0x34, 0x12, + }; + + 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.received_info.entropy_hash); + EXPECT_EQ(GG_UINT64_C(0x0123456789ABF), frame.received_info.largest_observed); + ASSERT_EQ(1u, frame.received_info.missing_packets.size()); + SequenceNumberSet::const_iterator missing_iter = + frame.received_info.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; + 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 < 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) { + 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 if (i < kRevivedPacketSequenceNumberLength) { + expected_error = "Unable to read num revived packets."; } else { + expected_error = "Unable to read revived packet."; + } + 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, AckFrameRevivedPackets15) { + if (framer_.version() != QUIC_VERSION_15) { + 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 sent packets till least awaiting - 1. + 0xAB, + // least packet sequence number awaiting an ack, delta from sequence number. + 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, + // 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. + 0x01, + // Revived packet sequence number. + 0xBE, 0x9A, 0x78, 0x56, + 0x34, 0x12, + }; + + 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(0xAB, frame.sent_info.entropy_hash); + EXPECT_EQ(0xBA, frame.received_info.entropy_hash); + EXPECT_EQ(GG_UINT64_C(0x0123456789ABF), frame.received_info.largest_observed); + ASSERT_EQ(1u, frame.received_info.missing_packets.size()); + SequenceNumberSet::const_iterator missing_iter = + frame.received_info.missing_packets.begin(); + EXPECT_EQ(GG_UINT64_C(0x0123456789ABE), *missing_iter); + EXPECT_EQ(GG_UINT64_C(0x0123456789AA0), frame.sent_info.least_unacked); + + const size_t kSentEntropyOffset = kQuicFrameTypeSize; + const size_t kLeastUnackedOffset = kSentEntropyOffset + kQuicEntropyHashSize; + const size_t kReceivedEntropyOffset = kLeastUnackedOffset + + PACKET_6BYTE_SEQUENCE_NUMBER; + 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; + 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 < kLeastUnackedOffset) { + expected_error = "Unable to read entropy hash for sent packets."; + } else 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) { + 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 if (i < kRevivedPacketSequenceNumberLength) { + expected_error = "Unable to read num revived packets."; + } else { + expected_error = "Unable to read revived packet."; } CheckProcessingFails( packet, - i + GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, + i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP), expected_error, QUIC_INVALID_ACK_DATA); } } TEST_P(QuicFramerTest, AckFrameNoNacks) { + if (framer_.version() <= QUIC_VERSION_15) { + return; + } unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // 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->received_info.entropy_hash); + EXPECT_EQ(GG_UINT64_C(0x0123456789ABF), + frame->received_info.largest_observed); + ASSERT_EQ(0u, frame->received_info.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, AckFrameNoNacks15) { + if (framer_.version() > QUIC_VERSION_15) { + return; + } + unsigned char packet[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -1750,8 +2214,7 @@ TEST_P(QuicFramerTest, AckFrameNoNacks) { // Verify that the packet re-serializes identically. QuicFrames frames; frames.push_back(QuicFrame(frame)); - scoped_ptr<QuicPacket> data( - framer_.BuildUnsizedDataPacket(*visitor_.header_, frames).packet); + scoped_ptr<QuicPacket> data(BuildDataPacket(*visitor_.header_, frames)); ASSERT_TRUE(data != NULL); test::CompareCharArraysWithHexError("constructed packet", @@ -1760,10 +2223,87 @@ TEST_P(QuicFramerTest, AckFrameNoNacks) { } TEST_P(QuicFramerTest, AckFrame500Nacks) { + if (framer_.version() <= QUIC_VERSION_15) { + 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->received_info.entropy_hash); + EXPECT_EQ(GG_UINT64_C(0x0123456789ABF), + frame->received_info.largest_observed); + EXPECT_EQ(0u, frame->received_info.revived_packets.size()); + ASSERT_EQ(500u, frame->received_info.missing_packets.size()); + SequenceNumberSet::const_iterator first_missing_iter = + frame->received_info.missing_packets.begin(); + EXPECT_EQ(GG_UINT64_C(0x0123456789ABE) - 499, *first_missing_iter); + SequenceNumberSet::const_reverse_iterator last_missing_iter = + frame->received_info.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, AckFrame500Nacks15) { + if (framer_.version() != QUIC_VERSION_15) { + return; + } unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -1798,6 +2338,8 @@ TEST_P(QuicFramerTest, AckFrame500Nacks) { 0x00, // 255 more missing packets in range. 0xFF, + // No revived packets. + 0x00, }; QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false); @@ -1814,6 +2356,7 @@ TEST_P(QuicFramerTest, AckFrame500Nacks) { EXPECT_EQ(0xBA, frame->received_info.entropy_hash); EXPECT_EQ(GG_UINT64_C(0x0123456789ABF), frame->received_info.largest_observed); + EXPECT_EQ(0u, frame->received_info.revived_packets.size()); ASSERT_EQ(500u, frame->received_info.missing_packets.size()); SequenceNumberSet::const_iterator first_missing_iter = frame->received_info.missing_packets.begin(); @@ -1826,8 +2369,7 @@ TEST_P(QuicFramerTest, AckFrame500Nacks) { // Verify that the packet re-serializes identically. QuicFrames frames; frames.push_back(QuicFrame(frame)); - scoped_ptr<QuicPacket> data( - framer_.BuildUnsizedDataPacket(*visitor_.header_, frames).packet); + scoped_ptr<QuicPacket> data(BuildDataPacket(*visitor_.header_, frames)); ASSERT_TRUE(data != NULL); test::CompareCharArraysWithHexError("constructed packet", @@ -1837,9 +2379,9 @@ TEST_P(QuicFramerTest, AckFrame500Nacks) { TEST_P(QuicFramerTest, CongestionFeedbackFrameTCP) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -1852,8 +2394,6 @@ TEST_P(QuicFramerTest, CongestionFeedbackFrameTCP) { 0x20, // congestion feedback type (tcp) 0x00, - // ack_frame.feedback.tcp.accumulated_number_of_lost_packets - 0x01, 0x02, // ack_frame.feedback.tcp.receive_window 0x03, 0x04, }; @@ -1870,23 +2410,19 @@ TEST_P(QuicFramerTest, CongestionFeedbackFrameTCP) { const QuicCongestionFeedbackFrame& frame = *visitor_.congestion_feedback_frames_[0]; ASSERT_EQ(kTCP, frame.type); - EXPECT_EQ(0x0201, - frame.tcp.accumulated_number_of_lost_packets); EXPECT_EQ(0x4030u, frame.tcp.receive_window); // Now test framing boundaries - for (size_t i = kQuicFrameTypeSize; i < 6; ++i) { + for (size_t i = kQuicFrameTypeSize; i < 4; ++i) { string expected_error; if (i < 2) { expected_error = "Unable to read congestion feedback type."; } else if (i < 4) { - expected_error = "Unable to read accumulated number of lost packets."; - } else if (i < 6) { expected_error = "Unable to read receive window."; } CheckProcessingFails( packet, - i + GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, + i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP), expected_error, QUIC_INVALID_CONGESTION_FEEDBACK_DATA); } @@ -1894,9 +2430,9 @@ TEST_P(QuicFramerTest, CongestionFeedbackFrameTCP) { TEST_P(QuicFramerTest, CongestionFeedbackFrameInterArrival) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -1909,8 +2445,6 @@ TEST_P(QuicFramerTest, CongestionFeedbackFrameInterArrival) { 0x20, // congestion feedback type (inter arrival) 0x01, - // accumulated_number_of_lost_packets - 0x02, 0x03, // num received packets 0x03, // lowest sequence number @@ -1941,8 +2475,6 @@ TEST_P(QuicFramerTest, CongestionFeedbackFrameInterArrival) { const QuicCongestionFeedbackFrame& frame = *visitor_.congestion_feedback_frames_[0]; ASSERT_EQ(kInterArrival, frame.type); - EXPECT_EQ(0x0302, frame.inter_arrival. - accumulated_number_of_lost_packets); ASSERT_EQ(3u, frame.inter_arrival.received_packet_times.size()); TimeMap::const_iterator iter = frame.inter_arrival.received_packet_times.begin(); @@ -1959,30 +2491,28 @@ TEST_P(QuicFramerTest, CongestionFeedbackFrameInterArrival) { iter->second.Subtract(start_).ToMicroseconds()); // Now test framing boundaries - for (size_t i = kQuicFrameTypeSize; i < 31; ++i) { + for (size_t i = kQuicFrameTypeSize; i < 29; ++i) { string expected_error; if (i < 2) { expected_error = "Unable to read congestion feedback type."; - } else if (i < 4) { - expected_error = "Unable to read accumulated number of lost packets."; - } else if (i < 5) { + } else if (i < 3) { expected_error = "Unable to read num received packets."; - } else if (i < 11) { + } else if (i < 9) { expected_error = "Unable to read smallest received."; - } else if (i < 19) { + } else if (i < 17) { expected_error = "Unable to read time received."; - } else if (i < 21) { + } else if (i < 19) { expected_error = "Unable to read sequence delta in received packets."; - } else if (i < 25) { + } else if (i < 23) { expected_error = "Unable to read time delta in received packets."; - } else if (i < 27) { + } else if (i < 25) { expected_error = "Unable to read sequence delta in received packets."; - } else if (i < 31) { + } else if (i < 29) { expected_error = "Unable to read time delta in received packets."; } CheckProcessingFails( packet, - i + GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, + i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP), expected_error, QUIC_INVALID_CONGESTION_FEEDBACK_DATA); } @@ -1990,9 +2520,9 @@ TEST_P(QuicFramerTest, CongestionFeedbackFrameInterArrival) { TEST_P(QuicFramerTest, CongestionFeedbackFrameFixRate) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -2034,7 +2564,7 @@ TEST_P(QuicFramerTest, CongestionFeedbackFrameFixRate) { } CheckProcessingFails( packet, - i + GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, + i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP), expected_error, QUIC_INVALID_CONGESTION_FEEDBACK_DATA); } @@ -2042,9 +2572,9 @@ TEST_P(QuicFramerTest, CongestionFeedbackFrameFixRate) { TEST_P(QuicFramerTest, CongestionFeedbackFrameInvalidFeedback) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -2065,11 +2595,68 @@ TEST_P(QuicFramerTest, CongestionFeedbackFrameInvalidFeedback) { EXPECT_EQ(QUIC_INVALID_CONGESTION_FEEDBACK_DATA, framer_.error()); } -TEST_P(QuicFramerTest, RstStreamFrame) { +TEST_P(QuicFramerTest, StopWaitingFrame) { + if (framer_.version() <= QUIC_VERSION_15) { + return; + } unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // 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) + 0x06, + // entropy hash of sent packets till least awaiting - 1. + 0xAB, + // least packet sequence number awaiting an ack, delta from sequence number. + 0x08, 0x00, 0x00, 0x00, + 0x00, 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_.stop_waiting_frames_.size()); + const QuicStopWaitingFrame& frame = *visitor_.stop_waiting_frames_[0]; + EXPECT_EQ(0xAB, frame.entropy_hash); + EXPECT_EQ(GG_UINT64_C(0x0123456789AA0), frame.least_unacked); + + const size_t kSentEntropyOffset = kQuicFrameTypeSize; + const size_t kLeastUnackedOffset = kSentEntropyOffset + kQuicEntropyHashSize; + const size_t frame_size = 7; + for (size_t i = kQuicFrameTypeSize; i < frame_size; ++i) { + string expected_error; + if (i < kLeastUnackedOffset) { + expected_error = "Unable to read entropy hash for sent packets."; + } else { + expected_error = "Unable to read least unacked delta."; + } + CheckProcessingFails( + packet, + i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, + PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP), + expected_error, QUIC_INVALID_STOP_WAITING_DATA); + } +} + +TEST_P(QuicFramerTest, RstStreamFrameQuic) { + unsigned char packet[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -2082,6 +2669,11 @@ TEST_P(QuicFramerTest, RstStreamFrame) { 0x01, // stream id 0x04, 0x03, 0x02, 0x01, + + // sent byte offset + 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + // error code 0x01, 0x00, 0x00, 0x00, @@ -2104,21 +2696,27 @@ TEST_P(QuicFramerTest, RstStreamFrame) { EXPECT_EQ(GG_UINT64_C(0x01020304), visitor_.rst_stream_frame_.stream_id); EXPECT_EQ(0x01, visitor_.rst_stream_frame_.error_code); EXPECT_EQ("because I can", visitor_.rst_stream_frame_.error_details); + EXPECT_EQ(GG_UINT64_C(0x0807060504030201), + visitor_.rst_stream_frame_.byte_offset); // Now test framing boundaries - for (size_t i = kQuicFrameTypeSize; i < 24; ++i) { + for (size_t i = kQuicFrameTypeSize; + i < QuicFramer::GetMinRstStreamFrameSize(version_); ++i) { string expected_error; if (i < kQuicFrameTypeSize + kQuicMaxStreamIdSize) { expected_error = "Unable to read stream_id."; } else if (i < kQuicFrameTypeSize + kQuicMaxStreamIdSize + - kQuicErrorCodeSize) { + + kQuicMaxStreamOffsetSize) { + expected_error = "Unable to read rst stream sent byte offset."; + } else if (i < kQuicFrameTypeSize + kQuicMaxStreamIdSize + + + kQuicMaxStreamOffsetSize + kQuicErrorCodeSize) { expected_error = "Unable to read rst stream error code."; } else { expected_error = "Unable to read rst stream error details."; } CheckProcessingFails( packet, - i + GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, + i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP), expected_error, QUIC_INVALID_RST_STREAM_DATA); } @@ -2126,9 +2724,9 @@ TEST_P(QuicFramerTest, RstStreamFrame) { TEST_P(QuicFramerTest, ConnectionCloseFrame) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -2176,7 +2774,7 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) { } CheckProcessingFails( packet, - i + GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, + i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP), expected_error, QUIC_INVALID_CONNECTION_CLOSE_DATA); } @@ -2184,9 +2782,9 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) { TEST_P(QuicFramerTest, GoAwayFrame) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -2237,25 +2835,164 @@ TEST_P(QuicFramerTest, GoAwayFrame) { } CheckProcessingFails( packet, - i + GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, + i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP), expected_error, QUIC_INVALID_GOAWAY_DATA); } } +TEST_P(QuicFramerTest, WindowUpdateFrame) { + unsigned char packet[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet sequence number + 0xBC, 0x9A, 0x78, 0x56, + 0x34, 0x12, + // private flags + 0x00, + + // frame type (window update frame) + 0x04, + // stream id + 0x04, 0x03, 0x02, 0x01, + // byte offset + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, + }; + + 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(GG_UINT64_C(0x01020304), + visitor_.window_update_frame_.stream_id); + EXPECT_EQ(GG_UINT64_C(0x0c0b0a0908070605), + visitor_.window_update_frame_.byte_offset); + + // Now test framing boundaries + for (size_t i = kQuicFrameTypeSize; + i < QuicFramer::GetWindowUpdateFrameSize(); ++i) { + string expected_error; + if (i < kQuicFrameTypeSize + kQuicMaxStreamIdSize) { + expected_error = "Unable to read stream_id."; + } else { + expected_error = "Unable to read window byte_offset."; + } + CheckProcessingFails( + packet, + i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, + PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP), + expected_error, QUIC_INVALID_WINDOW_UPDATE_DATA); + } +} + +TEST_P(QuicFramerTest, BlockedFrame) { + unsigned char packet[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet sequence number + 0xBC, 0x9A, 0x78, 0x56, + 0x34, 0x12, + // private flags + 0x00, + + // frame type (blocked frame) + 0x05, + // stream id + 0x04, 0x03, 0x02, 0x01, + }; + + 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(GG_UINT64_C(0x01020304), + visitor_.blocked_frame_.stream_id); + + // Now test framing boundaries + for (size_t i = kQuicFrameTypeSize; i < QuicFramer::GetBlockedFrameSize(); + ++i) { + string expected_error = "Unable to read stream_id."; + CheckProcessingFails( + packet, + i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, + PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP), + expected_error, QUIC_INVALID_BLOCKED_DATA); + } +} + +TEST_P(QuicFramerTest, PingFrame) { + if (version_ <= QUIC_VERSION_17) { + return; + } + + unsigned char packet[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet sequence number + 0xBC, 0x9A, 0x78, 0x56, + 0x34, 0x12, + // private flags + 0x00, + + // frame type (ping frame) + 0x07, + }; + + 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(1u, visitor_.ping_frames_.size()); + + // No need to check the PING frame boundaries because it has no payload. +} + TEST_P(QuicFramerTest, PublicResetPacket) { unsigned char packet[] = { - // public flags (public reset, 8 byte guid) - 0x3E, - // guid + // public flags (public reset, 8 byte connection_id) + 0x0E, + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, + // message tag (kPRST) + 'P', 'R', 'S', 'T', + // num_entries (2) + padding + 0x02, 0x00, 0x00, 0x00, + // tag kRNON + 'R', 'N', 'O', 'N', + // end offset 8 + 0x08, 0x00, 0x00, 0x00, + // tag kRSEQ + 'R', 'S', 'E', 'Q', + // end offset 16 + 0x10, 0x00, 0x00, 0x00, // nonce proof 0x89, 0x67, 0x45, 0x23, 0x01, 0xEF, 0xCD, 0xAB, // rejected sequence number 0xBC, 0x9A, 0x78, 0x56, - 0x34, 0x12, + 0x34, 0x12, 0x00, 0x00, }; QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false); @@ -2263,32 +3000,136 @@ TEST_P(QuicFramerTest, PublicResetPacket) { ASSERT_EQ(QUIC_NO_ERROR, framer_.error()); ASSERT_TRUE(visitor_.public_reset_packet_.get()); EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210), - visitor_.public_reset_packet_->public_header.guid); + visitor_.public_reset_packet_->public_header.connection_id); EXPECT_TRUE(visitor_.public_reset_packet_->public_header.reset_flag); EXPECT_FALSE(visitor_.public_reset_packet_->public_header.version_flag); EXPECT_EQ(GG_UINT64_C(0xABCDEF0123456789), visitor_.public_reset_packet_->nonce_proof); EXPECT_EQ(GG_UINT64_C(0x123456789ABC), visitor_.public_reset_packet_->rejected_sequence_number); + EXPECT_TRUE( + visitor_.public_reset_packet_->client_address.address().empty()); // Now test framing boundaries - for (size_t i = 0; i < GetPublicResetPacketSize(); ++i) { + for (size_t i = 0; i < arraysize(packet); ++i) { string expected_error; - DLOG(INFO) << "iteration: " << i; - if (i < kGuidOffset) { + DVLOG(1) << "iteration: " << i; + if (i < kConnectionIdOffset) { expected_error = "Unable to read public flags."; CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER); - } else if (i < kPublicResetPacketNonceProofOffset) { - expected_error = "Unable to read GUID."; + } else if (i < kPublicResetPacketMessageTagOffset) { + expected_error = "Unable to read ConnectionId."; CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PACKET_HEADER); - } else if (i < kPublicResetPacketRejectedSequenceNumberOffset) { - expected_error = "Unable to read nonce proof."; + } else { + expected_error = "Unable to read reset message."; CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PUBLIC_RST_PACKET); + } + } +} + +TEST_P(QuicFramerTest, PublicResetPacketWithTrailingJunk) { + unsigned char packet[] = { + // public flags (public reset, 8 byte connection_id) + 0x0E, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // message tag (kPRST) + 'P', 'R', 'S', 'T', + // num_entries (2) + padding + 0x02, 0x00, 0x00, 0x00, + // tag kRNON + 'R', 'N', 'O', 'N', + // end offset 8 + 0x08, 0x00, 0x00, 0x00, + // tag kRSEQ + 'R', 'S', 'E', 'Q', + // end offset 16 + 0x10, 0x00, 0x00, 0x00, + // nonce proof + 0x89, 0x67, 0x45, 0x23, + 0x01, 0xEF, 0xCD, 0xAB, + // rejected sequence number + 0xBC, 0x9A, 0x78, 0x56, + 0x34, 0x12, 0x00, 0x00, + // trailing junk + 'j', 'u', 'n', 'k', + }; + + string expected_error = "Unable to read reset message."; + CheckProcessingFails(packet, arraysize(packet), expected_error, + QUIC_INVALID_PUBLIC_RST_PACKET); +} + +TEST_P(QuicFramerTest, PublicResetPacketWithClientAddress) { + unsigned char packet[] = { + // public flags (public reset, 8 byte connection_id) + 0x0E, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // message tag (kPRST) + 'P', 'R', 'S', 'T', + // num_entries (3) + padding + 0x03, 0x00, 0x00, 0x00, + // tag kRNON + 'R', 'N', 'O', 'N', + // end offset 8 + 0x08, 0x00, 0x00, 0x00, + // tag kRSEQ + 'R', 'S', 'E', 'Q', + // end offset 16 + 0x10, 0x00, 0x00, 0x00, + // tag kCADR + 'C', 'A', 'D', 'R', + // end offset 24 + 0x18, 0x00, 0x00, 0x00, + // nonce proof + 0x89, 0x67, 0x45, 0x23, + 0x01, 0xEF, 0xCD, 0xAB, + // rejected sequence number + 0xBC, 0x9A, 0x78, 0x56, + 0x34, 0x12, 0x00, 0x00, + // client address: 4.31.198.44:443 + 0x02, 0x00, + 0x04, 0x1F, 0xC6, 0x2C, + 0xBB, 0x01, + }; + + QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false); + EXPECT_TRUE(framer_.ProcessPacket(encrypted)); + ASSERT_EQ(QUIC_NO_ERROR, framer_.error()); + ASSERT_TRUE(visitor_.public_reset_packet_.get()); + EXPECT_EQ(GG_UINT64_C(0xFEDCBA9876543210), + visitor_.public_reset_packet_->public_header.connection_id); + EXPECT_TRUE(visitor_.public_reset_packet_->public_header.reset_flag); + EXPECT_FALSE(visitor_.public_reset_packet_->public_header.version_flag); + EXPECT_EQ(GG_UINT64_C(0xABCDEF0123456789), + visitor_.public_reset_packet_->nonce_proof); + EXPECT_EQ(GG_UINT64_C(0x123456789ABC), + visitor_.public_reset_packet_->rejected_sequence_number); + EXPECT_EQ("4.31.198.44", + IPAddressToString(visitor_.public_reset_packet_-> + client_address.address())); + EXPECT_EQ(443, visitor_.public_reset_packet_->client_address.port()); + + // Now test framing boundaries + for (size_t i = 0; i < arraysize(packet); ++i) { + string expected_error; + DVLOG(1) << "iteration: " << i; + if (i < kConnectionIdOffset) { + expected_error = "Unable to read public flags."; + CheckProcessingFails(packet, i, expected_error, + QUIC_INVALID_PACKET_HEADER); + } else if (i < kPublicResetPacketMessageTagOffset) { + expected_error = "Unable to read ConnectionId."; + CheckProcessingFails(packet, i, expected_error, + QUIC_INVALID_PACKET_HEADER); } else { - expected_error = "Unable to read rejected sequence number."; + expected_error = "Unable to read reset message."; CheckProcessingFails(packet, i, expected_error, QUIC_INVALID_PUBLIC_RST_PACKET); } @@ -2297,9 +3138,9 @@ TEST_P(QuicFramerTest, PublicResetPacket) { TEST_P(QuicFramerTest, VersionNegotiationPacket) { unsigned char packet[] = { - // public flags (version, 8 byte guid) + // public flags (version, 8 byte connection_id) 0x3D, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // version tag @@ -2316,13 +3157,13 @@ TEST_P(QuicFramerTest, VersionNegotiationPacket) { EXPECT_EQ(2u, visitor_.version_negotiation_packet_->versions.size()); EXPECT_EQ(GetParam(), visitor_.version_negotiation_packet_->versions[0]); - for (size_t i = 0; i <= kPublicFlagsSize + PACKET_8BYTE_GUID; ++i) { + for (size_t i = 0; i <= kPublicFlagsSize + PACKET_8BYTE_CONNECTION_ID; ++i) { string expected_error; QuicErrorCode error_code = QUIC_INVALID_PACKET_HEADER; - if (i < kGuidOffset) { + if (i < kConnectionIdOffset) { expected_error = "Unable to read public flags."; } else if (i < kVersionOffset) { - expected_error = "Unable to read GUID."; + expected_error = "Unable to read ConnectionId."; } else { expected_error = "Unable to read supported version in negotiation."; error_code = QUIC_INVALID_VERSION_NEGOTIATION_PACKET; @@ -2333,9 +3174,9 @@ TEST_P(QuicFramerTest, VersionNegotiationPacket) { TEST_P(QuicFramerTest, FecPacket) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -2370,7 +3211,7 @@ TEST_P(QuicFramerTest, FecPacket) { TEST_P(QuicFramerTest, BuildPaddingFramePacket) { QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + 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; @@ -2384,9 +3225,9 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) { frames.push_back(QuicFrame(&padding_frame)); unsigned char packet[kMaxPacketSize] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -2401,12 +3242,11 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) { }; uint64 header_size = - GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1); - scoped_ptr<QuicPacket> data( - framer_.BuildUnsizedDataPacket(header, frames).packet); + scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != NULL); test::CompareCharArraysWithHexError("constructed packet", @@ -2417,7 +3257,7 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) { TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) { QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + 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; @@ -2432,9 +3272,9 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) { frames.push_back(QuicFrame(&padding_frame)); unsigned char packet[kMaxPacketSize] = { - // public flags (8 byte guid and 4 byte sequence number) + // public flags (8 byte connection_id and 4 byte sequence number) 0x2C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -2448,12 +3288,11 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) { }; uint64 header_size = - GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_4BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1); - scoped_ptr<QuicPacket> data( - framer_.BuildUnsizedDataPacket(header, frames).packet); + scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != NULL); test::CompareCharArraysWithHexError("constructed packet", @@ -2464,7 +3303,7 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) { TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) { QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + 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; @@ -2479,9 +3318,9 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) { frames.push_back(QuicFrame(&padding_frame)); unsigned char packet[kMaxPacketSize] = { - // public flags (8 byte guid and 2 byte sequence number) + // public flags (8 byte connection_id and 2 byte sequence number) 0x1C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -2495,12 +3334,11 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) { }; uint64 header_size = - GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_2BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1); - scoped_ptr<QuicPacket> data( - framer_.BuildUnsizedDataPacket(header, frames).packet); + scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != NULL); test::CompareCharArraysWithHexError("constructed packet", @@ -2511,7 +3349,7 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) { TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) { QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + 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; @@ -2526,9 +3364,9 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) { frames.push_back(QuicFrame(&padding_frame)); unsigned char packet[kMaxPacketSize] = { - // public flags (8 byte guid and 1 byte sequence number) + // public flags (8 byte connection_id and 1 byte sequence number) 0x0C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -2542,12 +3380,11 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) { }; uint64 header_size = - GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_1BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1); - scoped_ptr<QuicPacket> data( - framer_.BuildUnsizedDataPacket(header, frames).packet); + scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != NULL); test::CompareCharArraysWithHexError("constructed packet", @@ -2558,7 +3395,7 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) { TEST_P(QuicFramerTest, BuildStreamFramePacket) { QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + 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; @@ -2576,9 +3413,9 @@ TEST_P(QuicFramerTest, BuildStreamFramePacket) { frames.push_back(QuicFrame(&stream_frame)); unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -2600,8 +3437,62 @@ TEST_P(QuicFramerTest, BuildStreamFramePacket) { 'r', 'l', 'd', '!', }; - scoped_ptr<QuicPacket> data( - framer_.BuildUnsizedDataPacket(header, frames).packet); + scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != NULL); + + test::CompareCharArraysWithHexError("constructed packet", + data->data(), data->length(), + AsChars(packet), arraysize(packet)); +} + +TEST_P(QuicFramerTest, BuildStreamFramePacketInFecGroup) { + 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(0x77123456789ABC); + header.is_in_fec_group = IN_FEC_GROUP; + header.fec_group = GG_UINT64_C(0x77123456789ABC); + + QuicStreamFrame stream_frame; + stream_frame.stream_id = 0x01020304; + stream_frame.fin = true; + stream_frame.offset = GG_UINT64_C(0xBA98FEDC32107654); + stream_frame.data = MakeIOVector("hello world!"); + + QuicFrames frames; + frames.push_back(QuicFrame(&stream_frame)); + unsigned char packet[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet sequence number + 0xBC, 0x9A, 0x78, 0x56, + 0x34, 0x12, + // private flags (entropy, is_in_fec_group) + 0x03, + // FEC group + 0x00, + // frame type (stream frame with fin and data length field) + 0xFF, + // stream id + 0x04, 0x03, 0x02, 0x01, + // offset + 0x54, 0x76, 0x10, 0x32, + 0xDC, 0xFE, 0x98, 0xBA, + // data length (since packet is in an FEC group) + 0x0C, 0x00, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; + + scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != NULL); test::CompareCharArraysWithHexError("constructed packet", @@ -2611,7 +3502,7 @@ TEST_P(QuicFramerTest, BuildStreamFramePacket) { TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) { QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + header.public_header.connection_id = GG_UINT64_C(0xFEDCBA9876543210); header.public_header.reset_flag = false; header.public_header.version_flag = true; header.fec_flag = false; @@ -2629,9 +3520,9 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) { frames.push_back(QuicFrame(&stream_frame)); unsigned char packet[] = { - // public flags (version, 8 byte guid) + // public flags (version, 8 byte connection_id) 0x3D, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // version tag @@ -2656,8 +3547,7 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) { }; QuicFramerPeer::SetIsServer(&framer_, false); - scoped_ptr<QuicPacket> data( - framer_.BuildUnsizedDataPacket(header, frames).packet); + scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != NULL); test::CompareCharArraysWithHexError("constructed packet", @@ -2667,14 +3557,14 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) { TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) { QuicPacketPublicHeader header; - header.guid = GG_UINT64_C(0xFEDCBA9876543210); + header.connection_id = GG_UINT64_C(0xFEDCBA9876543210); header.reset_flag = false; header.version_flag = true; unsigned char packet[] = { - // public flags (version, 8 byte guid) - 0x3D, - // guid + // public flags (version, 8 byte connection_id) + 0x0D, + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // version tag @@ -2692,8 +3582,74 @@ TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) { } TEST_P(QuicFramerTest, BuildAckFramePacket) { + if (version_ <= QUIC_VERSION_15) { + return; + } QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + 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.received_info.entropy_hash = 0x43; + ack_frame.received_info.largest_observed = GG_UINT64_C(0x770123456789ABF); + ack_frame.received_info.delta_time_largest_observed = QuicTime::Delta::Zero(); + ack_frame.received_info.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(), + AsChars(packet), arraysize(packet)); +} + +TEST_P(QuicFramerTest, BuildAckFramePacket15) { + if (version_ != QUIC_VERSION_15) { + 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; @@ -2714,9 +3670,9 @@ TEST_P(QuicFramerTest, BuildAckFramePacket) { frames.push_back(QuicFrame(&ack_frame)); unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -2746,10 +3702,128 @@ TEST_P(QuicFramerTest, BuildAckFramePacket) { 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(), + AsChars(packet), arraysize(packet)); +} + +// 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, BuildTruncatedAckFrameLargePacket) { + if (version_ <= QUIC_VERSION_15) { + 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.received_info.entropy_hash = 0x43; + ack_frame.received_info.largest_observed = 2 * 300; + ack_frame.received_info.delta_time_largest_observed = QuicTime::Delta::Zero(); + for (size_t i = 1; i < 2 * 300; i += 2) { + ack_frame.received_info.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_.BuildUnsizedDataPacket(header, frames).packet); + framer_.BuildDataPacket(header, frames, kMaxPacketSize).packet); ASSERT_TRUE(data != NULL); test::CompareCharArraysWithHexError("constructed packet", @@ -2757,9 +3831,79 @@ TEST_P(QuicFramerTest, BuildAckFramePacket) { AsChars(packet), arraysize(packet)); } + +TEST_P(QuicFramerTest, BuildTruncatedAckFrameSmallPacket) { + if (version_ <= QUIC_VERSION_15) { + 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.received_info.entropy_hash = 0x43; + ack_frame.received_info.largest_observed = 2 * 300; + ack_frame.received_info.delta_time_largest_observed = QuicTime::Delta::Zero(); + for (size_t i = 1; i < 2 * 300; i += 2) { + ack_frame.received_info.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, BuildCongestionFeedbackFramePacketTCP) { QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + 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; @@ -2769,16 +3913,15 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketTCP) { QuicCongestionFeedbackFrame congestion_feedback_frame; congestion_feedback_frame.type = kTCP; - congestion_feedback_frame.tcp.accumulated_number_of_lost_packets = 0x0201; congestion_feedback_frame.tcp.receive_window = 0x4030; QuicFrames frames; frames.push_back(QuicFrame(&congestion_feedback_frame)); unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -2791,14 +3934,11 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketTCP) { 0x20, // congestion feedback type (TCP) 0x00, - // accumulated number of lost packets - 0x01, 0x02, // TCP receive window 0x03, 0x04, }; - scoped_ptr<QuicPacket> data( - framer_.BuildUnsizedDataPacket(header, frames).packet); + scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != NULL); test::CompareCharArraysWithHexError("constructed packet", @@ -2808,7 +3948,7 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketTCP) { TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketInterArrival) { QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + 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; @@ -2818,7 +3958,6 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketInterArrival) { QuicCongestionFeedbackFrame frame; frame.type = kInterArrival; - frame.inter_arrival.accumulated_number_of_lost_packets = 0x0302; frame.inter_arrival.received_packet_times.insert( make_pair(GG_UINT64_C(0x0123456789ABA), start_.Add(QuicTime::Delta::FromMicroseconds( @@ -2835,9 +3974,9 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketInterArrival) { frames.push_back(QuicFrame(&frame)); unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -2850,8 +3989,6 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketInterArrival) { 0x20, // congestion feedback type (inter arrival) 0x01, - // accumulated_number_of_lost_packets - 0x02, 0x03, // num received packets 0x03, // lowest sequence number @@ -2870,8 +4007,56 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketInterArrival) { 0x02, 0x00, 0x00, 0x00, }; - scoped_ptr<QuicPacket> data( - framer_.BuildUnsizedDataPacket(header, frames).packet); + scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != NULL); + + test::CompareCharArraysWithHexError("constructed packet", + data->data(), data->length(), + AsChars(packet), arraysize(packet)); +} + +TEST_P(QuicFramerTest, BuildStopWaitingPacket) { + if (version_ <= QUIC_VERSION_15) { + 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; + + QuicStopWaitingFrame stop_waiting_frame; + stop_waiting_frame.entropy_hash = 0x14; + stop_waiting_frame.least_unacked = GG_UINT64_C(0x770123456789AA0); + + QuicFrames frames; + frames.push_back(QuicFrame(&stop_waiting_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 (stop waiting frame) + 0x06, + // entropy hash of sent packets till least awaiting - 1. + 0x14, + // least packet sequence number awaiting an ack, delta from sequence number. + 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, + }; + + scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != NULL); test::CompareCharArraysWithHexError("constructed packet", @@ -2881,7 +4066,7 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketInterArrival) { TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketFixRate) { QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + 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; @@ -2898,9 +4083,9 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketFixRate) { frames.push_back(QuicFrame(&congestion_feedback_frame)); unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -2917,8 +4102,7 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketFixRate) { 0x01, 0x02, 0x03, 0x04, }; - scoped_ptr<QuicPacket> data( - framer_.BuildUnsizedDataPacket(header, frames).packet); + scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != NULL); test::CompareCharArraysWithHexError("constructed packet", @@ -2928,7 +4112,7 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketFixRate) { TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketInvalidFeedback) { QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + 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; @@ -2943,14 +4127,16 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketInvalidFeedback) { QuicFrames frames; frames.push_back(QuicFrame(&congestion_feedback_frame)); - scoped_ptr<QuicPacket> data( - framer_.BuildUnsizedDataPacket(header, frames).packet); + scoped_ptr<QuicPacket> data; + EXPECT_DFATAL( + data.reset(BuildDataPacket(header, frames)), + "AppendCongestionFeedbackFrame failed"); ASSERT_TRUE(data == NULL); } -TEST_P(QuicFramerTest, BuildRstFramePacket) { +TEST_P(QuicFramerTest, BuildRstFramePacketQuic) { QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + 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; @@ -2962,11 +4148,12 @@ TEST_P(QuicFramerTest, BuildRstFramePacket) { rst_frame.stream_id = 0x01020304; rst_frame.error_code = static_cast<QuicRstStreamErrorCode>(0x05060708); rst_frame.error_details = "because I can"; + rst_frame.byte_offset = 0x0807060504030201; unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -2979,6 +4166,9 @@ TEST_P(QuicFramerTest, BuildRstFramePacket) { 0x01, // stream id 0x04, 0x03, 0x02, 0x01, + // sent byte offset + 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, // error code 0x08, 0x07, 0x06, 0x05, // error details length @@ -2993,8 +4183,7 @@ TEST_P(QuicFramerTest, BuildRstFramePacket) { QuicFrames frames; frames.push_back(QuicFrame(&rst_frame)); - scoped_ptr<QuicPacket> data( - framer_.BuildUnsizedDataPacket(header, frames).packet); + scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != NULL); test::CompareCharArraysWithHexError("constructed packet", @@ -3004,7 +4193,7 @@ TEST_P(QuicFramerTest, BuildRstFramePacket) { TEST_P(QuicFramerTest, BuildCloseFramePacket) { QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + 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; @@ -3020,9 +4209,9 @@ TEST_P(QuicFramerTest, BuildCloseFramePacket) { frames.push_back(QuicFrame(&close_frame)); unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -3044,8 +4233,7 @@ TEST_P(QuicFramerTest, BuildCloseFramePacket) { 'n', }; - scoped_ptr<QuicPacket> data( - framer_.BuildUnsizedDataPacket(header, frames).packet); + scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != NULL); test::CompareCharArraysWithHexError("constructed packet", @@ -3055,7 +4243,7 @@ TEST_P(QuicFramerTest, BuildCloseFramePacket) { TEST_P(QuicFramerTest, BuildGoAwayPacket) { QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + 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; @@ -3072,9 +4260,9 @@ TEST_P(QuicFramerTest, BuildGoAwayPacket) { frames.push_back(QuicFrame(&goaway_frame)); unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -3098,8 +4286,7 @@ TEST_P(QuicFramerTest, BuildGoAwayPacket) { 'n', }; - scoped_ptr<QuicPacket> data( - framer_.BuildUnsizedDataPacket(header, frames).packet); + scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != NULL); test::CompareCharArraysWithHexError("constructed packet", @@ -3107,25 +4294,224 @@ TEST_P(QuicFramerTest, BuildGoAwayPacket) { AsChars(packet), arraysize(packet)); } +TEST_P(QuicFramerTest, BuildWindowUpdatePacket) { + 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(0x123456789ABC); + header.fec_group = 0; + + QuicWindowUpdateFrame window_update_frame; + window_update_frame.stream_id = 0x01020304; + window_update_frame.byte_offset = 0x1122334455667788; + + QuicFrames frames; + frames.push_back(QuicFrame(&window_update_frame)); + + unsigned char packet[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet sequence number + 0xBC, 0x9A, 0x78, 0x56, + 0x34, 0x12, + // private flags(entropy) + 0x01, + + // frame type (window update frame) + 0x04, + // stream id + 0x04, 0x03, 0x02, 0x01, + // byte offset + 0x88, 0x77, 0x66, 0x55, + 0x44, 0x33, 0x22, 0x11, + }; + + scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != NULL); + + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); +} + +TEST_P(QuicFramerTest, BuildBlockedPacket) { + 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(0x123456789ABC); + header.fec_group = 0; + + QuicBlockedFrame blocked_frame; + blocked_frame.stream_id = 0x01020304; + + QuicFrames frames; + frames.push_back(QuicFrame(&blocked_frame)); + + unsigned char packet[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet sequence number + 0xBC, 0x9A, 0x78, 0x56, + 0x34, 0x12, + // private flags(entropy) + 0x01, + + // frame type (blocked frame) + 0x05, + // stream id + 0x04, 0x03, 0x02, 0x01, + }; + + scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != NULL); + + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); +} + +TEST_P(QuicFramerTest, BuildPingPacket) { + 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(0x123456789ABC); + header.fec_group = 0; + + QuicPingFrame ping_frame; + + QuicFrames frames; + frames.push_back(QuicFrame(&ping_frame)); + + unsigned char packet[] = { + // public flags (8 byte connection_id) + 0x3C, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet sequence number + 0xBC, 0x9A, 0x78, 0x56, + 0x34, 0x12, + // private flags(entropy) + 0x01, + + // frame type (ping frame) + 0x07, + }; + + if (version_ > QUIC_VERSION_17) { + scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != NULL); + + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); + } else { + string expected_error = + "Attempt to add a PingFrame in " + QuicVersionToString(version_); + EXPECT_DFATAL(BuildDataPacket(header, frames), + expected_error); + return; + } +} + TEST_P(QuicFramerTest, BuildPublicResetPacket) { QuicPublicResetPacket reset_packet; - reset_packet.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + reset_packet.public_header.connection_id = GG_UINT64_C(0xFEDCBA9876543210); reset_packet.public_header.reset_flag = true; reset_packet.public_header.version_flag = false; reset_packet.rejected_sequence_number = GG_UINT64_C(0x123456789ABC); reset_packet.nonce_proof = GG_UINT64_C(0xABCDEF0123456789); unsigned char packet[] = { - // public flags (public reset, 8 byte GUID) - 0x3E, - // guid + // public flags (public reset, 8 byte ConnectionId) + 0x0E, + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, + // message tag (kPRST) + 'P', 'R', 'S', 'T', + // num_entries (2) + padding + 0x02, 0x00, 0x00, 0x00, + // tag kRNON + 'R', 'N', 'O', 'N', + // end offset 8 + 0x08, 0x00, 0x00, 0x00, + // tag kRSEQ + 'R', 'S', 'E', 'Q', + // end offset 16 + 0x10, 0x00, 0x00, 0x00, // nonce proof 0x89, 0x67, 0x45, 0x23, 0x01, 0xEF, 0xCD, 0xAB, // rejected sequence number 0xBC, 0x9A, 0x78, 0x56, + 0x34, 0x12, 0x00, 0x00, + }; + + scoped_ptr<QuicEncryptedPacket> data( + framer_.BuildPublicResetPacket(reset_packet)); + ASSERT_TRUE(data != NULL); + + test::CompareCharArraysWithHexError("constructed packet", + data->data(), data->length(), + AsChars(packet), arraysize(packet)); +} + +TEST_P(QuicFramerTest, BuildPublicResetPacketWithClientAddress) { + QuicPublicResetPacket reset_packet; + reset_packet.public_header.connection_id = GG_UINT64_C(0xFEDCBA9876543210); + reset_packet.public_header.reset_flag = true; + reset_packet.public_header.version_flag = false; + reset_packet.rejected_sequence_number = GG_UINT64_C(0x123456789ABC); + reset_packet.nonce_proof = GG_UINT64_C(0xABCDEF0123456789); + reset_packet.client_address = IPEndPoint(Loopback4(), 0x1234); + + unsigned char packet[] = { + // public flags (public reset, 8 byte ConnectionId) + 0x0E, + // connection_id + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // message tag (kPRST) + 'P', 'R', 'S', 'T', + // num_entries (3) + padding + 0x03, 0x00, 0x00, 0x00, + // tag kRNON + 'R', 'N', 'O', 'N', + // end offset 8 + 0x08, 0x00, 0x00, 0x00, + // tag kRSEQ + 'R', 'S', 'E', 'Q', + // end offset 16 + 0x10, 0x00, 0x00, 0x00, + // tag kCADR + 'C', 'A', 'D', 'R', + // end offset 24 + 0x18, 0x00, 0x00, 0x00, + // nonce proof + 0x89, 0x67, 0x45, 0x23, + 0x01, 0xEF, 0xCD, 0xAB, + // rejected sequence number + 0xBC, 0x9A, 0x78, 0x56, + 0x34, 0x12, 0x00, 0x00, + // client address + 0x02, 0x00, + 0x7F, 0x00, 0x00, 0x01, 0x34, 0x12, }; @@ -3140,7 +4526,7 @@ TEST_P(QuicFramerTest, BuildPublicResetPacket) { TEST_P(QuicFramerTest, BuildFecPacket) { QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + header.public_header.connection_id = GG_UINT64_C(0xFEDCBA9876543210); header.public_header.reset_flag = false; header.public_header.version_flag = false; header.fec_flag = true; @@ -3154,9 +4540,9 @@ TEST_P(QuicFramerTest, BuildFecPacket) { fec_data.redundancy = "abcdefghijklmnop"; unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -3186,9 +4572,9 @@ TEST_P(QuicFramerTest, BuildFecPacket) { TEST_P(QuicFramerTest, EncryptPacket) { QuicPacketSequenceNumber sequence_number = GG_UINT64_C(0x123456789ABC); unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -3208,7 +4594,7 @@ TEST_P(QuicFramerTest, EncryptPacket) { scoped_ptr<QuicPacket> raw( QuicPacket::NewDataPacket(AsChars(packet), arraysize(packet), false, - PACKET_8BYTE_GUID, !kIncludeVersion, + PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER)); scoped_ptr<QuicEncryptedPacket> encrypted( framer_.EncryptPacket(ENCRYPTION_NONE, sequence_number, *raw)); @@ -3220,9 +4606,9 @@ TEST_P(QuicFramerTest, EncryptPacket) { TEST_P(QuicFramerTest, EncryptPacketWithVersionFlag) { QuicPacketSequenceNumber sequence_number = GG_UINT64_C(0x123456789ABC); unsigned char packet[] = { - // public flags (version, 8 byte guid) + // public flags (version, 8 byte connection_id) 0x3D, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // version tag @@ -3244,7 +4630,7 @@ TEST_P(QuicFramerTest, EncryptPacketWithVersionFlag) { scoped_ptr<QuicPacket> raw( QuicPacket::NewDataPacket(AsChars(packet), arraysize(packet), false, - PACKET_8BYTE_GUID, kIncludeVersion, + PACKET_8BYTE_CONNECTION_ID, kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER)); scoped_ptr<QuicEncryptedPacket> encrypted( framer_.EncryptPacket(ENCRYPTION_NONE, sequence_number, *raw)); @@ -3253,31 +4639,98 @@ TEST_P(QuicFramerTest, EncryptPacketWithVersionFlag) { EXPECT_TRUE(CheckEncryption(sequence_number, raw.get())); } -// TODO(rch): re-enable after https://codereview.chromium.org/11820005/ -// lands. Currently this is causing valgrind problems, but it should be -// fixed in the followup CL. -TEST_P(QuicFramerTest, DISABLED_CalculateLargestReceived) { - SequenceNumberSet missing; - missing.insert(1); - missing.insert(5); - missing.insert(7); +TEST_P(QuicFramerTest, AckTruncationLargePacket) { + if (framer_.version() <= QUIC_VERSION_15) { + 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, kMaxPacketSize).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.received_info.is_truncated); + EXPECT_EQ(510u, processed_ack_frame.received_info.largest_observed); + ASSERT_EQ(255u, processed_ack_frame.received_info.missing_packets.size()); + SequenceNumberSet::const_iterator missing_iter = + processed_ack_frame.received_info.missing_packets.begin(); + EXPECT_EQ(1u, *missing_iter); + SequenceNumberSet::const_reverse_iterator last_missing_iter = + processed_ack_frame.received_info.missing_packets.rbegin(); + EXPECT_EQ(509u, *last_missing_iter); +} + +TEST_P(QuicFramerTest, AckTruncationSmallPacket) { + if (framer_.version() <= QUIC_VERSION_15) { + 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; - // These two we just walk to the next gap, and return the largest seen. - EXPECT_EQ(4u, QuicFramer::CalculateLargestObserved(missing, missing.find(1))); - EXPECT_EQ(6u, QuicFramer::CalculateLargestObserved(missing, missing.find(5))); + // 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); - missing.insert(2); - // For 1, we can't go forward as 2 would be implicitly acked so we return the - // largest missing packet. - EXPECT_EQ(1u, QuicFramer::CalculateLargestObserved(missing, missing.find(1))); - // For 2, we've seen 3 and 4, so can admit to a largest observed. - EXPECT_EQ(4u, QuicFramer::CalculateLargestObserved(missing, missing.find(2))); + // 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.received_info.is_truncated); + EXPECT_EQ(476u, processed_ack_frame.received_info.largest_observed); + ASSERT_EQ(238u, processed_ack_frame.received_info.missing_packets.size()); + SequenceNumberSet::const_iterator missing_iter = + processed_ack_frame.received_info.missing_packets.begin(); + EXPECT_EQ(1u, *missing_iter); + SequenceNumberSet::const_reverse_iterator last_missing_iter = + processed_ack_frame.received_info.missing_packets.rbegin(); + EXPECT_EQ(475u, *last_missing_iter); } -// TODO(rch) enable after landing the revised truncation CL. -TEST_P(QuicFramerTest, DISABLED_Truncation) { +TEST_P(QuicFramerTest, Truncation15) { + if (framer_.version() > QUIC_VERSION_15) { + return; + } QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + 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; @@ -3287,31 +4740,31 @@ TEST_P(QuicFramerTest, DISABLED_Truncation) { QuicAckFrame ack_frame; ack_frame.received_info.largest_observed = 601; - ack_frame.sent_info.least_unacked = 0; + ack_frame.sent_info.least_unacked = header.packet_sequence_number - 1; for (uint64 i = 1; i < ack_frame.received_info.largest_observed; i += 2) { ack_frame.received_info.missing_packets.insert(i); } - // Create a packet with just the ack + // Create a packet with just the ack. QuicFrame frame; frame.type = ACK_FRAME; frame.ack_frame = &ack_frame; QuicFrames frames; frames.push_back(frame); - scoped_ptr<QuicPacket> raw_ack_packet( - framer_.BuildUnsizedDataPacket(header, frames).packet); + scoped_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames)); 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 + // 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()); const QuicAckFrame& processed_ack_frame = *visitor_.ack_frames_[0]; - EXPECT_EQ(0u, processed_ack_frame.sent_info.least_unacked); + EXPECT_EQ(header.packet_sequence_number - 1, + processed_ack_frame.sent_info.least_unacked); EXPECT_TRUE(processed_ack_frame.received_info.is_truncated); EXPECT_EQ(510u, processed_ack_frame.received_info.largest_observed); ASSERT_EQ(255u, processed_ack_frame.received_info.missing_packets.size()); @@ -3325,7 +4778,7 @@ TEST_P(QuicFramerTest, DISABLED_Truncation) { TEST_P(QuicFramerTest, CleanTruncation) { QuicPacketHeader header; - header.public_header.guid = GG_UINT64_C(0xFEDCBA9876543210); + 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; @@ -3335,27 +4788,26 @@ TEST_P(QuicFramerTest, CleanTruncation) { QuicAckFrame ack_frame; ack_frame.received_info.largest_observed = 201; - ack_frame.sent_info.least_unacked = 0; + ack_frame.sent_info.least_unacked = header.packet_sequence_number - 2; for (uint64 i = 1; i < ack_frame.received_info.largest_observed; ++i) { ack_frame.received_info.missing_packets.insert(i); } - // Create a packet with just the ack + // Create a packet with just the ack. QuicFrame frame; frame.type = ACK_FRAME; frame.ack_frame = &ack_frame; QuicFrames frames; frames.push_back(frame); - scoped_ptr<QuicPacket> raw_ack_packet( - framer_.BuildUnsizedDataPacket(header, frames).packet); + scoped_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames)); 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 + // Now make sure we can turn our ack packet back into an ack frame. ASSERT_TRUE(framer_.ProcessPacket(*ack_packet)); // Test for clean truncation of the ack by comparing the length of the @@ -3366,8 +4818,7 @@ TEST_P(QuicFramerTest, CleanTruncation) { frames.push_back(frame); size_t original_raw_length = raw_ack_packet->length(); - raw_ack_packet.reset( - framer_.BuildUnsizedDataPacket(header, frames).packet); + raw_ack_packet.reset(BuildDataPacket(header, frames)); ASSERT_TRUE(raw_ack_packet != NULL); EXPECT_EQ(original_raw_length, raw_ack_packet->length()); ASSERT_TRUE(raw_ack_packet != NULL); @@ -3375,9 +4826,9 @@ TEST_P(QuicFramerTest, CleanTruncation) { TEST_P(QuicFramerTest, EntropyFlagTest) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -3410,9 +4861,9 @@ TEST_P(QuicFramerTest, EntropyFlagTest) { TEST_P(QuicFramerTest, FecEntropyTest) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -3447,9 +4898,9 @@ TEST_P(QuicFramerTest, FecEntropyTest) { TEST_P(QuicFramerTest, StopPacketProcessing) { unsigned char packet[] = { - // public flags (8 byte guid) + // public flags (8 byte connection_id) 0x3C, - // guid + // connection_id 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // packet sequence number @@ -3498,6 +4949,7 @@ TEST_P(QuicFramerTest, StopPacketProcessing) { EXPECT_CALL(visitor, OnStreamFrame(_)).WillOnce(Return(false)); EXPECT_CALL(visitor, OnAckFrame(_)).Times(0); EXPECT_CALL(visitor, OnPacketComplete()); + EXPECT_CALL(visitor, OnUnauthenticatedPublicHeader(_)).WillOnce(Return(true)); QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); |