Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Unified Diff: net/quic/quic_framer_test.cc

Issue 11125002: Add QuicFramer and friends. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix final comments. Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/quic/quic_framer.cc ('k') | net/quic/quic_protocol.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/quic/quic_framer_test.cc
diff --git a/net/quic/quic_framer_test.cc b/net/quic/quic_framer_test.cc
new file mode 100644
index 0000000000000000000000000000000000000000..884f7089d3938fdc834262216e7fa45263fac755
--- /dev/null
+++ b/net/quic/quic_framer_test.cc
@@ -0,0 +1,2157 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+#include <vector>
+
+#include "base/hash_tables.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/stl_util.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_test_utils.h"
+
+using base::hash_set;
+using base::StringPiece;
+using std::string;
+using std::vector;
+
+namespace net {
+
+namespace test {
+
+class TestEncrypter : public QuicEncrypter {
+ public:
+ virtual ~TestEncrypter() {}
+ virtual QuicData* Encrypt(StringPiece associated_data,
+ StringPiece plaintext) {
+ associated_data_ = associated_data.as_string();
+ plaintext_ = plaintext.as_string();
+ return new QuicData(plaintext.data(), plaintext.length());
+ }
+ virtual size_t GetMaxPlaintextSize(size_t ciphertext_size) {
+ return ciphertext_size;
+ }
+ virtual size_t GetCiphertextSize(size_t plaintext_size) {
+ return plaintext_size;
+ }
+ string associated_data_;
+ string plaintext_;
+};
+
+class TestDecrypter : public QuicDecrypter {
+ public:
+ virtual ~TestDecrypter() {}
+ virtual QuicData* Decrypt(StringPiece associated_data,
+ StringPiece ciphertext) {
+ associated_data_ = associated_data.as_string();
+ ciphertext_ = ciphertext.as_string();
+ return new QuicData(ciphertext.data(), ciphertext.length());
+ }
+ string associated_data_;
+ string ciphertext_;
+};
+
+// The offset of congestion info in our tests, given the size of our usual ack
+// fragment. This does NOT work for all packets.
+const int kCongestionInfoOffset = kPacketHeaderSize + 54;
+
+class TestQuicVisitor : public ::net::QuicFramerVisitorInterface {
+ public:
+ TestQuicVisitor()
+ : error_count_(0),
+ packet_count_(0),
+ fragment_count_(0),
+ fec_count_(0),
+ complete_packets_(0),
+ accept_packet_(true) {
+ }
+
+ ~TestQuicVisitor() {
+ STLDeleteElements(&stream_fragments_);
+ STLDeleteElements(&ack_fragments_);
+ STLDeleteElements(&fec_data_);
+ }
+
+ virtual void OnError(QuicFramer* f) {
+ DLOG(INFO) << "QuicFramer Error: " << QuicUtils::ErrorToString(f->error())
+ << " (" << f->error() << ")";
+ error_count_++;
+ }
+
+ virtual void OnPacket(const IPEndPoint& client_address) {
+ address_ = client_address;
+ }
+
+ virtual bool OnPacketHeader(const QuicPacketHeader& header) {
+ packet_count_++;
+ header_.reset(new QuicPacketHeader(header));
+ return accept_packet_;
+ }
+
+ virtual void OnStreamFragment(const QuicStreamFragment& fragment) {
+ fragment_count_++;
+ stream_fragments_.push_back(new QuicStreamFragment(fragment));
+ }
+
+ virtual void OnFecProtectedPayload(StringPiece payload) {
+ fec_protected_payload_ = payload.as_string();
+ }
+
+ virtual void OnAckFragment(const QuicAckFragment& fragment) {
+ fragment_count_++;
+ ack_fragments_.push_back(new QuicAckFragment(fragment));
+ }
+
+ virtual void OnFecData(const QuicFecData& fec) {
+ fec_count_++;
+ fec_data_.push_back(new QuicFecData(fec));
+ }
+
+ virtual void OnPacketComplete() {
+ complete_packets_++;
+ }
+
+ virtual void OnRstStreamFragment(const QuicRstStreamFragment& fragment) {
+ rst_stream_fragment_ = fragment;
+ }
+
+ virtual void OnConnectionCloseFragment(
+ const QuicConnectionCloseFragment& fragment) {
+ connection_close_fragment_ = fragment;
+ }
+
+ // Counters from the visitor_ callbacks.
+ int error_count_;
+ int packet_count_;
+ int fragment_count_;
+ int fec_count_;
+ int complete_packets_;
+ bool accept_packet_;
+
+ IPEndPoint address_;
+ scoped_ptr<QuicPacketHeader> header_;
+ vector<QuicStreamFragment*> stream_fragments_;
+ vector<QuicAckFragment*> ack_fragments_;
+ vector<QuicFecData*> fec_data_;
+ string fec_protected_payload_;
+ QuicRstStreamFragment rst_stream_fragment_;
+ QuicConnectionCloseFragment connection_close_fragment_;
+};
+
+class QuicFramerTest : public ::testing::Test {
+ public:
+ QuicFramerTest()
+ : encrypter_(new test::TestEncrypter()),
+ decrypter_(new test::TestDecrypter()),
+ framer_(decrypter_, encrypter_) {
+ framer_.set_visitor(&visitor_);
+ }
+
+ bool CheckEncryption(StringPiece packet) {
+ StringPiece associated_data(
+ packet.substr(kStartOfHashData,
+ kStartOfEncryptedData - kStartOfHashData));
+ if (associated_data != encrypter_->associated_data_) {
+ LOG(ERROR) << "Encrypted incorrect associated data. expected "
+ << associated_data << " actual: "
+ << encrypter_->associated_data_;
+ return false;
+ }
+ StringPiece plaintext(packet.substr(kStartOfEncryptedData));
+ if (plaintext != encrypter_->plaintext_) {
+ LOG(ERROR) << "Encrypted incorrect plaintext data. expected "
+ << plaintext << " actual: "
+ << encrypter_->plaintext_;
+ return false;
+ }
+ return true;
+ }
+
+ bool CheckDecryption(StringPiece packet) {
+ StringPiece associated_data(
+ packet.substr(kStartOfHashData,
+ kStartOfEncryptedData - kStartOfHashData));
+ if (associated_data != decrypter_->associated_data_) {
+ LOG(ERROR) << "Decrypted incorrect associated data. expected "
+ << associated_data << " actual: "
+ << decrypter_->associated_data_;
+ return false;
+ }
+ StringPiece plaintext(packet.substr(kStartOfEncryptedData));
+ if (plaintext != decrypter_->ciphertext_) {
+ LOG(ERROR) << "Decrypted incorrect chipertext data. expected "
+ << plaintext << " actual: "
+ << decrypter_->ciphertext_;
+ return false;
+ }
+ return true;
+ }
+
+ char* AsChars(unsigned char* data) {
+ return reinterpret_cast<char*>(data);
+ }
+
+ test::TestEncrypter* encrypter_;
+ test::TestDecrypter* decrypter_;
+ QuicFramer framer_;
+ test::TestQuicVisitor visitor_;
+ IPEndPoint address_;
+};
+
+TEST_F(QuicFramerTest, EmptyPacket) {
+ char packet[] = { 0x00 };
+ EXPECT_FALSE(framer_.ProcessPacket(address_,
+ QuicEncryptedPacket(packet, 0, false)));
+ EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+}
+
+TEST_F(QuicFramerTest, LargePacket) {
+ unsigned char packet[kMaxPacketSize + 1] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+ // fragment count
+ 0x01,
+ };
+
+ memset(packet + kPacketHeaderSize, 0, kMaxPacketSize - kPacketHeaderSize + 1);
+
+ EXPECT_FALSE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet),
+ arraysize(packet), false)));
+
+ ASSERT_TRUE(visitor_.header_.get());
+ // Make sure we've parsed the packet header, so we can send an error.
+ EXPECT_EQ(0xFEDCBA9876543210, visitor_.header_->guid);
+ // Make sure the correct error is propogated.
+ EXPECT_EQ(QUIC_PACKET_TOO_LARGE, framer_.error());
+}
+
+TEST_F(QuicFramerTest, PacketHeader) {
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+ };
+
+ EXPECT_FALSE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet),
+ arraysize(packet), false)));
+
+ EXPECT_EQ(QUIC_INVALID_FRAGMENT_DATA, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_EQ(0xFEDCBA9876543210, visitor_.header_->guid);
+ EXPECT_EQ(0x1, visitor_.header_->retransmission_count);
+ EXPECT_EQ(static_cast<uint64>(0x123456789ABC),
+ visitor_.header_->packet_sequence_number);
+ EXPECT_EQ(static_cast<uint64>(0xF0E1D2C3B4A59687),
+ visitor_.header_->transmission_time);
+ EXPECT_EQ(0x00, visitor_.header_->flags);
+ EXPECT_EQ(0x00, visitor_.header_->fec_group);
+
+ // Now test framing boundaries
+ for (int i = 0; i < 25; ++i) {
+ string expected_error;
+ if (i < 8) {
+ expected_error = "Unable to read GUID.";
+ } else if (i < 14) {
+ expected_error = "Unable to read sequence number.";
+ } else if (i < 15) {
+ expected_error = "Unable to read retransmission count.";
+ } else if (i < 23) {
+ expected_error = "Unable to read transmission time.";
+ } else if (i < 24) {
+ expected_error = "Unable to read flags.";
+ } else if (i < 25) {
+ expected_error = "Unable to read fec group.";
+ }
+
+ EXPECT_FALSE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet), i, false)));
+ EXPECT_EQ(expected_error, framer_.detailed_error());
+ EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ }
+}
+
+TEST_F(QuicFramerTest, StreamFragment) {
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+
+ // fragment count
+ 0x01,
+ // fragment type (stream fragment)
+ 0x00,
+ // stream id
+ 0x04, 0x03, 0x02, 0x01,
+ // fin
+ 0x01,
+ // offset
+ 0x54, 0x76, 0x10, 0x32,
+ 0xDC, 0xFE, 0x98, 0xBA,
+ // data length
+ 0x0c, 0x00,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!',
+ };
+
+ EXPECT_TRUE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet),
+ arraysize(packet), false)));
+
+ EXPECT_TRUE(CheckDecryption(StringPiece(AsChars(packet), arraysize(packet))));
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ ASSERT_EQ(address_, visitor_.address_);
+
+ ASSERT_EQ(1u, visitor_.stream_fragments_.size());
+ EXPECT_EQ(0u, visitor_.ack_fragments_.size());
+ EXPECT_EQ(static_cast<uint64>(0x01020304),
+ visitor_.stream_fragments_[0]->stream_id);
+ EXPECT_TRUE(visitor_.stream_fragments_[0]->fin);
+ EXPECT_EQ(0xBA98FEDC32107654, visitor_.stream_fragments_[0]->offset);
+ EXPECT_EQ("hello world!", visitor_.stream_fragments_[0]->data);
+
+ // Now test framing boundaries
+ for (size_t i = kPacketHeaderSize; i < kPacketHeaderSize + 29; ++i) {
+ string expected_error;
+ if (i < kPacketHeaderSize + 1) {
+ expected_error = "Unable to read fragment count.";
+ } else if (i < kPacketHeaderSize + 2) {
+ expected_error = "Unable to read fragment type.";
+ } else if (i < kPacketHeaderSize + 6) {
+ expected_error = "Unable to read stream_id.";
+ } else if (i < kPacketHeaderSize + 7) {
+ expected_error = "Unable to read fin.";
+ } else if (i < kPacketHeaderSize + 15) {
+ expected_error = "Unable to read offset.";
+ } else if (i < kPacketHeaderSize + 29) {
+ expected_error = "Unable to read fragment data.";
+ }
+
+ EXPECT_FALSE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet), i, false)));
+ EXPECT_EQ(expected_error, framer_.detailed_error());
+ EXPECT_EQ(QUIC_INVALID_FRAGMENT_DATA, framer_.error());
+ }
+}
+
+TEST_F(QuicFramerTest, RejectPacket) {
+ visitor_.accept_packet_ = false;
+
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+
+ // fragment count
+ 0x01,
+ // fragment type (stream fragment)
+ 0x00,
+ // stream id
+ 0x04, 0x03, 0x02, 0x01,
+ // fin
+ 0x01,
+ // offset
+ 0x54, 0x76, 0x10, 0x32,
+ 0xDC, 0xFE, 0x98, 0xBA,
+ // data length
+ 0x0c, 0x00,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!',
+ };
+
+ EXPECT_TRUE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet),
+ arraysize(packet), false)));
+
+ EXPECT_TRUE(CheckDecryption(StringPiece(AsChars(packet), arraysize(packet))));
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ ASSERT_EQ(address_, visitor_.address_);
+
+ ASSERT_EQ(0u, visitor_.stream_fragments_.size());
+ EXPECT_EQ(0u, visitor_.ack_fragments_.size());
+}
+
+TEST_F(QuicFramerTest, RevivedStreamFragment) {
+ unsigned char payload[] = {
+ // fragment count
+ 0x01,
+ // fragment type (stream fragment)
+ 0x00,
+ // stream id
+ 0x04, 0x03, 0x02, 0x01,
+ // fin
+ 0x01,
+ // offset
+ 0x54, 0x76, 0x10, 0x32,
+ 0xDC, 0xFE, 0x98, 0xBA,
+ // data length
+ 0x0c, 0x00,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!',
+ };
+
+ QuicPacketHeader header;
+ header.guid = 0xFEDCBA9876543210;
+ header.retransmission_count = 0x01;
+ header.packet_sequence_number = 0x123456789ABC;
+ header.transmission_time = 0xF0E1D2C3B4A59687;
+ header.flags = PACKET_FLAGS_NONE;
+ header.fec_group = 0;
+
+ // Do not encrypt the payload because the revived payload is post-encryption.
+ EXPECT_TRUE(framer_.ProcessRevivedPacket(address_,
+ header,
+ StringPiece(AsChars(payload),
+ arraysize(payload))));
+
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_EQ(address_, visitor_.address_);
+ ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_EQ(0xFEDCBA9876543210, visitor_.header_->guid);
+ EXPECT_EQ(0x1, visitor_.header_->retransmission_count);
+ EXPECT_EQ(static_cast<uint64>(0x123456789ABC),
+ visitor_.header_->packet_sequence_number);
+ EXPECT_EQ(static_cast<uint64>(0xF0E1D2C3B4A59687),
+ visitor_.header_->transmission_time);
+ EXPECT_EQ(0x00, visitor_.header_->flags);
+ EXPECT_EQ(0x00, visitor_.header_->fec_group);
+
+
+ ASSERT_EQ(1u, visitor_.stream_fragments_.size());
+ EXPECT_EQ(0u, visitor_.ack_fragments_.size());
+ EXPECT_EQ(static_cast<uint64>(0x01020304),
+ visitor_.stream_fragments_[0]->stream_id);
+ EXPECT_TRUE(visitor_.stream_fragments_[0]->fin);
+ EXPECT_EQ(0xBA98FEDC32107654, visitor_.stream_fragments_[0]->offset);
+ EXPECT_EQ("hello world!", visitor_.stream_fragments_[0]->data);
+}
+
+TEST_F(QuicFramerTest, StreamFragmentInFecGroup) {
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x12, 0x34,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x02,
+
+ // fragment count
+ 0x01,
+ // fragment type (stream fragment)
+ 0x00,
+ // stream id
+ 0x04, 0x03, 0x02, 0x01,
+ // fin
+ 0x01,
+ // offset
+ 0x54, 0x76, 0x10, 0x32,
+ 0xDC, 0xFE, 0x98, 0xBA,
+ // data length
+ 0x0c, 0x00,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!',
+ };
+
+ EXPECT_TRUE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet),
+ arraysize(packet), false)));
+
+ EXPECT_TRUE(CheckDecryption(StringPiece(AsChars(packet), arraysize(packet))));
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_EQ(2, visitor_.header_->fec_group);
+ EXPECT_EQ(string(AsChars(packet) + kStartOfFecProtectedData,
+ arraysize(packet) - kStartOfFecProtectedData),
+ visitor_.fec_protected_payload_);
+ ASSERT_EQ(address_, visitor_.address_);
+
+ ASSERT_EQ(1u, visitor_.stream_fragments_.size());
+ EXPECT_EQ(0u, visitor_.ack_fragments_.size());
+ EXPECT_EQ(static_cast<uint64>(0x01020304),
+ visitor_.stream_fragments_[0]->stream_id);
+ EXPECT_TRUE(visitor_.stream_fragments_[0]->fin);
+ EXPECT_EQ(0xBA98FEDC32107654, visitor_.stream_fragments_[0]->offset);
+ EXPECT_EQ("hello world!", visitor_.stream_fragments_[0]->data);
+}
+
+TEST_F(QuicFramerTest, AckFragment) {
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+
+ // fragment count
+ 0x01,
+ // fragment type (ack fragment)
+ 0x02,
+ // largest received packet sequence number
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // time delta
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // num_unacked_packets
+ 0x02,
+ // unacked packet sequence number
+ 0xBA, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // unacked packet sequence number
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // least packet sequence number awaiting an ack
+ 0xA0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // num non retransmitting packets
+ 0x03,
+ // non retransmitting packet sequence number
+ 0xAE, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xB0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // congestion feedback type (none)
+ 0x00,
+ };
+
+ EXPECT_TRUE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet),
+ arraysize(packet), false)));
+
+ EXPECT_TRUE(CheckDecryption(StringPiece(AsChars(packet), arraysize(packet))));
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+
+ EXPECT_EQ(0u, visitor_.stream_fragments_.size());
+ ASSERT_EQ(1u, visitor_.ack_fragments_.size());
+ const QuicAckFragment& fragment = *visitor_.ack_fragments_[0];
+ EXPECT_EQ(static_cast<uint64>(0x0123456789ABC),
+ fragment.received_info.largest_received);
+ EXPECT_EQ(0xF0E1D2C3B4A59687, fragment.received_info.time_received);
+
+ const hash_set<QuicPacketSequenceNumber>* sequence_nums =
+ &fragment.received_info.missing_packets;
+ ASSERT_EQ(2u, sequence_nums->size());
+ EXPECT_TRUE(sequence_nums->find(0x0123456789ABB) != sequence_nums->end());
+ EXPECT_TRUE(sequence_nums->find(0x0123456789ABA) != sequence_nums->end());
+ EXPECT_EQ(static_cast<uint64>(0x0123456789AA0),
+ fragment.sent_info.least_unacked);
+ ASSERT_EQ(3u, fragment.sent_info.non_retransmiting.size());
+ const hash_set<QuicPacketSequenceNumber>* non_retrans =
+ &fragment.sent_info.non_retransmiting;
+ EXPECT_TRUE(non_retrans->find(0x0123456789AB0) != non_retrans->end());
+ EXPECT_TRUE(non_retrans->find(0x0123456789AAF) != non_retrans->end());
+ EXPECT_TRUE(non_retrans->find(0x0123456789AAE) != non_retrans->end());
+ ASSERT_EQ(kNone, fragment.congestion_info.type);
+
+ // Now test framing boundaries
+ for (size_t i = kPacketHeaderSize; i < kPacketHeaderSize + 55; ++i) {
+ string expected_error;
+ if (i < kPacketHeaderSize + 1) {
+ expected_error = "Unable to read fragment count.";
+ } else if (i < kPacketHeaderSize + 2) {
+ expected_error = "Unable to read fragment type.";
+ } else if (i < kPacketHeaderSize + 8) {
+ expected_error = "Unable to read largest received.";
+ } else if (i < kPacketHeaderSize + 16) {
+ expected_error = "Unable to read time received.";
+ } else if (i < kPacketHeaderSize + 17) {
+ expected_error = "Unable to read num unacked packets.";
+ } else if (i < kPacketHeaderSize + 29) {
+ expected_error = "Unable to read sequence number in unacked packets.";
+ } else if (i < kPacketHeaderSize + 35) {
+ expected_error = "Unable to read least unacked.";
+ } else if (i < kPacketHeaderSize + 36) {
+ expected_error = "Unable to read num non-retransmitting.";
+ } else if (i < kPacketHeaderSize + 54) {
+ expected_error = "Unable to read sequence number in non-retransmitting.";
+ } else if (i < kPacketHeaderSize + 55) {
+ expected_error = "Unable to read congestion info type.";
+ }
+
+ EXPECT_FALSE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet), i, false)));
+ EXPECT_EQ(expected_error, framer_.detailed_error());
+ EXPECT_EQ(QUIC_INVALID_FRAGMENT_DATA, framer_.error());
+ }
+}
+
+TEST_F(QuicFramerTest, AckFragmentTCP) {
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+
+ // fragment count
+ 0x01,
+ // fragment type (ack fragment)
+ 0x02,
+ // largest received packet sequence number
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // time delta
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // num_unacked_packets
+ 0x02,
+ // unacked packet sequence number
+ 0xBA, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // unacked packet sequence number
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // least packet sequence number awaiting an ack
+ 0xA0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // num non retransmitting packets
+ 0x03,
+ // non retransmitting packet sequence number
+ 0xAE, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xB0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // congestion feedback type (tcp)
+ 0x01,
+ // ack_fragment.congestion_info.tcp.accumulated_number_of_lost_packets
+ 0x01, 0x02,
+ // ack_fragment.congestion_info.tcp.receive_window
+ 0x03, 0x04,
+ };
+
+ EXPECT_TRUE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet),
+ arraysize(packet), false)));
+
+ EXPECT_TRUE(CheckDecryption(StringPiece(AsChars(packet), arraysize(packet))));
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+
+ EXPECT_EQ(0u, visitor_.stream_fragments_.size());
+ ASSERT_EQ(1u, visitor_.ack_fragments_.size());
+ const QuicAckFragment& fragment = *visitor_.ack_fragments_[0];
+ EXPECT_EQ(static_cast<uint64>(0x0123456789ABC),
+ fragment.received_info.largest_received);
+ EXPECT_EQ(0xF0E1D2C3B4A59687, fragment.received_info.time_received);
+
+ const hash_set<QuicPacketSequenceNumber>* sequence_nums =
+ &fragment.received_info.missing_packets;
+ ASSERT_EQ(2u, sequence_nums->size());
+ EXPECT_TRUE(sequence_nums->find(0x0123456789ABB) != sequence_nums->end());
+ EXPECT_TRUE(sequence_nums->find(0x0123456789ABA) != sequence_nums->end());
+ EXPECT_EQ(static_cast<uint64>(0x0123456789AA0),
+ fragment.sent_info.least_unacked);
+ ASSERT_EQ(3u, fragment.sent_info.non_retransmiting.size());
+ const hash_set<QuicPacketSequenceNumber>* non_retrans =
+ &fragment.sent_info.non_retransmiting;
+ EXPECT_TRUE(non_retrans->find(0x0123456789AB0) != non_retrans->end());
+ EXPECT_TRUE(non_retrans->find(0x0123456789AAF) != non_retrans->end());
+ EXPECT_TRUE(non_retrans->find(0x0123456789AAE) != non_retrans->end());
+ ASSERT_EQ(kTCP, fragment.congestion_info.type);
+ EXPECT_EQ(0x0201,
+ fragment.congestion_info.tcp.accumulated_number_of_lost_packets);
+ EXPECT_EQ(0x0403, fragment.congestion_info.tcp.receive_window);
+
+ // Now test framing boundaries
+ for (size_t i = kCongestionInfoOffset; i < kCongestionInfoOffset + 5; ++i) {
+ string expected_error;
+ if (i < kCongestionInfoOffset + 1) {
+ expected_error = "Unable to read congestion info type.";
+ } else if (i < kCongestionInfoOffset + 3) {
+ expected_error = "Unable to read accumulated number of lost packets.";
+ } else if (i < kCongestionInfoOffset + 5) {
+ expected_error = "Unable to read receive window.";
+ }
+
+ EXPECT_FALSE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet), i, false)));
+ EXPECT_EQ(expected_error, framer_.detailed_error());
+ EXPECT_EQ(QUIC_INVALID_FRAGMENT_DATA, framer_.error());
+ }
+}
+
+TEST_F(QuicFramerTest, AckFragmentInterArrival) {
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+
+ // fragment count
+ 0x01,
+ // fragment type (ack fragment)
+ 0x02,
+ // largest received packet sequence number
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // time delta
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // num_unacked_packets
+ 0x02,
+ // unacked packet sequence number
+ 0xBA, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // unacked packet sequence number
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // least packet sequence number awaiting an ack
+ 0xA0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // num non retransmitting packets
+ 0x03,
+ // non retransmitting packet sequence number
+ 0xAE, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xB0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // congestion feedback type (inter arrival)
+ 0x02,
+ // accumulated_number_of_lost_packets
+ 0x02, 0x03,
+ // offset_time
+ 0x04, 0x05,
+ // delta_time
+ 0x06, 0x07,
+ };
+
+ EXPECT_TRUE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet),
+ arraysize(packet), false)));
+
+ EXPECT_TRUE(CheckDecryption(StringPiece(AsChars(packet), arraysize(packet))));
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+
+ EXPECT_EQ(0u, visitor_.stream_fragments_.size());
+ ASSERT_EQ(1u, visitor_.ack_fragments_.size());
+ const QuicAckFragment& fragment = *visitor_.ack_fragments_[0];
+ EXPECT_EQ(static_cast<uint64>(0x0123456789ABC),
+ fragment.received_info.largest_received);
+ EXPECT_EQ(0xF0E1D2C3B4A59687, fragment.received_info.time_received);
+
+ const hash_set<QuicPacketSequenceNumber>* sequence_nums =
+ &fragment.received_info.missing_packets;
+ ASSERT_EQ(2u, sequence_nums->size());
+ EXPECT_TRUE(sequence_nums->find(0x0123456789ABB) != sequence_nums->end());
+ EXPECT_TRUE(sequence_nums->find(0x0123456789ABA) != sequence_nums->end());
+ EXPECT_EQ(static_cast<uint64>(0x0123456789AA0),
+ fragment.sent_info.least_unacked);
+ ASSERT_EQ(3u, fragment.sent_info.non_retransmiting.size());
+ const hash_set<QuicPacketSequenceNumber>* non_retrans =
+ &fragment.sent_info.non_retransmiting;
+ EXPECT_TRUE(non_retrans->find(0x0123456789AB0) != non_retrans->end());
+ EXPECT_TRUE(non_retrans->find(0x0123456789AAF) != non_retrans->end());
+ EXPECT_TRUE(non_retrans->find(0x0123456789AAE) != non_retrans->end());
+ ASSERT_EQ(kInterArrival, fragment.congestion_info.type);
+ EXPECT_EQ(0x0302, fragment.congestion_info.inter_arrival.
+ accumulated_number_of_lost_packets);
+ EXPECT_EQ(0x0504,
+ fragment.congestion_info.inter_arrival.offset_time);
+ EXPECT_EQ(0x0706,
+ fragment.congestion_info.inter_arrival.delta_time);
+
+ // Now test framing boundaries
+ for (size_t i = kCongestionInfoOffset; i < kCongestionInfoOffset + 5; ++i) {
+ string expected_error;
+ if (i < kCongestionInfoOffset + 1) {
+ expected_error = "Unable to read congestion info type.";
+ } else if (i < kCongestionInfoOffset + 3) {
+ expected_error = "Unable to read accumulated number of lost packets.";
+ } else if (i < kCongestionInfoOffset + 5) {
+ expected_error = "Unable to read offset time.";
+ } else if (i < kCongestionInfoOffset + 7) {
+ expected_error = "Unable to read delta time.";
+ }
+ EXPECT_FALSE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet), i, false)));
+ EXPECT_EQ(expected_error, framer_.detailed_error());
+ EXPECT_EQ(QUIC_INVALID_FRAGMENT_DATA, framer_.error());
+ }
+}
+
+TEST_F(QuicFramerTest, AckFragmentFixRate) {
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+
+ // fragment count
+ 0x01,
+ // fragment type (ack fragment)
+ 0x02,
+ // largest received packet sequence number
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // time delta
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // num_unacked_packets
+ 0x02,
+ // unacked packet sequence number
+ 0xBA, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // unacked packet sequence number
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // least packet sequence number awaiting an ack
+ 0xA0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // num non retransmitting packets
+ 0x03,
+ // non retransmitting packet sequence number
+ 0xAE, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xB0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // congestion feedback type (fix rate)
+ 0x03,
+ // bitrate_in_bytes_per_second;
+ 0x01, 0x02, 0x03, 0x04,
+ };
+
+ EXPECT_TRUE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet),
+ arraysize(packet), false)));
+
+ EXPECT_TRUE(CheckDecryption(StringPiece(AsChars(packet), arraysize(packet))));
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+
+ EXPECT_EQ(0u, visitor_.stream_fragments_.size());
+ ASSERT_EQ(1u, visitor_.ack_fragments_.size());
+ const QuicAckFragment& fragment = *visitor_.ack_fragments_[0];
+ EXPECT_EQ(static_cast<uint64>(0x0123456789ABC),
+ fragment.received_info.largest_received);
+ EXPECT_EQ(0xF0E1D2C3B4A59687, fragment.received_info.time_received);
+
+ const hash_set<QuicPacketSequenceNumber>* sequence_nums =
+ &fragment.received_info.missing_packets;
+ ASSERT_EQ(2u, sequence_nums->size());
+ EXPECT_TRUE(sequence_nums->find(0x0123456789ABB) != sequence_nums->end());
+ EXPECT_TRUE(sequence_nums->find(0x0123456789ABA) != sequence_nums->end());
+ EXPECT_EQ(static_cast<uint64>(0x0123456789AA0),
+ fragment.sent_info.least_unacked);
+ ASSERT_EQ(3u, fragment.sent_info.non_retransmiting.size());
+ const hash_set<QuicPacketSequenceNumber>* non_retrans =
+ &fragment.sent_info.non_retransmiting;
+ EXPECT_TRUE(non_retrans->find(0x0123456789AB0) != non_retrans->end());
+ EXPECT_TRUE(non_retrans->find(0x0123456789AAF) != non_retrans->end());
+ EXPECT_TRUE(non_retrans->find(0x0123456789AAE) != non_retrans->end());
+ ASSERT_EQ(kFixRate, fragment.congestion_info.type);
+ EXPECT_EQ(static_cast<uint32>(0x04030201),
+ fragment.congestion_info.fix_rate.bitrate_in_bytes_per_second);
+
+ // Now test framing boundaries
+ for (size_t i = kCongestionInfoOffset; i < kCongestionInfoOffset + 5; ++i) {
+ string expected_error;
+ if (i < kCongestionInfoOffset + 1) {
+ expected_error = "Unable to read congestion info type.";
+ } else if (i < kCongestionInfoOffset + 5) {
+ expected_error = "Unable to read bitrate.";
+ }
+ EXPECT_FALSE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet), i, false)));
+ EXPECT_EQ(expected_error, framer_.detailed_error());
+ EXPECT_EQ(QUIC_INVALID_FRAGMENT_DATA, framer_.error());
+ }
+}
+
+
+TEST_F(QuicFramerTest, AckFragmentInvalidFeedback) {
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+
+ // fragment count
+ 0x01,
+ // fragment type (ack fragment)
+ 0x02,
+ // largest received packet sequence number
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // time delta
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // num_unacked_packets
+ 0x02,
+ // unacked packet sequence number
+ 0xBA, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // unacked packet sequence number
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // least packet sequence number awaiting an ack
+ 0xA0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // num non retransmitting packets
+ 0x03,
+ // non retransmitting packet sequence number
+ 0xAE, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xB0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // congestion feedback type (invalid)
+ 0x04,
+ };
+
+ EXPECT_FALSE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet),
+ arraysize(packet), false)));
+ EXPECT_TRUE(CheckDecryption(StringPiece(AsChars(packet), arraysize(packet))));
+ EXPECT_EQ(QUIC_INVALID_FRAGMENT_DATA, framer_.error());
+}
+
+TEST_F(QuicFramerTest, RstStreamFragment) {
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+
+ // fragment count
+ 0x01,
+ // fragment type (rst stream fragment)
+ 0x03,
+ // stream id
+ 0x04, 0x03, 0x02, 0x01,
+ // offset
+ 0x54, 0x76, 0x10, 0x32,
+ 0xDC, 0xFE, 0x98, 0xBA,
+ // details
+ 0x08, 0x07, 0x06, 0x05,
+ };
+
+ EXPECT_TRUE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet),
+ arraysize(packet), false)));
+
+ EXPECT_TRUE(CheckDecryption(StringPiece(AsChars(packet), arraysize(packet))));
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ ASSERT_EQ(address_, visitor_.address_);
+
+ EXPECT_EQ(static_cast<uint64>(0x01020304),
+ visitor_.rst_stream_fragment_.stream_id);
+ EXPECT_EQ(0x05060708, visitor_.rst_stream_fragment_.details);
+ EXPECT_EQ(0xBA98FEDC32107654, visitor_.rst_stream_fragment_.offset);
+
+ // Now test framing boundaries
+ for (size_t i = kPacketHeaderSize + 3; i < kPacketHeaderSize + 18; ++i) {
+ string expected_error;
+ if (i < kPacketHeaderSize + 6) {
+ expected_error = "Unable to read stream_id.";
+ } else if (i < kPacketHeaderSize + 14) {
+ expected_error = "Unable to read offset in rst fragment.";
+ } else if (i < kPacketHeaderSize + 18) {
+ expected_error = "Unable to read rst stream details.";
+ }
+ EXPECT_FALSE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet), i, false)));
+ EXPECT_EQ(expected_error, framer_.detailed_error());
+ EXPECT_EQ(QUIC_INVALID_RST_STREAM_DATA, framer_.error());
+ }
+}
+
+TEST_F(QuicFramerTest, ConnectionCloseFragment) {
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+
+
+ // fragment count
+ 0x01,
+ // fragment type (connection close fragment)
+ 0x04,
+ // details
+ 0x08, 0x07, 0x06, 0x05,
+
+ // Ack fragment.
+
+ // largest received packet sequence number
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // time delta
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // num_unacked_packets
+ 0x02,
+ // unacked packet sequence number
+ 0xBA, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // unacked packet sequence number
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // least packet sequence number awaiting an ack
+ 0xA0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // num non retransmitting packets
+ 0x03,
+ // non retransmitting packet sequence number
+ 0xAE, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xB0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // congestion feedback type (inter arrival)
+ 0x02,
+ // accumulated_number_of_lost_packets
+ 0x02, 0x03,
+ // offset_time
+ 0x04, 0x05,
+ // delta_time
+ 0x06, 0x07,
+ };
+
+ EXPECT_TRUE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet),
+ arraysize(packet), false)));
+
+ EXPECT_TRUE(CheckDecryption(StringPiece(AsChars(packet), arraysize(packet))));
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+
+ EXPECT_EQ(0u, visitor_.stream_fragments_.size());
+
+ EXPECT_EQ(0x05060708, visitor_.connection_close_fragment_.details);
+
+ ASSERT_EQ(1u, visitor_.ack_fragments_.size());
+ const QuicAckFragment& fragment = *visitor_.ack_fragments_[0];
+ EXPECT_EQ(static_cast<uint64>(0x0123456789ABC),
+ fragment.received_info.largest_received);
+ EXPECT_EQ(0xF0E1D2C3B4A59687, fragment.received_info.time_received);
+
+ const hash_set<QuicPacketSequenceNumber>* sequence_nums =
+ &fragment.received_info.missing_packets;
+ ASSERT_EQ(2u, sequence_nums->size());
+ EXPECT_TRUE(sequence_nums->find(0x0123456789ABB) != sequence_nums->end());
+ EXPECT_TRUE(sequence_nums->find(0x0123456789ABA) != sequence_nums->end());
+ EXPECT_EQ(static_cast<uint64>(0x0123456789AA0),
+ fragment.sent_info.least_unacked);
+ ASSERT_EQ(3u, fragment.sent_info.non_retransmiting.size());
+ const hash_set<QuicPacketSequenceNumber>* non_retrans =
+ &fragment.sent_info.non_retransmiting;
+ EXPECT_TRUE(non_retrans->find(0x0123456789AB0) != non_retrans->end());
+ EXPECT_TRUE(non_retrans->find(0x0123456789AAF) != non_retrans->end());
+ EXPECT_TRUE(non_retrans->find(0x0123456789AAE) != non_retrans->end());
+ ASSERT_EQ(kInterArrival, fragment.congestion_info.type);
+ EXPECT_EQ(0x0302, fragment.congestion_info.inter_arrival.
+ accumulated_number_of_lost_packets);
+ EXPECT_EQ(0x0504,
+ fragment.congestion_info.inter_arrival.offset_time);
+ EXPECT_EQ(0x0706,
+ fragment.congestion_info.inter_arrival.delta_time);
+
+ // Now test framing boundaries
+ for (size_t i = kPacketHeaderSize + 3; i < kPacketHeaderSize + 6; ++i) {
+ string expected_error;
+ if (i < kPacketHeaderSize + 6) {
+ expected_error = "Unable to read connection close details.";
+ }
+ EXPECT_FALSE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet), i, false)));
+ EXPECT_EQ(expected_error, framer_.detailed_error());
+ EXPECT_EQ(QUIC_INVALID_CONNECTION_CLOSE_DATA, framer_.error());
+ }
+}
+
+TEST_F(QuicFramerTest, FecPacket) {
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags (FEC)
+ 0x01,
+ // fec group
+ 0x01,
+
+ // first protected packet
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // redundancy
+ 'a', 'b', 'c', 'd',
+ 'e', 'f', 'g', 'h',
+ 'i', 'j', 'k', 'l',
+ 'm', 'n', 'o', 'p',
+ };
+
+ EXPECT_TRUE(framer_.ProcessPacket(
+ address_, QuicEncryptedPacket(AsChars(packet),
+ arraysize(packet), false)));
+
+ EXPECT_TRUE(CheckDecryption(StringPiece(AsChars(packet), arraysize(packet))));
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+
+ EXPECT_EQ(0u, visitor_.stream_fragments_.size());
+ EXPECT_EQ(0u, visitor_.ack_fragments_.size());
+ ASSERT_EQ(1, visitor_.fec_count_);
+ const QuicFecData& fec_data = *visitor_.fec_data_[0];
+ EXPECT_EQ(static_cast<uint64>(0x0123456789ABB),
+ fec_data.first_protected_packet_sequence_number);
+ EXPECT_EQ("abcdefghijklmnop", fec_data.redundancy);
+}
+
+TEST_F(QuicFramerTest, ConstructStreamFragmentPacket) {
+ QuicPacketHeader header;
+ header.guid = 0xFEDCBA9876543210;
+ header.retransmission_count = 0x01;
+ header.packet_sequence_number = 0x123456789ABC;
+ header.transmission_time = 0xF0E1D2C3B4A59687;
+ header.flags = PACKET_FLAGS_NONE;
+ header.fec_group = 0;
+
+ QuicStreamFragment stream_fragment;
+ stream_fragment.stream_id = 0x01020304;
+ stream_fragment.fin = true;
+ stream_fragment.offset = 0xBA98FEDC32107654;
+ stream_fragment.data = "hello world!";
+
+ QuicFragment fragment;
+ fragment.type = STREAM_FRAGMENT;
+ fragment.stream_fragment = &stream_fragment;
+
+ QuicFragments fragments;
+ fragments.push_back(fragment);
+
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+
+ // fragment count
+ 0x01,
+ // fragment type (stream fragment)
+ 0x00,
+ // stream id
+ 0x04, 0x03, 0x02, 0x01,
+ // fin
+ 0x01,
+ // offset
+ 0x54, 0x76, 0x10, 0x32,
+ 0xDC, 0xFE, 0x98, 0xBA,
+ // data length
+ 0x0c, 0x00,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!',
+ };
+
+ QuicPacket* data;
+ ASSERT_TRUE(framer_.ConstructFragementDataPacket(header, fragments, &data));
+
+ test::CompareCharArraysWithHexError("constructed packet",
+ data->data(), data->length(),
+ AsChars(packet), arraysize(packet));
+
+ delete data;
+}
+
+TEST_F(QuicFramerTest, ConstructAckFragmentPacket) {
+ QuicPacketHeader header;
+ header.guid = 0xFEDCBA9876543210;
+ header.retransmission_count = 0x01;
+ header.packet_sequence_number = 0x123456789ABC;
+ header.transmission_time = 0xF0E1D2C3B4A59687;
+ header.flags = PACKET_FLAGS_NONE;
+ header.fec_group = 0;
+
+ QuicAckFragment ack_fragment;
+ ack_fragment.received_info.largest_received = 0x0123456789ABC;
+ ack_fragment.received_info.time_received = 0xF0E1D2C3B4A59687;
+ ack_fragment.received_info.missing_packets.insert(0x0123456789ABB);
+ ack_fragment.received_info.missing_packets.insert(0x0123456789ABA);
+ ack_fragment.sent_info.least_unacked = 0x0123456789AA0;
+ ack_fragment.sent_info.non_retransmiting.insert(0x0123456789AB0);
+ ack_fragment.sent_info.non_retransmiting.insert(0x0123456789AAF);
+ ack_fragment.sent_info.non_retransmiting.insert(0x0123456789AAE);
+ ack_fragment.congestion_info.type = kNone;
+
+ QuicFragment fragment;
+ fragment.type = ACK_FRAGMENT;
+ fragment.ack_fragment = &ack_fragment;
+
+ QuicFragments fragments;
+ fragments.push_back(fragment);
+
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+
+ // fragment count
+ 0x01,
+ // fragment type (ack fragment)
+ 0x02,
+ // largest received packet sequence number
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // time delta
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // num_unacked_packets
+ 0x02,
+#if defined(OS_WIN)
+ // unacked packet sequence number
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // unacked packet sequence number
+ 0xBA, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#else
+ // unacked packet sequence number
+ 0xBA, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // unacked packet sequence number
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#endif
+ // least packet sequence number awaiting an ack
+ 0xA0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // num non retransmitting packets
+ 0x03,
+#if defined(OS_WIN)
+ // non retransmitting packet sequence number
+ 0xB0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAE, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#else
+ // non retransmitting packet sequence number
+ 0xAE, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xB0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#endif
+ // congestion feedback type (none)
+ 0x00,
+ };
+
+ QuicPacket* data;
+ EXPECT_TRUE(framer_.ConstructFragementDataPacket(header, fragments, &data));
+
+ test::CompareCharArraysWithHexError("constructed packet",
+ data->data(), data->length(),
+ AsChars(packet), arraysize(packet));
+
+ delete data;
+}
+
+TEST_F(QuicFramerTest, ConstructAckFragmentPacketTCP) {
+ QuicPacketHeader header;
+ header.guid = 0xFEDCBA9876543210;
+ header.retransmission_count = 0x01;
+ header.packet_sequence_number = 0x123456789ABC;
+ header.transmission_time = 0xF0E1D2C3B4A59687;
+ header.flags = PACKET_FLAGS_NONE;
+ header.fec_group = 0;
+
+ QuicAckFragment ack_fragment;
+ ack_fragment.received_info.largest_received = 0x0123456789ABC;
+ ack_fragment.received_info.time_received = 0xF0E1D2C3B4A59687;
+ ack_fragment.received_info.missing_packets.insert(0x0123456789ABB);
+ ack_fragment.received_info.missing_packets.insert(0x0123456789ABA);
+ ack_fragment.sent_info.least_unacked = 0x0123456789AA0;
+ ack_fragment.sent_info.non_retransmiting.insert(0x0123456789AB0);
+ ack_fragment.sent_info.non_retransmiting.insert(0x0123456789AAF);
+ ack_fragment.sent_info.non_retransmiting.insert(0x0123456789AAE);
+ ack_fragment.congestion_info.type = kTCP;
+ ack_fragment.congestion_info.tcp.accumulated_number_of_lost_packets = 0x0201;
+ ack_fragment.congestion_info.tcp.receive_window = 0x0403;
+
+ QuicFragment fragment;
+ fragment.type = ACK_FRAGMENT;
+ fragment.ack_fragment = &ack_fragment;
+
+ QuicFragments fragments;
+ fragments.push_back(fragment);
+
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+
+ // fragment count
+ 0x01,
+ // fragment type (ack fragment)
+ 0x02,
+ // largest received packet sequence number
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // time delta
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // num_unacked_packets
+ 0x02,
+#if defined(OS_WIN)
+ // unacked packet sequence number
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // unacked packet sequence number
+ 0xBA, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#else
+ // unacked packet sequence number
+ 0xBA, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // unacked packet sequence number
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#endif
+ // least packet sequence number awaiting an ack
+ 0xA0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // num non retransmitting packets
+ 0x03,
+#if defined(OS_WIN)
+ // non retransmitting packet sequence number
+ 0xB0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAE, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#else
+ // non retransmitting packet sequence number
+ 0xAE, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xB0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#endif
+ // congestion feedback type (tcp)
+ 0x01,
+ // ack_fragment.congestion_info.tcp.accumulated_number_of_lost_packets
+ 0x01, 0x02,
+ // ack_fragment.congestion_info.tcp.receive_window
+ 0x03, 0x04,
+ };
+
+ QuicPacket* data;
+ EXPECT_TRUE(framer_.ConstructFragementDataPacket(header, fragments, &data));
+
+ test::CompareCharArraysWithHexError("constructed packet",
+ data->data(), data->length(),
+ AsChars(packet), arraysize(packet));
+
+ delete data;
+}
+
+TEST_F(QuicFramerTest, ConstructAckFragmentPacketInterArrival) {
+ QuicPacketHeader header;
+ header.guid = 0xFEDCBA9876543210;
+ header.retransmission_count = 0x01;
+ header.packet_sequence_number = 0x123456789ABC;
+ header.transmission_time = 0xF0E1D2C3B4A59687;
+ header.flags = PACKET_FLAGS_NONE;
+ header.fec_group = 0;
+
+ QuicAckFragment ack_fragment;
+ ack_fragment.received_info.largest_received = 0x0123456789ABC;
+ ack_fragment.received_info.time_received = 0xF0E1D2C3B4A59687;
+ ack_fragment.received_info.missing_packets.insert(0x0123456789ABB);
+ ack_fragment.received_info.missing_packets.insert(0x0123456789ABA);
+ ack_fragment.sent_info.least_unacked = 0x0123456789AA0;
+ ack_fragment.sent_info.non_retransmiting.insert(0x0123456789AB0);
+ ack_fragment.sent_info.non_retransmiting.insert(0x0123456789AAF);
+ ack_fragment.sent_info.non_retransmiting.insert(0x0123456789AAE);
+ ack_fragment.congestion_info.type = kInterArrival;
+ ack_fragment.congestion_info.inter_arrival.accumulated_number_of_lost_packets
+ = 0x0302;
+ ack_fragment.congestion_info.inter_arrival.offset_time = 0x0504;
+ ack_fragment.congestion_info.inter_arrival.delta_time = 0x0706;
+
+ QuicFragment fragment;
+ fragment.type = ACK_FRAGMENT;
+ fragment.ack_fragment = &ack_fragment;
+
+ QuicFragments fragments;
+ fragments.push_back(fragment);
+
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+
+ // fragment count
+ 0x01,
+ // fragment type (ack fragment)
+ 0x02,
+ // largest received packet sequence number
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // time delta
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // num_unacked_packets
+ 0x02,
+#if defined(OS_WIN)
+ // unacked packet sequence number
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // unacked packet sequence number
+ 0xBA, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#else
+ // unacked packet sequence number
+ 0xBA, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // unacked packet sequence number
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#endif
+ // least packet sequence number awaiting an ack
+ 0xA0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // num non retransmitting packets
+ 0x03,
+#if defined(OS_WIN)
+ // non retransmitting packet sequence number
+ 0xB0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAE, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#else
+ // non retransmitting packet sequence number
+ 0xAE, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xB0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#endif
+ // congestion feedback type (inter arrival)
+ 0x02,
+ // accumulated_number_of_lost_packets
+ 0x02, 0x03,
+ // offset_time
+ 0x04, 0x05,
+ // delta_time
+ 0x06, 0x07,
+ };
+
+ QuicPacket* data;
+ EXPECT_TRUE(framer_.ConstructFragementDataPacket(header, fragments, &data));
+
+ test::CompareCharArraysWithHexError("constructed packet",
+ data->data(), data->length(),
+ AsChars(packet), arraysize(packet));
+
+ delete data;
+}
+
+TEST_F(QuicFramerTest, ConstructAckFragmentPacketFixRate) {
+ QuicPacketHeader header;
+ header.guid = 0xFEDCBA9876543210;
+ header.retransmission_count = 0x01;
+ header.packet_sequence_number = 0x123456789ABC;
+ header.transmission_time = 0xF0E1D2C3B4A59687;
+ header.flags = PACKET_FLAGS_NONE;
+ header.fec_group = 0;
+
+ QuicAckFragment ack_fragment;
+ ack_fragment.received_info.largest_received = 0x0123456789ABC;
+ ack_fragment.received_info.time_received = 0xF0E1D2C3B4A59687;
+ ack_fragment.received_info.missing_packets.insert(0x0123456789ABB);
+ ack_fragment.received_info.missing_packets.insert(0x0123456789ABA);
+ ack_fragment.sent_info.least_unacked = 0x0123456789AA0;
+ ack_fragment.sent_info.non_retransmiting.insert(0x0123456789AB0);
+ ack_fragment.sent_info.non_retransmiting.insert(0x0123456789AAF);
+ ack_fragment.sent_info.non_retransmiting.insert(0x0123456789AAE);
+ ack_fragment.congestion_info.type = kFixRate;
+ ack_fragment.congestion_info.fix_rate.bitrate_in_bytes_per_second
+ = 0x04030201;
+
+ QuicFragment fragment;
+ fragment.type = ACK_FRAGMENT;
+ fragment.ack_fragment = &ack_fragment;
+
+ QuicFragments fragments;
+ fragments.push_back(fragment);
+
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+
+ // fragment count
+ 0x01,
+ // fragment type (ack fragment)
+ 0x02,
+ // largest received packet sequence number
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // time delta
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // num_unacked_packets
+ 0x02,
+#if defined(OS_WIN)
+ // unacked packet sequence number
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // unacked packet sequence number
+ 0xBA, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#else
+ // unacked packet sequence number
+ 0xBA, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // unacked packet sequence number
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#endif
+ // least packet sequence number awaiting an ack
+ 0xA0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // num non retransmitting packets
+ 0x03,
+#if defined(OS_WIN)
+ // non retransmitting packet sequence number
+ 0xB0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAE, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#else
+ // non retransmitting packet sequence number
+ 0xAE, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xB0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#endif
+ // congestion feedback type (fix rate)
+ 0x03,
+ // bitrate_in_bytes_per_second;
+ 0x01, 0x02, 0x03, 0x04,
+ };
+
+ QuicPacket* data;
+ EXPECT_TRUE(framer_.ConstructFragementDataPacket(header, fragments, &data));
+
+ test::CompareCharArraysWithHexError("constructed packet",
+ data->data(), data->length(),
+ AsChars(packet), arraysize(packet));
+
+ delete data;
+}
+
+TEST_F(QuicFramerTest, ConstructAckFragmentPacketInvalidFeedback) {
+ QuicPacketHeader header;
+ header.guid = 0xFEDCBA9876543210;
+ header.retransmission_count = 0x01;
+ header.packet_sequence_number = 0x123456789ABC;
+ header.transmission_time = 0xF0E1D2C3B4A59687;
+ header.flags = PACKET_FLAGS_NONE;
+ header.fec_group = 0;
+
+ QuicAckFragment ack_fragment;
+ ack_fragment.received_info.largest_received = 0x0123456789ABC;
+ ack_fragment.received_info.time_received = 0xF0E1D2C3B4A59687;
+ ack_fragment.received_info.missing_packets.insert(0x0123456789ABB);
+ ack_fragment.received_info.missing_packets.insert(0x0123456789ABA);
+ ack_fragment.sent_info.least_unacked = 0x0123456789AA0;
+ ack_fragment.sent_info.non_retransmiting.insert(0x0123456789AB0);
+ ack_fragment.sent_info.non_retransmiting.insert(0x0123456789AAF);
+ ack_fragment.sent_info.non_retransmiting.insert(0x0123456789AAE);
+ ack_fragment.congestion_info.type =
+ static_cast<CongestionFeedbackType>(kFixRate + 1);
+
+ QuicFragment fragment;
+ fragment.type = ACK_FRAGMENT;
+ fragment.ack_fragment = &ack_fragment;
+
+ QuicFragments fragments;
+ fragments.push_back(fragment);
+
+ QuicPacket* data;
+ EXPECT_FALSE(framer_.ConstructFragementDataPacket(header, fragments, &data));
+}
+
+TEST_F(QuicFramerTest, ConstructRstFragmentPacket) {
+ QuicPacketHeader header;
+ header.guid = 0xFEDCBA9876543210;
+ header.retransmission_count = 0x01;
+ header.packet_sequence_number = 0x123456789ABC;
+ header.transmission_time = 0xF0E1D2C3B4A59687;
+ header.flags = PACKET_FLAGS_NONE;
+ header.fec_group = 0;
+
+ QuicRstStreamFragment rst_fragment;
+ rst_fragment.stream_id = 0x01020304;
+ rst_fragment.details = static_cast<QuicErrorCode>(0x05060708);
+ rst_fragment.offset = 0xBA98FEDC32107654;
+
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+
+ // fragment count
+ 0x01,
+ // fragment type (rst stream fragment)
+ 0x03,
+ // stream id
+ 0x04, 0x03, 0x02, 0x01,
+ // offset
+ 0x54, 0x76, 0x10, 0x32,
+ 0xDC, 0xFE, 0x98, 0xBA,
+ // details
+ 0x08, 0x07, 0x06, 0x05,
+ };
+
+ QuicFragment fragment(&rst_fragment);
+
+ QuicFragments fragments;
+ fragments.push_back(fragment);
+
+ QuicPacket* data;
+ EXPECT_TRUE(framer_.ConstructFragementDataPacket(header, fragments, &data));
+
+ test::CompareCharArraysWithHexError("constructed packet",
+ data->data(), data->length(),
+ AsChars(packet), arraysize(packet));
+
+ delete data;
+}
+
+TEST_F(QuicFramerTest, ConstructCloseFragmentPacket) {
+ QuicPacketHeader header;
+ header.guid = 0xFEDCBA9876543210;
+ header.retransmission_count = 0x01;
+ header.packet_sequence_number = 0x123456789ABC;
+ header.transmission_time = 0xF0E1D2C3B4A59687;
+ header.flags = PACKET_FLAGS_NONE;
+ header.fec_group = 0;
+
+ QuicConnectionCloseFragment close_fragment;
+ close_fragment.details = static_cast<QuicErrorCode>(0x05060708);
+
+ QuicAckFragment* ack_fragment = &close_fragment.ack_fragment;
+ ack_fragment->received_info.largest_received = 0x0123456789ABC;
+ ack_fragment->received_info.time_received = 0xF0E1D2C3B4A59687;
+ ack_fragment->received_info.missing_packets.insert(0x0123456789ABB);
+ ack_fragment->received_info.missing_packets.insert(0x0123456789ABA);
+ ack_fragment->sent_info.least_unacked = 0x0123456789AA0;
+ ack_fragment->sent_info.non_retransmiting.insert(0x0123456789AB0);
+ ack_fragment->sent_info.non_retransmiting.insert(0x0123456789AAF);
+ ack_fragment->sent_info.non_retransmiting.insert(0x0123456789AAE);
+ ack_fragment->congestion_info.type = kInterArrival;
+ ack_fragment->congestion_info.inter_arrival.accumulated_number_of_lost_packets
+ = 0x0302;
+ ack_fragment->congestion_info.inter_arrival.offset_time = 0x0504;
+ ack_fragment->congestion_info.inter_arrival.delta_time = 0x0706;
+
+ QuicFragment fragment(&close_fragment);
+
+ QuicFragments fragments;
+ fragments.push_back(fragment);
+
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x00,
+ // fec group
+ 0x00,
+
+ // fragment count
+ 0x01,
+ // fragment type (connection close fragment)
+ 0x04,
+ // details
+ 0x08, 0x07, 0x06, 0x05,
+
+ // Ack fragment.
+
+ // largest received packet sequence number
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // time delta
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // num_unacked_packets
+ 0x02,
+#if defined(OS_WIN)
+ // unacked packet sequence number
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // unacked packet sequence number
+ 0xBA, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#else
+ // unacked packet sequence number
+ 0xBA, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // unacked packet sequence number
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#endif
+ // least packet sequence number awaiting an ack
+ 0xA0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // num non retransmitting packets
+ 0x03,
+#if defined(OS_WIN)
+ // non retransmitting packet sequence number
+ 0xB0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAE, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#else
+ // non retransmitting packet sequence number
+ 0xAE, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xAF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // non retransmitting packet sequence number
+ 0xB0, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+#endif
+ // congestion feedback type (inter arrival)
+ 0x02,
+ // accumulated_number_of_lost_packets
+ 0x02, 0x03,
+ // offset_time
+ 0x04, 0x05,
+ // delta_time
+ 0x06, 0x07,
+ };
+
+ QuicPacket* data;
+ EXPECT_TRUE(framer_.ConstructFragementDataPacket(header, fragments, &data));
+
+ test::CompareCharArraysWithHexError("constructed packet",
+ data->data(), data->length(),
+ AsChars(packet), arraysize(packet));
+
+ delete data;
+}
+
+TEST_F(QuicFramerTest, ConstructFecPacket) {
+ QuicPacketHeader header;
+ header.guid = 0xFEDCBA9876543210;
+ header.retransmission_count = 0x01;
+ header.packet_sequence_number = 0x123456789ABC;
+ header.transmission_time = 0xF0E1D2C3B4A59687;
+ header.flags = PACKET_FLAGS_FEC;
+ header.fec_group = 1;
+
+ QuicFecData fec_data;
+ fec_data.fec_group = 1;
+ fec_data.first_protected_packet_sequence_number = 0x123456789ABB;
+ fec_data.redundancy = "abcdefghijklmnop";
+
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x01,
+ // fec group
+ 0x01,
+ // first protected packet
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // redundancy
+ 'a', 'b', 'c', 'd',
+ 'e', 'f', 'g', 'h',
+ 'i', 'j', 'k', 'l',
+ 'm', 'n', 'o', 'p',
+ };
+
+ QuicPacket* data;
+ EXPECT_TRUE(framer_.ConstructFecPacket(header, fec_data, &data));
+
+ test::CompareCharArraysWithHexError("constructed packet",
+ data->data(), data->length(),
+ AsChars(packet), arraysize(packet));
+
+ delete data;
+}
+
+TEST_F(QuicFramerTest, IncrementRetransmitCount) {
+ QuicPacketHeader header;
+ header.guid = 0xFEDCBA9876543210;
+ header.retransmission_count = 1;
+ header.packet_sequence_number = 0x123456789ABC;
+ header.transmission_time = 0xF0E1D2C3B4A59687;
+ header.flags = PACKET_FLAGS_NONE;
+ header.fec_group = 0;
+
+ QuicStreamFragment stream_fragment;
+ stream_fragment.stream_id = 0x01020304;
+ stream_fragment.fin = true;
+ stream_fragment.offset = 0xBA98FEDC32107654;
+ stream_fragment.data = "hello world!";
+
+ QuicFragment fragment;
+ fragment.type = STREAM_FRAGMENT;
+ fragment.stream_fragment = &stream_fragment;
+
+ QuicFragments fragments;
+ fragments.push_back(fragment);
+
+ QuicPacket *original;
+ ASSERT_TRUE(framer_.ConstructFragementDataPacket(
+ header, fragments, &original));
+ EXPECT_EQ(header.retransmission_count, framer_.GetRetransmitCount(original));
+
+ header.retransmission_count = 2;
+ QuicPacket *retransmitted;
+ ASSERT_TRUE(framer_.ConstructFragementDataPacket(
+ header, fragments, &retransmitted));
+
+ framer_.IncrementRetransmitCount(original);
+ EXPECT_EQ(header.retransmission_count, framer_.GetRetransmitCount(original));
+
+ test::CompareCharArraysWithHexError(
+ "constructed packet", original->data(), original->length(),
+ retransmitted->data(), retransmitted->length());
+ delete original;
+ delete retransmitted;
+}
+
+TEST_F(QuicFramerTest, EncryptPacket) {
+ unsigned char packet[] = {
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet id
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // retransmission count
+ 0x01,
+ // transmission time
+ 0x87, 0x96, 0xA5, 0xB4,
+ 0xC3, 0xD2, 0xE1, 0xF0,
+ // flags
+ 0x01,
+ // fec group
+ 0x01,
+ // first protected packet
+ 0xBB, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // redundancy
+ 'a', 'b', 'c', 'd',
+ 'e', 'f', 'g', 'h',
+ 'i', 'j', 'k', 'l',
+ 'm', 'n', 'o', 'p',
+ };
+
+ scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(
+ QuicPacket(AsChars(packet), arraysize(packet), false)));
+ ASSERT_TRUE(encrypted.get() != NULL);
+ EXPECT_TRUE(CheckEncryption(StringPiece(AsChars(packet), arraysize(packet))));
+}
+
+} // namespace test
+
+} // namespace net
« no previous file with comments | « net/quic/quic_framer.cc ('k') | net/quic/quic_protocol.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698