blob: e2c106adbef158d326b979f12a22da04399daca4 [file] [log] [blame] [edit]
// 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/quiche/src/quic/core/quic_framer.h"
#include <algorithm>
#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "net/third_party/quiche/src/quic/core/crypto/null_decrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_data_producer.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));
}
QuicConnectionId FramerTestConnectionIdNineBytes() {
char connection_id_bytes[9] = {0xFE, 0xDC, 0xBA, 0x98, 0x76,
0x54, 0x32, 0x10, 0x42};
return QuicConnectionId(connection_id_bytes, sizeof(connection_id_bytes));
}
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 SetHeaderProtectionKey(QuicStringPiece /*key*/) 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_ = std::string(associated_data);
plaintext_ = std::string(plaintext);
memcpy(output, plaintext.data(), plaintext.length());
*output_length = plaintext.length();
return true;
}
std::string GenerateHeaderProtectionMask(
QuicStringPiece /*sample*/) override {
return std::string(5, 0);
}
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_;
std::string associated_data_;
std::string 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 SetHeaderProtectionKey(QuicStringPiece /*key*/) 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_ = std::string(associated_data);
ciphertext_ = std::string(ciphertext);
memcpy(output, ciphertext.data(), ciphertext.length());
*output_length = ciphertext.length();
return true;
}
std::string GenerateHeaderProtectionMask(
QuicDataReader* /*sample_reader*/) override {
return std::string(5, 0);
}
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_;
std::string associated_data_;
std::string 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));
}
void OnRetryPacket(QuicConnectionId original_connection_id,
QuicConnectionId new_connection_id,
QuicStringPiece retry_token) override {
retry_original_connection_id_ =
QuicMakeUnique<QuicConnectionId>(original_connection_id);
retry_new_connection_id_ =
QuicMakeUnique<QuicConnectionId>(new_connection_id);
retry_token_ = QuicMakeUnique<std::string>(std::string(retry_token));
}
bool OnProtocolVersionMismatch(ParsedQuicVersion received_version) override {
QUIC_DLOG(INFO) << "QuicFramer Version Mismatch, version: "
<< received_version;
++version_mismatch_;
return false;
}
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.
std::string* string_data =
new std::string(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.
std::string* string_data =
new std::string(frame.data_buffer, frame.data_length);
crypto_data_.push_back(QuicWrapUnique(string_data));
crypto_frames_.push_back(QuicMakeUnique<QuicCryptoFrame>(
ENCRYPTION_INITIAL, 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 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 OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override {
max_streams_frame_ = frame;
return true;
}
bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override {
streams_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::unique_ptr<QuicConnectionId> retry_original_connection_id_;
std::unique_ptr<QuicConnectionId> retry_new_connection_id_;
std::unique_ptr<std::string> retry_token_;
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_;
QuicStopSendingFrame stop_sending_frame_;
QuicGoAwayFrame goaway_frame_;
QuicPathChallengeFrame path_challenge_frame_;
QuicPathResponseFrame path_response_frame_;
QuicWindowUpdateFrame window_update_frame_;
QuicBlockedFrame blocked_frame_;
QuicStreamsBlockedFrame streams_blocked_frame_;
QuicMaxStreamsFrame max_streams_frame_;
QuicNewConnectionIdFrame new_connection_id_;
QuicRetireConnectionIdFrame retire_connection_id_;
QuicNewTokenFrame new_token_;
std::vector<std::unique_ptr<std::string>> stream_data_;
std::vector<std::unique_ptr<std::string>> crypto_data_;
};
// Simple struct for defining a packet's content, and associated
// parse error.
struct PacketFragment {
std::string error_if_missing;
std::vector<unsigned char> fragment;
};
using PacketFragments = std::vector<struct PacketFragment>;
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_(AllSupportedVersions(),
start_,
Perspective::IS_SERVER,
kQuicDefaultConnectionIdLength) {
SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
framer_.set_version(version_);
if (framer_.version().KnowsWhichDecrypterToUse()) {
framer_.InstallDecrypter(ENCRYPTION_INITIAL,
std::unique_ptr<QuicDecrypter>(decrypter_));
} else {
framer_.SetDecrypter(ENCRYPTION_INITIAL,
std::unique_ptr<QuicDecrypter>(decrypter_));
}
framer_.SetEncrypter(ENCRYPTION_INITIAL,
std::unique_ptr<QuicEncrypter>(encrypter_));
framer_.set_visitor(&visitor_);
framer_.InferPacketHeaderTypeFromVersion();
}
void SetDecrypterLevel(EncryptionLevel level) {
if (!framer_.version().KnowsWhichDecrypterToUse()) {
return;
}
decrypter_ = new TestDecrypter();
framer_.InstallDecrypter(level, std::unique_ptr<QuicDecrypter>(decrypter_));
}
// 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[kMaxOutgoingPacketSize + 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) {
std::string 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,
std::string 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,
std::string 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(std::string str, QuicStreamFrame* frame) {
EXPECT_EQ(str, std::string(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(AllSupportedVersions()));
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) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// clang-format off
unsigned char packet[kMaxIncomingPacketSize + 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[kMaxIncomingPacketSize + 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[kMaxIncomingPacketSize + 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, kMaxIncomingPacketSize - header_size);
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
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());
EXPECT_EQ("Packet too large.", framer_.detailed_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);
PacketHeaderFormat format;
bool version_flag;
QuicConnectionId destination_connection_id, source_connection_id;
QuicVersionLabel version_label;
std::string detailed_error;
QuicErrorCode error_code;
if (!GetQuicReloadableFlag(quic_use_parse_public_header)) {
error_code = QuicFramer::ProcessPacketDispatcher(
*encrypted, kQuicDefaultConnectionIdLength, &format, &version_flag,
&version_label, &destination_connection_id, &source_connection_id,
&detailed_error);
} else {
bool retry_token_present, use_length_prefix;
QuicStringPiece retry_token;
ParsedQuicVersion parsed_version = UnsupportedQuicVersion();
error_code = QuicFramer::ParsePublicHeaderDispatcher(
*encrypted, kQuicDefaultConnectionIdLength, &format, &version_flag,
&use_length_prefix, &version_label, &parsed_version,
&destination_connection_id, &source_connection_id, &retry_token_present,
&retry_token, &detailed_error);
EXPECT_FALSE(retry_token_present);
EXPECT_FALSE(use_length_prefix);
}
EXPECT_EQ(QUIC_NO_ERROR, error_code);
EXPECT_EQ(GOOGLE_QUIC_PACKET, format);
EXPECT_FALSE(version_flag);
EXPECT_EQ(kQuicDefaultConnectionIdLength, destination_connection_id.length());
EXPECT_EQ(FramerTestConnectionId(), destination_connection_id);
EXPECT_EQ(EmptyQuicConnectionId(), source_connection_id);
}
TEST_P(QuicFramerTest, LongPacketHeader) {
// clang-format off
PacketFragments packet44 = {
// type (long header with packet type INITIAL)
{"Unable to read first byte.",
{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 connection ID.",
{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 first byte.",
{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 connection ID.",
{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);
PacketHeaderFormat format;
bool version_flag;
QuicConnectionId destination_connection_id, source_connection_id;
QuicVersionLabel version_label;
std::string detailed_error;
QuicErrorCode error_code;
if (!GetQuicReloadableFlag(quic_use_parse_public_header)) {
error_code = QuicFramer::ProcessPacketDispatcher(
*encrypted, kQuicDefaultConnectionIdLength, &format, &version_flag,
&version_label, &destination_connection_id, &source_connection_id,
&detailed_error);
} else {
bool retry_token_present, use_length_prefix;
QuicStringPiece retry_token;
ParsedQuicVersion parsed_version = UnsupportedQuicVersion();
error_code = QuicFramer::ParsePublicHeaderDispatcher(
*encrypted, kQuicDefaultConnectionIdLength, &format, &version_flag,
&use_length_prefix, &version_label, &parsed_version,
&destination_connection_id, &source_connection_id, &retry_token_present,
&retry_token, &detailed_error);
EXPECT_EQ(retry_token_present, framer_.version().SupportsRetry());
EXPECT_FALSE(use_length_prefix);
}
EXPECT_EQ(IETF_QUIC_LONG_HEADER_PACKET, format);
EXPECT_TRUE(version_flag);
EXPECT_EQ(kQuicDefaultConnectionIdLength, destination_connection_id.length());
EXPECT_EQ(FramerTestConnectionId(), destination_connection_id);
EXPECT_EQ(EmptyQuicConnectionId(), source_connection_id);
}
TEST_P(QuicFramerTest, LongPacketHeaderWithBothConnectionIds) {
if (framer_.transport_version() <= QUIC_VERSION_43) {
// This test requires an IETF long header.
return;
}
SetQuicReloadableFlag(quic_use_parse_public_header, false);
SetQuicRestartFlag(quic_do_not_override_connection_id, true);
SetDecrypterLevel(ENCRYPTION_ZERO_RTT);
const unsigned char type_byte =
framer_.transport_version() == QUIC_VERSION_44 ? 0xFC : 0xD3;
// clang-format off
unsigned char packet[] = {
// public flags (long header with packet type ZERO_RTT_PROTECTED and
// 4-byte packet number)
type_byte,
// version
QUIC_VERSION_BYTES,
// connection ID lengths
0x55,
// destination connection ID
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// source connection ID
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x11,
// long header packet length
0x05,
// packet number
0x12, 0x34, 0x56, 0x00,
// padding frame
0x00,
};
// clang-format on
QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
PacketHeaderFormat format = GOOGLE_QUIC_PACKET;
bool version_flag = false;
QuicConnectionId destination_connection_id, source_connection_id;
QuicVersionLabel version_label = 0;
std::string detailed_error = "";
QuicErrorCode error_code;
if (!GetQuicReloadableFlag(quic_use_parse_public_header)) {
error_code = QuicFramer::ProcessPacketDispatcher(
encrypted, kQuicDefaultConnectionIdLength, &format, &version_flag,
&version_label, &destination_connection_id, &source_connection_id,
&detailed_error);
} else {
bool retry_token_present, use_length_prefix;
QuicStringPiece retry_token;
ParsedQuicVersion parsed_version = UnsupportedQuicVersion();
error_code = QuicFramer::ParsePublicHeaderDispatcher(
encrypted, kQuicDefaultConnectionIdLength, &format, &version_flag,
&use_length_prefix, &version_label, &parsed_version,
&destination_connection_id, &source_connection_id, &retry_token_present,
&retry_token, &detailed_error);
EXPECT_FALSE(retry_token_present);
EXPECT_FALSE(use_length_prefix);
}
EXPECT_EQ("", detailed_error);
EXPECT_EQ(IETF_QUIC_LONG_HEADER_PACKET, format);
EXPECT_TRUE(version_flag);
EXPECT_EQ(FramerTestConnectionId(), destination_connection_id);
EXPECT_EQ(FramerTestConnectionIdPlusOne(), source_connection_id);
}
TEST_P(QuicFramerTest, ClientConnectionIdFromShortHeaderToClient) {
SetQuicRestartFlag(quic_do_not_override_connection_id, true);
if (!framer_.version().SupportsClientConnectionIds()) {
return;
}
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
QuicFramerPeer::SetLastSerializedServerConnectionId(&framer_,
TestConnectionId(0x33));
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
framer_.SetExpectedClientConnectionIdLength(kQuicDefaultConnectionIdLength);
// clang-format off
unsigned char packet[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x13, 0x37, 0x42, 0x33,
// padding frame
0x00,
};
// clang-format on
QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
EXPECT_EQ("", framer_.detailed_error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_EQ(TestConnectionId(0x33), visitor_.header_->source_connection_id);
}
// In short header packets from client to server, the client connection ID
// is omitted, but the framer adds it to the header struct using its
// last serialized client connection ID. This test ensures that this
// mechanism behaves as expected.
TEST_P(QuicFramerTest, ClientConnectionIdFromShortHeaderToServer) {
SetQuicRestartFlag(quic_do_not_override_connection_id, true);
if (!framer_.version().SupportsClientConnectionIds()) {
return;
}
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
QuicFramerPeer::SetLastSerializedClientConnectionId(&framer_,
TestConnectionId(0x33));
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
// clang-format off
unsigned char packet[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x13, 0x37, 0x42, 0x33,
// padding frame
0x00,
};
// clang-format on
QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
EXPECT_EQ("", framer_.detailed_error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_EQ(TestConnectionId(0x33), visitor_.header_->source_connection_id);
}
TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
QuicFramerPeer::SetLastSerializedServerConnectionId(&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 first byte.",
{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 first byte.",
{0x43}},
// connection_id
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
PacketFragments packet_hp = {
// type (short header, 4 byte packet number)
{"Unable to read first byte.",
{0x43}},
// connection_id
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
};
// clang-format on
PacketFragments& fragments =
framer_.version().HasHeaderProtection()
? packet_hp
: 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());
if (!GetQuicRestartFlag(quic_do_not_override_connection_id)) {
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
} else {
EXPECT_EQ(FramerTestConnectionId(), visitor_.header_->source_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) {
SetDecrypterLevel(ENCRYPTION_ZERO_RTT);
// 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 first byte.",
{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 connection ID.",
{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 first byte.",
{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 connection ID.",
{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 first byte.",
{0xD3}},
// version tag
{"Unable to read protocol version.",
{QUIC_VERSION_BYTES}},
// destination connection ID length
{"Unable to read destination connection ID.",
{0x08}},
// destination connection ID
{"Unable to read destination connection ID.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// source connection ID length
{"Unable to read source connection ID.",
{0x00}},
// 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) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
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 first byte.",
{0x32}},
// connection_id
{"Unable to read destination connection ID.",
{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 first byte.",
{0x43}},
// connection_id
{"Unable to read destination connection ID.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
PacketFragments packet_hp = {
// type (short header, 4 byte packet number)
{"Unable to read first byte.",
{0x43}},
// connection_id
{"Unable to read destination connection ID.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
};
// clang-format on
PacketFragments& fragments =
framer_.version().HasHeaderProtection()
? packet_hp
: 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) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
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 first byte.",
{0x31}},
// connection_id
{"Unable to read destination connection ID.",
{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 first byte.",
{0x41}},
// connection_id
{"Unable to read destination connection ID.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x56, 0x78}},
};
PacketFragments packet_hp = {
// type (short header, 2 byte packet number)
{"Unable to read first byte.",
{0x41}},
// connection_id
{"Unable to read destination connection ID.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x56, 0x78}},
// padding
{"", {0x00, 0x00}},
};
// clang-format on
PacketFragments& fragments =
framer_.version().HasHeaderProtection()
? packet_hp
: (framer_.transport_version() > QUIC_VERSION_44
? packet46
: (framer_.transport_version() > QUIC_VERSION_43 ? packet44
: packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
if (framer_.version().HasHeaderProtection()) {
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
} else {
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) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
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 first byte.",
{0x30}},
// connection_id
{"Unable to read destination connection ID.",
{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 first byte.",
{0x40}},
// connection_id
{"Unable to read destination connection ID.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x78}},
};
PacketFragments packet_hp = {
// type (8 byte connection_id and 1 byte packet number)
{"Unable to read first byte.",
{0x40}},
// connection_id
{"Unable to read destination connection ID.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x78}},
// padding
{"", {0x00, 0x00, 0x00}},
};
// clang-format on
PacketFragments& fragments =
framer_.version().HasHeaderProtection()
? packet_hp
: (framer_.transport_version() > QUIC_VERSION_44
? packet46
: (framer_.transport_version() > QUIC_VERSION_43 ? packet44
: packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
if (framer_.version().HasHeaderProtection()) {
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
} else {
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) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// 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) {
SetDecrypterLevel(ENCRYPTION_ZERO_RTT);
// 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,
// destination connection ID length
0x00,
// source connection ID length
0x08,
// source 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
};
unsigned char packet45[] = {
// type (long header, ZERO_RTT_PROTECTED, 4-byte packet number)
0xD3,
// 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
};
unsigned char packet99[] = {
// type (long header, ZERO_RTT_PROTECTED, 4-byte packet number)
0xD3,
// version tag
'Q', '0', '0', '0',
// destination connection ID length
0x08,
// destination connection ID
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// source connection ID length
0x00,
// packet number
0x12, 0x34, 0x56, 0x78,
// frame type (padding frame)
0x00,
0x00, 0x00, 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 = packet45;
p_size = QUIC_ARRAYSIZE(packet45);
} 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_EQ(0, visitor_.frame_count_);
EXPECT_EQ(1, visitor_.version_mismatch_);
}
TEST_P(QuicFramerTest, PaddingFrame) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// 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 (VersionHasIetfQuicFrames(framer_.transport_version())) {
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) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// 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 =
VersionHasIetfQuicFrames(framer_.transport_version())
? 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 (!VersionHasIetfQuicFrames(framer_.transport_version())) {
return;
}
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// 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) {
if (framer_.version().handshake_protocol != PROTOCOL_QUIC_CRYPTO) {
// TLS does not use diversification nonces.
return;
}
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
decrypter_ = new test::TestDecrypter();
if (framer_.version().KnowsWhichDecrypterToUse()) {
framer_.InstallDecrypter(ENCRYPTION_INITIAL, QuicMakeUnique<NullDecrypter>(
Perspective::IS_CLIENT));
framer_.InstallDecrypter(ENCRYPTION_ZERO_RTT,
std::unique_ptr<QuicDecrypter>(decrypter_));
} else {
framer_.SetDecrypter(ENCRYPTION_INITIAL,
QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT));
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,
// padding frame
0x00,
};
unsigned char packet44[] = {
// type (long header, ZERO_RTT_PROTECTED, 4-byte packet number)
0xFC,
// version tag
QUIC_VERSION_BYTES,
// connection_id length
0x05,
// connection_id
0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
// packet number
0x12, 0x34, 0x56, 0x78,
// padding frame
0x00,
};
unsigned char packet46[] = {
// type (long header, ZERO_RTT_PROTECTED, 4-byte packet number)
0xD3,
// version tag
QUIC_VERSION_BYTES,
// connection_id length
0x05,
// connection_id
0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
// packet number
0x12, 0x34, 0x56, 0x78,
// padding frame
0x00,
};
unsigned char packet99[] = {
// type (long header, ZERO_RTT_PROTECTED, 4-byte packet number)
0xD3,
// version tag
QUIC_VERSION_BYTES,
// destination connection ID length
0x00,
// source connection ID length
0x08,
// source connection ID
0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
// IETF long header payload length
0x05,
// packet number
0x12, 0x34, 0x56, 0x78,
// padding frame
0x00,
};
// clang-format on
unsigned char* p = packet;
size_t p_length = QUIC_ARRAYSIZE(packet);
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_length = QUIC_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
p_length = QUIC_ARRAYSIZE(packet46);
} else if (framer_.transport_version() >= QUIC_VERSION_44) {
p = packet44;
p_length = QUIC_ARRAYSIZE(packet44);
}
QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
if (framer_.version().HasHeaderProtection()) {
EXPECT_EQ(QUIC_DECRYPTION_FAILURE, framer_.error());
EXPECT_EQ("Unable to decrypt header protection.", framer_.detailed_error());
} else if (framer_.transport_version() >= QUIC_VERSION_44) {
// Cannot read diversification nonce.
EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
EXPECT_EQ("Unable to read nonce.", framer_.detailed_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) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// 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 =
VersionHasIetfQuicFrames(framer_.transport_version())
? 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) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// 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 =
VersionHasIetfQuicFrames(framer_.transport_version())
? 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) {
// If IETF frames are in use then we must also have the IETF
// header invariants.
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
DCHECK(VersionHasIetfInvariantHeader(framer_.transport_version()));
}
SetDecrypterLevel(ENCRYPTION_ZERO_RTT);
// 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',