blob: cb44dad100be8f489db24a8c96950c739778c487 [file] [log] [blame]
// 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 "net/third_party/quic/core/quic_framer.h"
#include <algorithm>
#include <cstdint>
#include <map>
#include <memory>
#include <vector>
#include "net/third_party/quic/core/crypto/null_decrypter.h"
#include "net/third_party/quic/core/crypto/null_encrypter.h"
#include "net/third_party/quic/core/crypto/quic_decrypter.h"
#include "net/third_party/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quic/core/quic_packets.h"
#include "net/third_party/quic/core/quic_types.h"
#include "net/third_party/quic/core/quic_utils.h"
#include "net/third_party/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quic/platform/api/quic_flags.h"
#include "net/third_party/quic/platform/api/quic_logging.h"
#include "net/third_party/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quic/platform/api/quic_string.h"
#include "net/third_party/quic/platform/api/quic_test.h"
#include "net/third_party/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quic/test_tools/quic_framer_peer.h"
#include "net/third_party/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quic/test_tools/simple_data_producer.h"
#include "starboard/memory.h"
using testing::_;
using testing::Return;
using testing::Truly;
namespace quic {
namespace test {
namespace {
const uint64_t kEpoch = UINT64_C(1) << 32;
const uint64_t kMask = kEpoch - 1;
const QuicUint128 kTestStatelessResetToken = 1010101; // 0x0F69B5
// Use fields in which each byte is distinct to ensure that every byte is
// framed correctly. The values are otherwise arbitrary.
QuicConnectionId FramerTestConnectionId() {
return TestConnectionId(UINT64_C(0xFEDCBA9876543210));
}
QuicConnectionId FramerTestConnectionIdPlusOne() {
return TestConnectionId(UINT64_C(0xFEDCBA9876543211));
}
const QuicPacketNumber kPacketNumber = QuicPacketNumber(UINT64_C(0x12345678));
const QuicPacketNumber kSmallLargestObserved =
QuicPacketNumber(UINT16_C(0x1234));
const QuicPacketNumber kSmallMissingPacket = QuicPacketNumber(UINT16_C(0x1233));
const QuicPacketNumber kLeastUnacked = QuicPacketNumber(UINT64_C(0x012345670));
const QuicStreamId kStreamId = UINT64_C(0x01020304);
// Note that the high 4 bits of the stream offset must be less than 0x40
// in order to ensure that the value can be encoded using VarInt62 encoding.
const QuicStreamOffset kStreamOffset = UINT64_C(0x3A98FEDC32107654);
const QuicPublicResetNonceProof kNonceProof = UINT64_C(0xABCDEF0123456789);
// In testing that we can ack the full range of packets...
// This is the largest packet number that can be represented in IETF QUIC
// varint62 format.
const QuicPacketNumber kLargestIetfLargestObserved =
QuicPacketNumber(UINT64_C(0x3fffffffffffffff));
// Encodings for the two bits in a VarInt62 that
// describe the length of the VarInt61. For binary packet
// formats in this file, the convention is to code the
// first byte as
// kVarInt62FourBytes + 0x<value_in_that_byte>
const uint8_t kVarInt62OneByte = 0x00;
const uint8_t kVarInt62TwoBytes = 0x40;
const uint8_t kVarInt62FourBytes = 0x80;
const uint8_t kVarInt62EightBytes = 0xc0;
class TestEncrypter : public QuicEncrypter {
public:
~TestEncrypter() override {}
bool SetKey(QuicStringPiece key) override { return true; }
bool SetNoncePrefix(QuicStringPiece nonce_prefix) override { return true; }
bool SetIV(QuicStringPiece iv) override { return true; }
bool EncryptPacket(uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece plaintext,
char* output,
size_t* output_length,
size_t max_output_length) override {
packet_number_ = QuicPacketNumber(packet_number);
associated_data_ = QuicString(associated_data);
plaintext_ = QuicString(plaintext);
memcpy(output, plaintext.data(), plaintext.length());
*output_length = plaintext.length();
return true;
}
size_t GetKeySize() const override { return 0; }
size_t GetNoncePrefixSize() const override { return 0; }
size_t GetIVSize() const override { return 0; }
size_t GetMaxPlaintextSize(size_t ciphertext_size) const override {
return ciphertext_size;
}
size_t GetCiphertextSize(size_t plaintext_size) const override {
return plaintext_size;
}
QuicStringPiece GetKey() const override { return QuicStringPiece(); }
QuicStringPiece GetNoncePrefix() const override { return QuicStringPiece(); }
QuicPacketNumber packet_number_;
QuicString associated_data_;
QuicString plaintext_;
};
class TestDecrypter : public QuicDecrypter {
public:
~TestDecrypter() override {}
bool SetKey(QuicStringPiece key) override { return true; }
bool SetNoncePrefix(QuicStringPiece nonce_prefix) override { return true; }
bool SetIV(QuicStringPiece iv) override { return true; }
bool SetPreliminaryKey(QuicStringPiece key) override {
QUIC_BUG << "should not be called";
return false;
}
bool SetDiversificationNonce(const DiversificationNonce& key) override {
return true;
}
bool DecryptPacket(uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece ciphertext,
char* output,
size_t* output_length,
size_t max_output_length) override {
packet_number_ = QuicPacketNumber(packet_number);
associated_data_ = QuicString(associated_data);
ciphertext_ = QuicString(ciphertext);
memcpy(output, ciphertext.data(), ciphertext.length());
*output_length = ciphertext.length();
return true;
}
size_t GetKeySize() const override { return 0; }
size_t GetIVSize() const override { return 0; }
QuicStringPiece GetKey() const override { return QuicStringPiece(); }
QuicStringPiece GetNoncePrefix() const override { return QuicStringPiece(); }
// Use a distinct value starting with 0xFFFFFF, which is never used by TLS.
uint32_t cipher_id() const override { return 0xFFFFFFF2; }
QuicPacketNumber packet_number_;
QuicString associated_data_;
QuicString ciphertext_;
};
class TestQuicVisitor : public QuicFramerVisitorInterface {
public:
TestQuicVisitor()
: error_count_(0),
version_mismatch_(0),
packet_count_(0),
frame_count_(0),
complete_packets_(0),
accept_packet_(true),
accept_public_header_(true) {}
~TestQuicVisitor() override {}
void OnError(QuicFramer* f) override {
QUIC_DLOG(INFO) << "QuicFramer Error: " << QuicErrorCodeToString(f->error())
<< " (" << f->error() << ")";
++error_count_;
}
void OnPacket() override {}
void OnPublicResetPacket(const QuicPublicResetPacket& packet) override {
public_reset_packet_ = QuicMakeUnique<QuicPublicResetPacket>((packet));
}
void OnVersionNegotiationPacket(
const QuicVersionNegotiationPacket& packet) override {
version_negotiation_packet_ =
QuicMakeUnique<QuicVersionNegotiationPacket>((packet));
}
bool OnProtocolVersionMismatch(ParsedQuicVersion received_version,
PacketHeaderFormat /*form*/) override {
QUIC_DLOG(INFO) << "QuicFramer Version Mismatch, version: "
<< received_version;
++version_mismatch_;
return true;
}
bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override {
header_ = QuicMakeUnique<QuicPacketHeader>((header));
return accept_public_header_;
}
bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override {
return true;
}
void OnDecryptedPacket(EncryptionLevel level) override {}
bool OnPacketHeader(const QuicPacketHeader& header) override {
++packet_count_;
header_ = QuicMakeUnique<QuicPacketHeader>((header));
return accept_packet_;
}
void OnCoalescedPacket(const QuicEncryptedPacket& packet) override {
size_t coalesced_data_length = packet.length();
char* coalesced_data = new char[coalesced_data_length];
memcpy(coalesced_data, packet.data(), coalesced_data_length);
coalesced_packets_.push_back(QuicMakeUnique<QuicEncryptedPacket>(
coalesced_data, coalesced_data_length,
/*owns_buffer=*/true));
}
bool OnStreamFrame(const QuicStreamFrame& frame) override {
++frame_count_;
// Save a copy of the data so it is valid after the packet is processed.
QuicString* string_data =
new QuicString(frame.data_buffer, frame.data_length);
stream_data_.push_back(QuicWrapUnique(string_data));
stream_frames_.push_back(QuicMakeUnique<QuicStreamFrame>(
frame.stream_id, frame.fin, frame.offset, *string_data));
return true;
}
bool OnCryptoFrame(const QuicCryptoFrame& frame) override {
++frame_count_;
// Save a copy of the data so it is valid after the packet is processed.
QuicString* string_data =
new QuicString(frame.data_buffer, frame.data_length);
crypto_data_.push_back(QuicWrapUnique(string_data));
crypto_frames_.push_back(QuicMakeUnique<QuicCryptoFrame>(
ENCRYPTION_NONE, frame.offset, *string_data));
return true;
}
bool OnAckFrameStart(QuicPacketNumber largest_acked,
QuicTime::Delta ack_delay_time) override {
++frame_count_;
QuicAckFrame ack_frame;
ack_frame.largest_acked = largest_acked;
ack_frame.ack_delay_time = ack_delay_time;
ack_frames_.push_back(QuicMakeUnique<QuicAckFrame>(ack_frame));
return true;
}
bool OnAckRange(QuicPacketNumber start, QuicPacketNumber end) override {
DCHECK(!ack_frames_.empty());
ack_frames_[ack_frames_.size() - 1]->packets.AddRange(start, end);
return true;
}
bool OnAckTimestamp(QuicPacketNumber packet_number,
QuicTime timestamp) override {
ack_frames_[ack_frames_.size() - 1]->received_packet_times.push_back(
std::make_pair(packet_number, timestamp));
return true;
}
bool OnAckFrameEnd(QuicPacketNumber /*start*/) override { return true; }
bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override {
++frame_count_;
stop_waiting_frames_.push_back(QuicMakeUnique<QuicStopWaitingFrame>(frame));
return true;
}
bool OnPaddingFrame(const QuicPaddingFrame& frame) override {
padding_frames_.push_back(QuicMakeUnique<QuicPaddingFrame>(frame));
return true;
}
bool OnPingFrame(const QuicPingFrame& frame) override {
++frame_count_;
ping_frames_.push_back(QuicMakeUnique<QuicPingFrame>(frame));
return true;
}
bool OnMessageFrame(const QuicMessageFrame& frame) override {
++frame_count_;
message_frames_.push_back(
QuicMakeUnique<QuicMessageFrame>(frame.data, frame.message_length));
return true;
}
void OnPacketComplete() override { ++complete_packets_; }
bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override {
rst_stream_frame_ = frame;
return true;
}
bool OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override {
connection_close_frame_ = frame;
return true;
}
bool OnApplicationCloseFrame(
const QuicApplicationCloseFrame& frame) override {
application_close_frame_ = frame;
return true;
}
bool OnStopSendingFrame(const QuicStopSendingFrame& frame) override {
stop_sending_frame_ = frame;
return true;
}
bool OnPathChallengeFrame(const QuicPathChallengeFrame& frame) override {
path_challenge_frame_ = frame;
return true;
}
bool OnPathResponseFrame(const QuicPathResponseFrame& frame) override {
path_response_frame_ = frame;
return true;
}
bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override {
goaway_frame_ = frame;
return true;
}
bool OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) override {
max_stream_id_frame_ = frame;
return true;
}
bool OnStreamIdBlockedFrame(const QuicStreamIdBlockedFrame& frame) override {
stream_id_blocked_frame_ = frame;
return true;
}
bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override {
window_update_frame_ = frame;
return true;
}
bool OnBlockedFrame(const QuicBlockedFrame& frame) override {
blocked_frame_ = frame;
return true;
}
bool OnNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame) override {
new_connection_id_ = frame;
return true;
}
bool OnRetireConnectionIdFrame(
const QuicRetireConnectionIdFrame& frame) override {
retire_connection_id_ = frame;
return true;
}
bool OnNewTokenFrame(const QuicNewTokenFrame& frame) override {
new_token_ = frame;
return true;
}
bool IsValidStatelessResetToken(QuicUint128 token) const override {
return token == kTestStatelessResetToken;
}
void OnAuthenticatedIetfStatelessResetPacket(
const QuicIetfStatelessResetPacket& packet) override {
stateless_reset_packet_ =
QuicMakeUnique<QuicIetfStatelessResetPacket>(packet);
}
// Counters from the visitor_ callbacks.
int error_count_;
int version_mismatch_;
int packet_count_;
int frame_count_;
int complete_packets_;
bool accept_packet_;
bool accept_public_header_;
std::unique_ptr<QuicPacketHeader> header_;
std::unique_ptr<QuicPublicResetPacket> public_reset_packet_;
std::unique_ptr<QuicIetfStatelessResetPacket> stateless_reset_packet_;
std::unique_ptr<QuicVersionNegotiationPacket> version_negotiation_packet_;
std::vector<std::unique_ptr<QuicStreamFrame>> stream_frames_;
std::vector<std::unique_ptr<QuicCryptoFrame>> crypto_frames_;
std::vector<std::unique_ptr<QuicAckFrame>> ack_frames_;
std::vector<std::unique_ptr<QuicStopWaitingFrame>> stop_waiting_frames_;
std::vector<std::unique_ptr<QuicPaddingFrame>> padding_frames_;
std::vector<std::unique_ptr<QuicPingFrame>> ping_frames_;
std::vector<std::unique_ptr<QuicMessageFrame>> message_frames_;
std::vector<std::unique_ptr<QuicEncryptedPacket>> coalesced_packets_;
QuicRstStreamFrame rst_stream_frame_;
QuicConnectionCloseFrame connection_close_frame_;
QuicApplicationCloseFrame application_close_frame_;
QuicStopSendingFrame stop_sending_frame_;
QuicGoAwayFrame goaway_frame_;
QuicPathChallengeFrame path_challenge_frame_;
QuicPathResponseFrame path_response_frame_;
QuicWindowUpdateFrame window_update_frame_;
QuicBlockedFrame blocked_frame_;
QuicStreamIdBlockedFrame stream_id_blocked_frame_;
QuicMaxStreamIdFrame max_stream_id_frame_;
QuicNewConnectionIdFrame new_connection_id_;
QuicRetireConnectionIdFrame retire_connection_id_;
QuicNewTokenFrame new_token_;
std::vector<std::unique_ptr<QuicString>> stream_data_;
std::vector<std::unique_ptr<QuicString>> crypto_data_;
};
// Simple struct for defining a packet's content, and associated
// parse error.
struct PacketFragment {
QuicString error_if_missing;
std::vector<unsigned char> fragment;
};
using PacketFragments = std::vector<struct PacketFragment>;
ParsedQuicVersionVector AllSupportedVersionsIncludingTls() {
QuicFlagSaver flags;
SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
return AllSupportedVersions();
}
class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
public:
QuicFramerTest()
: encrypter_(new test::TestEncrypter()),
decrypter_(new test::TestDecrypter()),
version_(GetParam()),
start_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(0x10)),
framer_(AllSupportedVersionsIncludingTls(),
start_,
Perspective::IS_SERVER) {
SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
framer_.set_version(version_);
framer_.SetDecrypter(ENCRYPTION_NONE,
std::unique_ptr<QuicDecrypter>(decrypter_));
framer_.SetEncrypter(ENCRYPTION_NONE,
std::unique_ptr<QuicEncrypter>(encrypter_));
framer_.set_visitor(&visitor_);
framer_.InferPacketHeaderTypeFromVersion();
}
// Helper function to get unsigned char representation of the handshake
// protocol byte of the current QUIC version number.
unsigned char GetQuicVersionProtocolByte() {
return (CreateQuicVersionLabel(version_) >> 24) & 0xff;
}
// Helper function to get unsigned char representation of digit in the
// units place of the current QUIC version number.
unsigned char GetQuicVersionDigitOnes() {
return CreateQuicVersionLabel(version_) & 0xff;
}
// Helper function to get unsigned char representation of digit in the
// tens place of the current QUIC version number.
unsigned char GetQuicVersionDigitTens() {
return (CreateQuicVersionLabel(version_) >> 8) & 0xff;
}
bool CheckEncryption(QuicPacketNumber packet_number, QuicPacket* packet) {
if (packet_number != encrypter_->packet_number_) {
QUIC_LOG(ERROR) << "Encrypted incorrect packet number. expected "
<< packet_number
<< " actual: " << encrypter_->packet_number_;
return false;
}
if (packet->AssociatedData(framer_.transport_version()) !=
encrypter_->associated_data_) {
QUIC_LOG(ERROR) << "Encrypted incorrect associated data. expected "
<< packet->AssociatedData(framer_.transport_version())
<< " actual: " << encrypter_->associated_data_;
return false;
}
if (packet->Plaintext(framer_.transport_version()) !=
encrypter_->plaintext_) {
QUIC_LOG(ERROR) << "Encrypted incorrect plaintext data. expected "
<< packet->Plaintext(framer_.transport_version())
<< " actual: " << encrypter_->plaintext_;
return false;
}
return true;
}
bool CheckDecryption(const QuicEncryptedPacket& encrypted,
bool includes_version,
bool includes_diversification_nonce,
QuicConnectionIdLength destination_connection_id_length,
QuicConnectionIdLength source_connection_id_length) {
return CheckDecryption(
encrypted, includes_version, includes_diversification_nonce,
destination_connection_id_length, source_connection_id_length,
VARIABLE_LENGTH_INTEGER_LENGTH_0, 0, VARIABLE_LENGTH_INTEGER_LENGTH_0);
}
bool CheckDecryption(
const QuicEncryptedPacket& encrypted,
bool includes_version,
bool includes_diversification_nonce,
QuicConnectionIdLength destination_connection_id_length,
QuicConnectionIdLength source_connection_id_length,
QuicVariableLengthIntegerLength retry_token_length_length,
size_t retry_token_length,
QuicVariableLengthIntegerLength length_length) {
if (visitor_.header_->packet_number != decrypter_->packet_number_) {
QUIC_LOG(ERROR) << "Decrypted incorrect packet number. expected "
<< visitor_.header_->packet_number
<< " actual: " << decrypter_->packet_number_;
return false;
}
QuicStringPiece associated_data =
QuicFramer::GetAssociatedDataFromEncryptedPacket(
framer_.transport_version(), encrypted,
destination_connection_id_length, source_connection_id_length,
includes_version, includes_diversification_nonce,
PACKET_4BYTE_PACKET_NUMBER, retry_token_length_length,
retry_token_length, length_length);
if (associated_data != decrypter_->associated_data_) {
QUIC_LOG(ERROR) << "Decrypted incorrect associated data. expected "
<< QuicTextUtils::HexEncode(associated_data)
<< " actual: "
<< QuicTextUtils::HexEncode(decrypter_->associated_data_);
return false;
}
QuicStringPiece ciphertext(
encrypted.AsStringPiece().substr(GetStartOfEncryptedData(
framer_.transport_version(), destination_connection_id_length,
source_connection_id_length, includes_version,
includes_diversification_nonce, PACKET_4BYTE_PACKET_NUMBER,
retry_token_length_length, retry_token_length, length_length)));
if (ciphertext != decrypter_->ciphertext_) {
QUIC_LOG(ERROR) << "Decrypted incorrect ciphertext data. expected "
<< QuicTextUtils::HexEncode(ciphertext) << " actual: "
<< QuicTextUtils::HexEncode(decrypter_->ciphertext_)
<< " associated data: "
<< QuicTextUtils::HexEncode(associated_data);
return false;
}
return true;
}
char* AsChars(unsigned char* data) { return reinterpret_cast<char*>(data); }
// Creates a new QuicEncryptedPacket by concatenating the various
// packet fragments in |fragments|.
std::unique_ptr<QuicEncryptedPacket> AssemblePacketFromFragments(
const PacketFragments& fragments) {
char* buffer = new char[kMaxPacketSize + 1];
size_t len = 0;
for (const auto& fragment : fragments) {
memcpy(buffer + len, fragment.fragment.data(),
fragment.fragment.size());
len += fragment.fragment.size();
}
return QuicMakeUnique<QuicEncryptedPacket>(buffer, len, true);
}
void CheckFramingBoundaries(const PacketFragments& fragments,
QuicErrorCode error_code) {
std::unique_ptr<QuicEncryptedPacket> packet(
AssemblePacketFromFragments(fragments));
// Check all the various prefixes of |packet| for the expected
// parse error and error code.
for (size_t i = 0; i < packet->length(); ++i) {
QuicString expected_error;
size_t len = 0;
for (const auto& fragment : fragments) {
len += fragment.fragment.size();
if (i < len) {
expected_error = fragment.error_if_missing;
break;
}
}
if (expected_error.empty())
continue;
CheckProcessingFails(*packet, i, expected_error, error_code);
}
}
void CheckProcessingFails(const QuicEncryptedPacket& packet,
size_t len,
QuicString expected_error,
QuicErrorCode error_code) {
QuicEncryptedPacket encrypted(packet.data(), len, false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted)) << "len: " << len;
EXPECT_EQ(expected_error, framer_.detailed_error()) << "len: " << len;
EXPECT_EQ(error_code, framer_.error()) << "len: " << len;
}
void CheckProcessingFails(unsigned char* packet,
size_t len,
QuicString expected_error,
QuicErrorCode error_code) {
QuicEncryptedPacket encrypted(AsChars(packet), len, false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted)) << "len: " << len;
EXPECT_EQ(expected_error, framer_.detailed_error()) << "len: " << len;
EXPECT_EQ(error_code, framer_.error()) << "len: " << len;
}
// Checks if the supplied string matches data in the supplied StreamFrame.
void CheckStreamFrameData(QuicString str, QuicStreamFrame* frame) {
EXPECT_EQ(str, QuicString(frame->data_buffer, frame->data_length));
}
void CheckCalculatePacketNumber(uint64_t expected_packet_number,
QuicPacketNumber last_packet_number) {
uint64_t wire_packet_number = expected_packet_number & kMask;
EXPECT_EQ(expected_packet_number,
QuicFramerPeer::CalculatePacketNumberFromWire(
&framer_, PACKET_4BYTE_PACKET_NUMBER, last_packet_number,
wire_packet_number))
<< "last_packet_number: " << last_packet_number
<< " wire_packet_number: " << wire_packet_number;
}
std::unique_ptr<QuicPacket> BuildDataPacket(const QuicPacketHeader& header,
const QuicFrames& frames) {
return BuildUnsizedDataPacket(&framer_, header, frames);
}
std::unique_ptr<QuicPacket> BuildDataPacket(const QuicPacketHeader& header,
const QuicFrames& frames,
size_t packet_size) {
return BuildUnsizedDataPacket(&framer_, header, frames, packet_size);
}
// N starts at 1.
QuicStreamId GetNthStreamid(QuicTransportVersion transport_version,
Perspective perspective,
bool bidirectional,
int n) {
if (bidirectional) {
return QuicUtils::GetFirstBidirectionalStreamId(transport_version,
perspective) +
((n - 1) * QuicUtils::StreamIdDelta(transport_version));
}
// Unidirectional
return QuicUtils::GetFirstUnidirectionalStreamId(transport_version,
perspective) +
((n - 1) * QuicUtils::StreamIdDelta(transport_version));
}
test::TestEncrypter* encrypter_;
test::TestDecrypter* decrypter_;
ParsedQuicVersion version_;
QuicTime start_;
QuicFramer framer_;
test::TestQuicVisitor visitor_;
SimpleBufferAllocator allocator_;
};
// Multiple test cases of QuicFramerTest use byte arrays to define packets for
// testing, and these byte arrays contain the QUIC version. This macro explodes
// the 32-bit version into four bytes in network order. Since it uses methods of
// QuicFramerTest, it is only valid to use this in a QuicFramerTest.
#define QUIC_VERSION_BYTES \
GetQuicVersionProtocolByte(), '0', GetQuicVersionDigitTens(), \
GetQuicVersionDigitOnes()
// Run all framer tests with all supported versions of QUIC.
INSTANTIATE_TEST_SUITE_P(
QuicFramerTests,
QuicFramerTest,
::testing::ValuesIn(AllSupportedVersionsIncludingTls()));
TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearEpochStart) {
// A few quick manual sanity checks.
CheckCalculatePacketNumber(UINT64_C(1), QuicPacketNumber());
CheckCalculatePacketNumber(kEpoch + 1, QuicPacketNumber(kMask));
CheckCalculatePacketNumber(kEpoch, QuicPacketNumber(kMask));
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(j, QuicPacketNumber());
CheckCalculatePacketNumber(kEpoch - 1 - j, QuicPacketNumber());
}
// Cases where the last number was close to the start of the range.
for (QuicPacketNumber last = QuicPacketNumber(1); last < QuicPacketNumber(10);
last++) {
// Small numbers should not wrap (even if they're out of order).
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(j, last);
}
// Large numbers should not wrap either (because we're near 0 already).
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(kEpoch - 1 - j, last);
}
}
}
TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearEpochEnd) {
// Cases where the last number was close to the end of the range
for (uint64_t i = 0; i < 10; i++) {
QuicPacketNumber last = QuicPacketNumber(kEpoch - i);
// Small numbers should wrap.
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(kEpoch + j, last);
}
// Large numbers should not (even if they're out of order).
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(kEpoch - 1 - j, last);
}
}
}
// Next check where we're in a non-zero epoch to verify we handle
// reverse wrapping, too.
TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearPrevEpoch) {
const uint64_t prev_epoch = 1 * kEpoch;
const uint64_t cur_epoch = 2 * kEpoch;
// Cases where the last number was close to the start of the range
for (uint64_t i = 0; i < 10; i++) {
QuicPacketNumber last = QuicPacketNumber(cur_epoch + i);
// Small number should not wrap (even if they're out of order).
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(cur_epoch + j, last);
}
// But large numbers should reverse wrap.
for (uint64_t j = 0; j < 10; j++) {
uint64_t num = kEpoch - 1 - j;
CheckCalculatePacketNumber(prev_epoch + num, last);
}
}
}
TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearNextEpoch) {
const uint64_t cur_epoch = 2 * kEpoch;
const uint64_t next_epoch = 3 * kEpoch;
// Cases where the last number was close to the end of the range
for (uint64_t i = 0; i < 10; i++) {
QuicPacketNumber last = QuicPacketNumber(next_epoch - 1 - i);
// Small numbers should wrap.
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(next_epoch + j, last);
}
// but large numbers should not (even if they're out of order).
for (uint64_t j = 0; j < 10; j++) {
uint64_t num = kEpoch - 1 - j;
CheckCalculatePacketNumber(cur_epoch + num, last);
}
}
}
TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearNextMax) {
const uint64_t max_number = std::numeric_limits<uint64_t>::max();
const uint64_t max_epoch = max_number & ~kMask;
// Cases where the last number was close to the end of the range
for (uint64_t i = 0; i < 10; i++) {
// Subtract 1, because the expected next packet number is 1 more than the
// last packet number.
QuicPacketNumber last = QuicPacketNumber(max_number - i - 1);
// Small numbers should not wrap, because they have nowhere to go.
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(max_epoch + j, last);
}
// Large numbers should not wrap either.
for (uint64_t j = 0; j < 10; j++) {
uint64_t num = kEpoch - 1 - j;
CheckCalculatePacketNumber(max_epoch + num, last);
}
}
}
TEST_P(QuicFramerTest, EmptyPacket) {
char packet[] = {0x00};
QuicEncryptedPacket encrypted(packet, 0, false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
}
TEST_P(QuicFramerTest, LargePacket) {
// clang-format off
unsigned char packet[kMaxPacketSize + 1] = {
// public flags (8 byte connection_id)
0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x78, 0x56, 0x34, 0x12,
// private flags
0x00,
};
unsigned char packet44[kMaxPacketSize + 1] = {
// type (short header 4 byte packet number)
0x32,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x78, 0x56, 0x34, 0x12,
};
unsigned char packet46[kMaxPacketSize + 1] = {
// type (short header 4 byte packet number)
0x43,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x78, 0x56, 0x34, 0x12,
};
// clang-format on
unsigned char* p = packet;
size_t p_size = QUIC_ARRAYSIZE(packet);
if (framer_.transport_version() > QUIC_VERSION_44) {
p = packet46;
p_size = QUIC_ARRAYSIZE(packet46);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
}
const size_t header_size = GetPacketHeaderSize(
framer_.transport_version(), PACKET_8BYTE_CONNECTION_ID,
PACKET_0BYTE_CONNECTION_ID, !kIncludeVersion,
!kIncludeDiversificationNonce, PACKET_4BYTE_PACKET_NUMBER,
VARIABLE_LENGTH_INTEGER_LENGTH_0, 0, VARIABLE_LENGTH_INTEGER_LENGTH_0);
memset(p + header_size, 0, kMaxPacketSize - header_size);
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
EXPECT_QUIC_BUG(framer_.ProcessPacket(encrypted), "Packet too large:1");
ASSERT_TRUE(visitor_.header_.get());
// Make sure we've parsed the packet header, so we can send an error.
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
// Make sure the correct error is propagated.
EXPECT_EQ(QUIC_PACKET_TOO_LARGE, framer_.error());
}
TEST_P(QuicFramerTest, PacketHeader) {
if (framer_.transport_version() > QUIC_VERSION_43) {
return;
}
// clang-format off
PacketFragments packet = {
// public flags (8 byte connection_id)
{"Unable to read public flags.",
{0x28}},
// connection_id
{"Unable to read ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
// clang-format on
PacketFragments& fragments = packet;
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_FALSE(visitor_.header_->reset_flag);
EXPECT_FALSE(visitor_.header_->version_flag);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER);
}
TEST_P(QuicFramerTest, LongPacketHeader) {
// clang-format off
PacketFragments packet44 = {
// type (long header with packet type INITIAL)
{"Unable to read type.",
{0xFF}},
// version tag
{"Unable to read protocol version.",
{QUIC_VERSION_BYTES}},
// connection_id length
{"Unable to read ConnectionId length.",
{0x50}},
// connection_id
{"Unable to read Destination ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
PacketFragments packet46 = {
// type (long header with packet type INITIAL)
{"Unable to read type.",
{0xC3}},
// version tag
{"Unable to read protocol version.",
{QUIC_VERSION_BYTES}},
// connection_id length
{"Unable to read ConnectionId length.",
{0x50}},
// connection_id
{"Unable to read Destination ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
// clang-format on
if (framer_.transport_version() <= QUIC_VERSION_43 ||
QuicVersionHasLongHeaderLengths(framer_.transport_version())) {
return;
}
PacketFragments& fragments =
framer_.transport_version() > QUIC_VERSION_44 ? packet46 : packet44;
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_FALSE(visitor_.header_->reset_flag);
EXPECT_TRUE(visitor_.header_->version_flag);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
CheckFramingBoundaries(
framer_.transport_version() > QUIC_VERSION_44 ? packet46 : packet44,
QUIC_INVALID_PACKET_HEADER);
}
TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) {
QuicFramerPeer::SetLastSerializedConnectionId(&framer_,
FramerTestConnectionId());
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
// clang-format off
PacketFragments packet = {
// public flags (0 byte connection_id)
{"Unable to read public flags.",
{0x20}},
// connection_id
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
PacketFragments packet44 = {
// type (short header, 4 byte packet number)
{"Unable to read type.",
{0x32}},
// connection_id
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
PacketFragments packet46 = {
// type (short header, 4 byte packet number)
{"Unable to read type.",
{0x43}},
// connection_id
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
// clang-format on
PacketFragments& fragments =
framer_.transport_version() > QUIC_VERSION_44
? packet46
: (framer_.transport_version() > QUIC_VERSION_43 ? packet44 : packet);
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_FALSE(visitor_.header_->reset_flag);
EXPECT_FALSE(visitor_.header_->version_flag);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER);
}
TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) {
// clang-format off
PacketFragments packet = {
// public flags (0 byte connection_id)
{"Unable to read public flags.",
{0x29}},
// connection_id
{"Unable to read ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// version tag
{"Unable to read protocol version.",
{QUIC_VERSION_BYTES}},
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
PacketFragments packet44 = {
// type (long header with packet type ZERO_RTT_PROTECTED)
{"Unable to read type.",
{0xFC}},
// version tag
{"Unable to read protocol version.",
{QUIC_VERSION_BYTES}},
// connection_id length
{"Unable to read ConnectionId length.",
{0x50}},
// connection_id
{"Unable to read Destination ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
PacketFragments packet46 = {
// type (long header with packet type ZERO_RTT_PROTECTED and 4 bytes
// packet number)
{"Unable to read type.",
{0xD3}},
// version tag
{"Unable to read protocol version.",
{QUIC_VERSION_BYTES}},
// connection_id length
{"Unable to read ConnectionId length.",
{0x50}},
// connection_id
{"Unable to read Destination ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
PacketFragments packet99 = {
// type (long header with packet type ZERO_RTT_PROTECTED and 4 bytes
// packet number)
{"Unable to read type.",
{0xD3}},
// version tag
{"Unable to read protocol version.",
{QUIC_VERSION_BYTES}},
// connection_id length
{"Unable to read ConnectionId length.",
{0x50}},
// connection_id
{"Unable to read Destination ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// long header packet length
{"Unable to read long header payload length.",
{0x04}},
// packet number
{"Long header payload length longer than packet.",
{0x12, 0x34, 0x56, 0x78}},
};
// clang-format on
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
: framer_.transport_version() > QUIC_VERSION_44
? packet46
: (framer_.transport_version() > QUIC_VERSION_43 ? packet44
: packet);
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_FALSE(visitor_.header_->reset_flag);
EXPECT_TRUE(visitor_.header_->version_flag);
EXPECT_EQ(GetParam(), visitor_.header_->version);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER);
}
TEST_P(QuicFramerTest, PacketHeaderWith4BytePacketNumber) {
QuicFramerPeer::SetLargestPacketNumber(&framer_, kPacketNumber - 2);
// clang-format off
PacketFragments packet = {
// public flags (8 byte connection_id and 4 byte packet number)
{"Unable to read public flags.",
{0x28}},
// connection_id
{"Unable to read ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
PacketFragments packet44 = {
// type (short header, 4 byte packet number)
{"Unable to read type.",
{0x32}},
// connection_id
{"Unable to read Destination ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
PacketFragments packet46 = {
// type (short header, 4 byte packet number)
{"Unable to read type.",
{0x43}},
// connection_id
{"Unable to read Destination ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
// clang-format on
PacketFragments& fragments =
framer_.transport_version() > QUIC_VERSION_44
? packet46
: (framer_.transport_version() > QUIC_VERSION_43 ? packet44 : packet);
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_FALSE(visitor_.header_->reset_flag);
EXPECT_FALSE(visitor_.header_->version_flag);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER);
}
TEST_P(QuicFramerTest, PacketHeaderWith2BytePacketNumber) {
QuicFramerPeer::SetLargestPacketNumber(&framer_, kPacketNumber - 2);
// clang-format off
PacketFragments packet = {
// public flags (8 byte connection_id and 2 byte packet number)
{"Unable to read public flags.",
{0x18}},
// connection_id
{"Unable to read ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x56, 0x78}},
};
PacketFragments packet44 = {
// type (short header, 2 byte packet number)
{"Unable to read type.",
{0x31}},
// connection_id
{"Unable to read Destination ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x56, 0x78}},
};
PacketFragments packet46 = {
// type (short header, 2 byte packet number)
{"Unable to read type.",
{0x41}},
// connection_id
{"Unable to read Destination ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x56, 0x78}},
};
// clang-format on
PacketFragments& fragments =
framer_.transport_version() > QUIC_VERSION_44
? packet46
: (framer_.transport_version() > QUIC_VERSION_43 ? packet44 : packet);
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_FALSE(visitor_.header_->reset_flag);
EXPECT_FALSE(visitor_.header_->version_flag);
EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER, visitor_.header_->packet_number_length);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER);
}
TEST_P(QuicFramerTest, PacketHeaderWith1BytePacketNumber) {
QuicFramerPeer::SetLargestPacketNumber(&framer_, kPacketNumber - 2);
// clang-format off
PacketFragments packet = {
// public flags (8 byte connection_id and 1 byte packet number)
{"Unable to read public flags.",
{0x08}},
// connection_id
{"Unable to read ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x78}},
};
PacketFragments packet44 = {
// type (8 byte connection_id and 1 byte packet number)
{"Unable to read type.",
{0x30}},
// connection_id
{"Unable to read Destination ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x78}},
};
PacketFragments packet46 = {
// type (8 byte connection_id and 1 byte packet number)
{"Unable to read type.",
{0x40}},
// connection_id
{"Unable to read Destination ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x78}},
};
// clang-format on
PacketFragments& fragments =
framer_.transport_version() > QUIC_VERSION_44
? packet46
: (framer_.transport_version() > QUIC_VERSION_43 ? packet44 : packet);
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_FALSE(visitor_.header_->reset_flag);
EXPECT_FALSE(visitor_.header_->version_flag);
EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, visitor_.header_->packet_number_length);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER);
}
TEST_P(QuicFramerTest, PacketNumberDecreasesThenIncreases) {
// Test the case when a packet is received from the past and future packet
// numbers are still calculated relative to the largest received packet.
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
header.version_flag = false;
header.packet_number = kPacketNumber - 2;
QuicFrames frames = {QuicFrame(QuicPaddingFrame())};
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
QuicEncryptedPacket encrypted(data->data(), data->length(), false);
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER, visitor_.header_->packet_number_length);
EXPECT_EQ(kPacketNumber - 2, visitor_.header_->packet_number);
// Receive a 1 byte packet number.
header.packet_number = kPacketNumber;
header.packet_number_length = PACKET_1BYTE_PACKET_NUMBER;
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
data = BuildDataPacket(header, frames);
QuicEncryptedPacket encrypted1(data->data(), data->length(), false);
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
EXPECT_TRUE(framer_.ProcessPacket(encrypted1));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, visitor_.header_->packet_number_length);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
// Process a 2 byte packet number 256 packets ago.
header.packet_number = kPacketNumber - 256;
header.packet_number_length = PACKET_2BYTE_PACKET_NUMBER;
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
data = BuildDataPacket(header, frames);
QuicEncryptedPacket encrypted2(data->data(), data->length(), false);
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
EXPECT_TRUE(framer_.ProcessPacket(encrypted2));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER, visitor_.header_->packet_number_length);
EXPECT_EQ(kPacketNumber - 256, visitor_.header_->packet_number);
// Process another 1 byte packet number and ensure it works.
header.packet_number = kPacketNumber - 1;
header.packet_number_length = PACKET_1BYTE_PACKET_NUMBER;
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
data = BuildDataPacket(header, frames);
QuicEncryptedPacket encrypted3(data->data(), data->length(), false);
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
EXPECT_TRUE(framer_.ProcessPacket(encrypted3));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, visitor_.header_->packet_number_length);
EXPECT_EQ(kPacketNumber - 1, visitor_.header_->packet_number);
}
TEST_P(QuicFramerTest, PacketWithDiversificationNonce) {
// clang-format off
unsigned char packet[] = {
// public flags: includes nonce flag
0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// nonce
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
// packet number
0x12, 0x34, 0x56, 0x78,
// frame type (padding)
0x00,
0x00, 0x00, 0x00, 0x00
};
unsigned char packet44[] = {
// type: Long header with packet type ZERO_RTT_PROTECTED
0xFC,
// version tag
QUIC_VERSION_BYTES,
// connection_id length
0x05,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
// nonce
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
// frame type (padding)
0x00,
0x00, 0x00, 0x00, 0x00
};
unsigned char packet46[] = {
// type: Long header with packet type ZERO_RTT_PROTECTED and 1 byte packet
// number.
0xD0,
// version tag
QUIC_VERSION_BYTES,
// connection_id length
0x05,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x78,
// nonce
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
// frame type (padding)
0x00,
0x00, 0x00, 0x00, 0x00
};
unsigned char packet99[] = {
// type: Long header with packet type ZERO_RTT_PROTECTED and 1 byte packet
// number.
0xD0,
// version tag
QUIC_VERSION_BYTES,
// connection_id length
0x05,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// long header packet length
0x26,
// packet number
0x78,
// nonce
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
// frame type (padding)
0x00,
0x00, 0x00, 0x00, 0x00
};
// clang-format on
if (framer_.version().handshake_protocol != PROTOCOL_QUIC_CRYPTO) {
return;
}
unsigned char* p = packet;
size_t p_size = QUIC_ARRAYSIZE(packet);
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_size = QUIC_ARRAYSIZE(packet99);
} else if (framer_.transport_version() > QUIC_VERSION_44) {
p = packet46;
p_size = QUIC_ARRAYSIZE(packet46);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
}
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
ASSERT_TRUE(visitor_.header_->nonce != nullptr);
for (char i = 0; i < 32; ++i) {
EXPECT_EQ(i, (*visitor_.header_->nonce)[static_cast<size_t>(i)]);
}
EXPECT_EQ(1u, visitor_.padding_frames_.size());
EXPECT_EQ(5, visitor_.padding_frames_[0]->num_padding_bytes);
}
TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id, version flag and an unknown flag)
0x29,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// version tag
'Q', '0', '0', '0',
// packet number
0x12, 0x34, 0x56, 0x78,
// frame type (padding frame)
0x00,
0x00, 0x00, 0x00, 0x00
};
unsigned char packet44[] = {
// type (long header with packet type ZERO_RTT_PROTECTED)
0xFC,
// version tag
'Q', '0', '0', '0',
// connection_id length
0x50,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
// frame type (padding frame)
0x00,
0x00, 0x00, 0x00, 0x00
};
// clang-format on
QuicEncryptedPacket encrypted(
AsChars(framer_.transport_version() > QUIC_VERSION_43 ? packet44
: packet),
framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet44)
: QUIC_ARRAYSIZE(packet),
false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(0, visitor_.frame_count_);
EXPECT_EQ(1, visitor_.version_mismatch_);
EXPECT_EQ(1u, visitor_.padding_frames_.size());
EXPECT_EQ(5, visitor_.padding_frames_[0]->num_padding_bytes);
}
TEST_P(QuicFramerTest, PaddingFrame) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
// paddings
0x00, 0x00,
// frame type (stream frame with fin)
0xFF,
// stream id
0x01, 0x02, 0x03, 0x04,
// offset
0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54,
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!',
// paddings
0x00, 0x00,
};
unsigned char packet44[] = {
// type (short header, 4 byte packet number)
0x32,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
// paddings
0x00, 0x00,
// frame type (stream frame with fin)
0xFF,
// stream id
0x01, 0x02, 0x03, 0x04,
// offset
0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54,
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!',
// paddings
0x00, 0x00,
};
unsigned char packet46[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
// paddings
0x00, 0x00,
// frame type (stream frame with fin)
0xFF,
// stream id
0x01, 0x02, 0x03, 0x04,
// offset
0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54,
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!',
// paddings
0x00, 0x00,
};
unsigned char packet99[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
// paddings
0x00, 0x00,
// frame type - IETF_STREAM with FIN, LEN, and OFFSET bits set.
0x08 | 0x01 | 0x02 | 0x04,
// stream id
kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
// offset
kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54,
// data length
kVarInt62OneByte + 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!',
// paddings
0x00, 0x00,
};
// clang-format on
unsigned char* p = packet;
size_t p_size = QUIC_ARRAYSIZE(packet);
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_size = QUIC_ARRAYSIZE(packet99);
} else if (framer_.transport_version() > QUIC_VERSION_44) {
p = packet46;
p_size = QUIC_ARRAYSIZE(packet46);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
}
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
EXPECT_EQ(2u, visitor_.padding_frames_.size());
EXPECT_EQ(2, visitor_.padding_frames_[0]->num_padding_bytes);
EXPECT_EQ(2, visitor_.padding_frames_[1]->num_padding_bytes);
EXPECT_EQ(kStreamId, visitor_.stream_frames_[0]->stream_id);
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get());
}
TEST_P(QuicFramerTest, StreamFrame) {
// clang-format off
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
{0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFF}},
// stream id
{"Unable to read stream_id.",
{0x01, 0x02, 0x03, 0x04}},
// offset
{"Unable to read offset.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Unable to read frame data.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
PacketFragments packet44 = {
// type (short header, 4 byte packet number)
{"",
{0x32}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFF}},
// stream id
{"Unable to read stream_id.",
{0x01, 0x02, 0x03, 0x04}},
// offset
{"Unable to read offset.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Unable to read frame data.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
PacketFragments packet46 = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFF}},
// stream id
{"Unable to read stream_id.",
{0x01, 0x02, 0x03, 0x04}},
// offset
{"Unable to read offset.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Unable to read frame data.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
PacketFragments packet99 = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type - IETF_STREAM with FIN, LEN, and OFFSET bits set.
{"",
{ 0x08 | 0x01 | 0x02 | 0x04 }},
// stream id
{"Unable to read stream_id.",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
// offset
{"Unable to read stream data offset.",
{kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
// data length
{"Unable to read stream data length.",
{kVarInt62OneByte + 0x0c}},
// data
{"Unable to read frame data.",
{ 'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
// clang-format on
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
: (framer_.transport_version() > QUIC_VERSION_44
? packet46
: (framer_.transport_version() > QUIC_VERSION_43 ? packet44
: packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
EXPECT_EQ(kStreamId, visitor_.stream_frames_[0]->stream_id);
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get());
CheckFramingBoundaries(fragments, QUIC_INVALID_STREAM_DATA);
}
// Test an empty (no data) stream frame.
TEST_P(QuicFramerTest, EmptyStreamFrame) {
// Only the IETF QUIC spec explicitly says that empty
// stream frames are supported.
if (framer_.transport_version() != QUIC_VERSION_99) {
return;
}
// clang-format off
PacketFragments packet = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type - IETF_STREAM with FIN, LEN, and OFFSET bits set.
{"",
{ 0x08 | 0x01 | 0x02 | 0x04 }},
// stream id
{"Unable to read stream_id.",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
// offset
{"Unable to read stream data offset.",
{kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
// data length
{"Unable to read stream data length.",
{kVarInt62OneByte + 0x00}},
};
// clang-format on
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(packet));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
EXPECT_EQ(kStreamId, visitor_.stream_frames_[0]->stream_id);
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
EXPECT_EQ(visitor_.stream_frames_[0].get()->data_length, 0u);
CheckFramingBoundaries(packet, QUIC_INVALID_STREAM_DATA);
}
TEST_P(QuicFramerTest, MissingDiversificationNonce) {
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
framer_.SetDecrypter(ENCRYPTION_NONE,
QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT));
decrypter_ = new test::TestDecrypter();
framer_.SetAlternativeDecrypter(
ENCRYPTION_ZERO_RTT, std::unique_ptr<QuicDecrypter>(decrypter_), false);
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
0x28,
// connection_id
0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
// packet number
0x12, 0x34, 0x56, 0x78,
// frame type (stream frame with fin)
0xFF,
// stream id
0x01, 0x02, 0x03, 0x04,
// offset
0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54,
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!',
};
unsigned char packet44[] = {
// type (long header with packet type ZERO_RTT_PROTECTED)
0xFC,
// version tag
QUIC_VERSION_BYTES,
// connection_id length
0x50,
// connection_id
0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
// packet number
0x12, 0x34, 0x56, 0x78,
// frame type - STREAM with LEN, FIN, and OFFSET bits set.
0x10 | 0x01 | 0x02 | 0x04,
// stream id
0x01, 0x02, 0x03, 0x04,
// offset
0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54,
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!',
};
// clang-format on
unsigned char* p = packet;
if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
}
QuicEncryptedPacket encrypted(AsChars(p),
framer_.transport_version() > QUIC_VERSION_43
? QUIC_ARRAYSIZE(packet44)
: QUIC_ARRAYSIZE(packet),
false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
if (framer_.transport_version() > QUIC_VERSION_43) {
// Cannot read diversification nonce.
EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
} else {
EXPECT_EQ(QUIC_DECRYPTION_FAILURE, framer_.error());
}
}
TEST_P(QuicFramerTest, StreamFrame3ByteStreamId) {
if (framer_.transport_version() > QUIC_VERSION_43) {
// This test is nonsensical for IETF Quic.
return;
}
// clang-format off
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
{0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFE}},
// stream id
{"Unable to read stream_id.",
{0x02, 0x03, 0x04}},
// offset
{"Unable to read offset.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Unable to read frame data.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
// clang-format on
PacketFragments& fragments = packet;
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
// Stream ID should be the last 3 bytes of kStreamId.
EXPECT_EQ(0x00FFFFFF & kStreamId, visitor_.stream_frames_[0]->stream_id);
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get());
CheckFramingBoundaries(fragments, QUIC_INVALID_STREAM_DATA);
}
TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) {
// clang-format off
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
{0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFD}},
// stream id
{"Unable to read stream_id.",
{0x03, 0x04}},
// offset
{"Unable to read offset.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Unable to read frame data.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
PacketFragments packet44 = {
// type (short header, 4 byte packet number)
{"",
{0x32}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFD}},
// stream id
{"Unable to read stream_id.",
{0x03, 0x04}},
// offset
{"Unable to read offset.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Unable to read frame data.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
PacketFragments packet46 = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFD}},
// stream id
{"Unable to read stream_id.",
{0x03, 0x04}},
// offset
{"Unable to read offset.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Unable to read frame data.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
PacketFragments packet99 = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (IETF_STREAM frame with LEN, FIN, and OFFSET bits set)
{"",
{0x08 | 0x01 | 0x02 | 0x04}},
// stream id
{"Unable to read stream_id.",
{kVarInt62TwoBytes + 0x03, 0x04}},
// offset
{"Unable to read stream data offset.",
{kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
// data length
{"Unable to read stream data length.",
{kVarInt62OneByte + 0x0c}},
// data
{"Unable to read frame data.",
{ 'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
// clang-format on
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
: (framer_.transport_version() > QUIC_VERSION_44
? packet46
: (framer_.transport_version() > QUIC_VERSION_43 ? packet44
: packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
// Stream ID should be the last 2 bytes of kStreamId.
EXPECT_EQ(0x0000FFFF & kStreamId, visitor_.stream_frames_[0]->stream_id);
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get());
CheckFramingBoundaries(fragments, QUIC_INVALID_STREAM_DATA);
}
TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) {
// clang-format off
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
{0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFC}},
// stream id
{"Unable to read stream_id.",
{0x04}},
// offset
{"Unable to read offset.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Unable to read frame data.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
PacketFragments packet44 = {
// type (short header, 4 byte packet number)
{"",
{0x32}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFC}},
// stream id
{"Unable to read stream_id.",
{0x04}},
// offset
{"Unable to read offset.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Unable to read frame data.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
PacketFragments packet46 = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFC}},
// stream id
{"Unable to read stream_id.",
{0x04}},
// offset
{"Unable to read offset.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Unable to read frame data.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
PacketFragments packet99 = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (IETF_STREAM frame with LEN, FIN, and OFFSET bits set)
{"",
{0x08 | 0x01 | 0x02 | 0x04}},
// stream id
{"Unable to read stream_id.",
{kVarInt62OneByte + 0x04}},
// offset
{"Unable to read stream data offset.",
{kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
// data length
{"Unable to read stream data length.",
{kVarInt62OneByte + 0x0c}},
// data
{"Unable to read frame data.",
{ 'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
// clang-format on
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
: (framer_.transport_version() > QUIC_VERSION_44
? packet46
: (framer_.transport_version() > QUIC_VERSION_43 ? packet44
: packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
// Stream ID should be the last 1 byte of kStreamId.
EXPECT_EQ(0x000000FF & kStreamId, visitor_.stream_frames_[0]->stream_id);
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get());
CheckFramingBoundaries(fragments, QUIC_INVALID_STREAM_DATA);
}
TEST_P(QuicFramerTest, StreamFrameWithVersion) {
// clang-format off
PacketFragments packet = {
// public flags (version, 8 byte connection_id)
{"",
{0x29}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// version tag
{"",
{QUIC_VERSION_BYTES}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFE}},
// stream id
{"Unable to read stream_id.",
{0x02, 0x03, 0x04}},
// offset
{"Unable to read offset.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Unable to read frame data.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
PacketFragments packet44 = {
// public flags (long header with packet type ZERO_RTT_PROTECTED)
{"",
{0xFC}},
// version tag
{"",
{QUIC_VERSION_BYTES}},
// connection_id length
{"",
{0x50}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFE}},
// stream id
{"Unable to read stream_id.",
{0x02, 0x03, 0x04}},
// offset
{"Unable to read offset.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Unable to read frame data.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
PacketFragments packet46 = {
// public flags (long header with packet type ZERO_RTT_PROTECTED and
// 4-byte packet number)
{"",
{0xD3}},
// version tag
{"",
{QUIC_VERSION_BYTES}},
// connection_id length
{"",
{0x50}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFE}},
// stream id
{"Unable to read stream_id.",
{0x02, 0x03, 0x04}},
// offset
{"Unable to read offset.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Unable to read frame data.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
PacketFragments packet99 = {
// public flags (long header with packet type ZERO_RTT_PROTECTED and
// 4-byte packet number)
{"",
{0xD3}},
// version tag
{"",
{QUIC_VERSION_BYTES}},
// connection_id length
{"",
{0x50}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// long header packet length
{"",
{0x1E}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (IETF_STREAM frame with FIN, LEN, and OFFSET bits set)
{"",
{0x08 | 0x01 | 0x02 | 0x04}},
// stream id
{"Long header payload length longer than packet.",
{kVarInt62FourBytes + 0x00, 0x02, 0x03, 0x04}},
// offset
{"Long header payload length longer than packet.",
{kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
// data length
{"Long header payload length longer than packet.",
{kVarInt62OneByte + 0x0c}},
// data
{"Long header payload length longer than packet.",
{ 'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
// clang-format on
QuicVariableLengthIntegerLength retry_token_length_length =
VARIABLE_LENGTH_INTEGER_LENGTH_0;
size_t retry_token_length = 0;
QuicVariableLengthIntegerLength length_length =
QuicVersionHasLongHeaderLengths(framer_.transport_version())
? VARIABLE_LENGTH_INTEGER_LENGTH_1
: VARIABLE_LENGTH_INTEGER_LENGTH_0;
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
: (framer_.transport_version() > QUIC_VERSION_44
? packet46
: (framer_.transport_version() > QUIC_VERSION_43 ? packet44
: packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID,
retry_token_length_length, retry_token_length, length_length));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
// Stream ID should be the last 3 bytes of kStreamId.
EXPECT_EQ(0x00FFFFFF & kStreamId, visitor_.stream_frames_[0]->stream_id);
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get());
CheckFramingBoundaries(fragments,
framer_.transport_version() == QUIC_VERSION_99
? QUIC_INVALID_PACKET_HEADER
: QUIC_INVALID_STREAM_DATA);
}
TEST_P(QuicFramerTest, RejectPacket) {
visitor_.accept_packet_ = false;
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
// frame type (stream frame with fin)
0xFF,
// stream id
0x01, 0x02, 0x03, 0x04,
// offset
0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54,
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!',
};
unsigned char packet44[] = {
// type (short header, 4 byte packet number)
0x32,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
// frame type (STREAM Frame with FIN, LEN, and OFFSET bits set)
0x10 | 0x01 | 0x02 | 0x04,
// stream id
kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
// offset
kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54,
// data length
kVarInt62OneByte + 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!',
};
unsigned char packet46[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
// frame type (STREAM Frame with FIN, LEN, and OFFSET bits set)
0x10 | 0x01 | 0x02 | 0x04,
// stream id
kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
// offset
kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54,
// data length
kVarInt62OneByte + 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!',
};
// clang-format on
unsigned char* p = packet;
if (framer_.transport_version() > QUIC_VERSION_44) {
p = packet46;
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
}
QuicEncryptedPacket encrypted(AsChars(p),
framer_.transport_version() > QUIC_VERSION_43
? QUIC_ARRAYSIZE(packet44)
: QUIC_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, !kIncludeDiversificationNonce,
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
ASSERT_EQ(0u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
}
TEST_P(QuicFramerTest, RejectPublicHeader) {
visitor_.accept_public_header_ = false;
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
};
unsigned char packet44[] = {
// type (short header, 1 byte packet number)
0x30,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x01,
};
unsigned char packet46[] = {
// type (short header, 1 byte packet number)
0x40,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x01,
};
// clang-format on
QuicEncryptedPacket encrypted(
framer_.transport_version() > QUIC_VERSION_44
? AsChars(packet46)
: (framer_.transport_version() > QUIC_VERSION_43 ? AsChars(packet44)
: AsChars(packet)),
framer_.transport_version() > QUIC_VERSION_44
? QUIC_ARRAYSIZE(packet46)
: (framer_.transport_version() > QUIC_VERSION_43
? QUIC_ARRAYSIZE(packet44)
: QUIC_ARRAYSIZE(packet)),
false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_FALSE(visitor_.header_->packet_number.IsInitialized());
}
TEST_P(QuicFramerTest, AckFrameOneAckBlock) {
// clang-format off
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
{0x2C}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (ack frame)
// (one ack block, 2 byte largest observed, 2 byte block length)
{"",
{0x45}},
// largest acked
{"Unable to read largest acked.",
{0x12, 0x34}},
// Zero delta time.
{"Unable to read ack delay time.",
{0x00, 0x00}},
// first ack block length.
{"Unable to read first ack block length.",
{0x12, 0x34}},
// num timestamps.
{"Unable to read num received packets.",
{0x00}}
};
PacketFragments packet44 = {
// type (short packet, 4 byte packet number)
{"",
{0x32}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (ack frame)
// (one ack block, 2 byte largest observed, 2 byte block length)
{"",
{0x45}},
// largest acked
{"Unable to read largest acked.",
{0x12, 0x34}},
// Zero delta time.
{"Unable to read ack delay time.",
{0x00, 0x00}},
// first ack block length.
{"Unable to read first ack block length.",
{0x12, 0x34}},
// num timestamps.
{"Unable to read num received packets.",
{0x00}}
};
PacketFragments packet46 = {
// type (short packet, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (ack frame)
// (one ack block, 2 byte largest observed, 2 byte block length)
{"",
{0x45}},
// largest acked
{"Unable to read largest acked.",
{0x12, 0x34}},
// Zero delta time.
{"Unable to read ack delay time.",
{0x00, 0x00}},
// first ack block length.
{"Unable to read first ack block length.",
{0x12, 0x34}},
// num timestamps.
{"Unable to read num received packets.",
{0x00}}
};
PacketFragments packet99 = {
// type (short packet, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (IETF_ACK)
// (one ack block, 2 byte largest observed, 2 byte block length)
// IETF-Quic ignores the bit-fields in the ack type, all of
// that information is encoded elsewhere in the frame.
{"",
{0x02}},
// largest acked
{"Unable to read largest acked.",
{kVarInt62TwoBytes + 0x12, 0x34}},
// Zero delta time.
{"Unable to read ack delay time.",
{kVarInt62OneByte + 0x00}},
// Ack block count (0 -- no blocks after the first)
{"Unable to read ack block count.",
{kVarInt62OneByte + 0x00}},
// first ack block length - 1.
// IETF Quic defines the ack block's value as the "number of
// packets that preceed the largest packet number in the block"
// which for the 1st ack block is the largest acked field,
// above. This means that if we are acking just packet 0x1234
// then the 1st ack block will be 0.
{"Unable to read first ack block length.",
{kVarInt62TwoBytes + 0x12, 0x33}}
};
// clang-format on
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
: (framer_.transport_version() > QUIC_VERSION_44
? packet46
: (framer_.transport_version() > QUIC_VERSION_43 ? packet44
: packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
EXPECT_EQ(0u, visitor_.stream_frames_.size());
ASSERT_EQ(1u, visitor_.ack_frames_.size());
const QuicAckFrame& frame = *visitor_.ack_frames_[0];
EXPECT_EQ(kSmallLargestObserved, LargestAcked(frame));
ASSERT_EQ(4660u, frame.packets.NumPacketsSlow());
CheckFramingBoundaries(fragments, QUIC_INVALID_ACK_DATA);
}
// This test checks that the ack frame processor correctly identifies
// and handles the case where the first ack block is larger than the
// largest_acked packet.
TEST_P(QuicFramerTest, FirstAckFrameUnderflow) {
// clang-format off
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
{0x2C}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (ack frame)
// (one ack block, 2 byte largest observed, 2 byte block length)
{"",
{0x45}},
// largest acked
{"Unable to read largest acked.",
{0x12, 0x34}},
// Zero delta time.
{"Unable to read ack delay time.",
{0x00, 0x00}},
// first ack block length.
{"Unable to read first ack block length.",
{0x88, 0x88}},
// num timestamps.
{"Underflow with first ack block length 34952 largest acked is 4660.",
{0x00}}