blob: 52ae592b1d48b48d889b154d08c32a41ea58852e [file] [log] [blame]
// Copyright 2013 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/quic/quic_test_packet_maker.h"
#include <list>
#include <utility>
#include "net/quic/mock_crypto_client_stream.h"
#include "net/quic/quic_http_utils.h"
#include "net/third_party/quic/core/quic_framer.h"
#include "net/third_party/quic/core/quic_utils.h"
#include "net/third_party/quic/test_tools/mock_random.h"
#include "net/third_party/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quic/test_tools/simple_data_producer.h"
namespace net {
namespace test {
namespace {
quic::QuicAckFrame MakeAckFrame(uint64_t largest_observed) {
quic::QuicAckFrame ack;
ack.largest_acked = quic::QuicPacketNumber(largest_observed);
return ack;
}
} // namespace
QuicTestPacketMaker::QuicTestPacketMaker(
quic::QuicTransportVersion version,
quic::QuicConnectionId connection_id,
quic::MockClock* clock,
const std::string& host,
quic::Perspective perspective,
bool client_headers_include_h2_stream_dependency)
: version_(version),
connection_id_(connection_id),
clock_(clock),
host_(host),
spdy_request_framer_(spdy::SpdyFramer::ENABLE_COMPRESSION),
spdy_response_framer_(spdy::SpdyFramer::ENABLE_COMPRESSION),
perspective_(perspective),
encryption_level_(quic::ENCRYPTION_FORWARD_SECURE),
long_header_type_(quic::INVALID_PACKET_TYPE),
client_headers_include_h2_stream_dependency_(
client_headers_include_h2_stream_dependency &&
version >= quic::QUIC_VERSION_43) {
DCHECK(!(perspective_ == quic::Perspective::IS_SERVER &&
client_headers_include_h2_stream_dependency_));
}
QuicTestPacketMaker::~QuicTestPacketMaker() {}
void QuicTestPacketMaker::set_hostname(const std::string& host) {
host_.assign(host);
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeConnectivityProbingPacket(uint64_t num,
bool include_version) {
quic::QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.destination_connection_id_included = HasDestinationConnectionId();
header.source_connection_id = connection_id_;
header.source_connection_id_included = HasSourceConnectionId();
header.reset_flag = false;
header.version_flag = ShouldIncludeVersion(include_version);
header.long_packet_type = long_header_type_;
header.packet_number_length = GetPacketNumberLength();
header.packet_number = quic::QuicPacketNumber(num);
if (quic::QuicVersionHasLongHeaderLengths(version_) && header.version_flag) {
if (long_header_type_ == quic::INITIAL) {
header.retry_token_length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_1;
}
header.length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_2;
}
quic::QuicFramer framer(quic::test::SupportedVersions(quic::ParsedQuicVersion(
quic::PROTOCOL_QUIC_CRYPTO, version_)),
clock_->Now(), perspective_);
size_t max_plaintext_size =
framer.GetMaxPlaintextSize(quic::kDefaultMaxPacketSize);
char buffer[quic::kDefaultMaxPacketSize];
size_t length;
if (version_ != quic::QUIC_VERSION_99) {
length = framer.BuildConnectivityProbingPacket(
header, buffer, max_plaintext_size, encryption_level_);
} else if (perspective_ == quic::Perspective::IS_CLIENT) {
quic::test::MockRandom rand(0);
quic::QuicPathFrameBuffer payload;
length = framer.BuildPaddedPathChallengePacket(
header, buffer, max_plaintext_size, &payload, &rand, encryption_level_);
} else {
quic::test::MockRandom rand(0);
quic::QuicPathFrameBuffer payload;
rand.RandBytes(payload.data(), payload.size());
quic::QuicDeque<quic::QuicPathFrameBuffer> payloads{payload};
length = framer.BuildPathResponsePacket(header, buffer, max_plaintext_size,
payloads, true, encryption_level_);
}
size_t encrypted_size = framer.EncryptInPlace(
quic::ENCRYPTION_NONE, header.packet_number,
GetStartOfEncryptedData(framer.transport_version(), header), length,
quic::kDefaultMaxPacketSize, buffer);
EXPECT_EQ(quic::kDefaultMaxPacketSize, encrypted_size);
quic::QuicReceivedPacket encrypted(buffer, encrypted_size, clock_->Now(),
false);
return encrypted.Clone();
}
std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakePingPacket(
uint64_t num,
bool include_version) {
quic::QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.destination_connection_id_included = HasDestinationConnectionId();
header.source_connection_id = connection_id_;
header.source_connection_id_included = HasSourceConnectionId();
header.reset_flag = false;
header.version_flag = ShouldIncludeVersion(include_version);
header.long_packet_type = long_header_type_;
header.packet_number_length = GetPacketNumberLength();
header.packet_number = quic::QuicPacketNumber(num);
if (quic::QuicVersionHasLongHeaderLengths(version_) && header.version_flag) {
if (long_header_type_ == quic::INITIAL) {
header.retry_token_length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_1;
}
header.length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_2;
}
quic::QuicPingFrame ping;
return MakePacket(header, quic::QuicFrame(ping));
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeDummyCHLOPacket(uint64_t packet_num) {
SetEncryptionLevel(quic::ENCRYPTION_NONE);
InitializeHeader(packet_num, /*include_version=*/true);
quic::CryptoHandshakeMessage message =
MockCryptoClientStream::GetDummyCHLOMessage();
const quic::QuicData& data = message.GetSerialized();
quic::QuicFrames frames;
quic::QuicCryptoFrame crypto_frame;
quic::test::SimpleDataProducer producer;
quic::QuicStreamFrameDataProducer* producer_p = nullptr;
if (version_ < quic::QUIC_VERSION_47) {
quic::QuicStreamFrame frame(quic::QuicUtils::GetCryptoStreamId(version_),
/*fin=*/false, /*offset=*/0,
data.AsStringPiece());
frames.push_back(quic::QuicFrame(frame));
} else {
crypto_frame =
quic::QuicCryptoFrame(quic::ENCRYPTION_NONE, 0, data.length());
producer.SaveCryptoData(quic::ENCRYPTION_NONE, 0, data.AsStringPiece());
frames.push_back(quic::QuicFrame(&crypto_frame));
producer_p = &producer;
}
DVLOG(1) << "Adding frame: " << frames.back();
quic::QuicPaddingFrame padding;
frames.push_back(quic::QuicFrame(padding));
DVLOG(1) << "Adding frame: " << frames.back();
std::unique_ptr<quic::QuicReceivedPacket> packet =
MakeMultipleFramesPacket(header_, frames, producer_p);
return packet;
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeAckAndPingPacket(uint64_t num,
bool include_version,
uint64_t largest_received,
uint64_t smallest_received,
uint64_t least_unacked) {
quic::QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.destination_connection_id_included = HasDestinationConnectionId();
header.source_connection_id = connection_id_;
header.source_connection_id_included = HasSourceConnectionId();
header.reset_flag = false;
header.version_flag = ShouldIncludeVersion(include_version);
header.long_packet_type = long_header_type_;
header.packet_number_length = GetPacketNumberLength();
header.packet_number = quic::QuicPacketNumber(num);
if (quic::QuicVersionHasLongHeaderLengths(version_) && header.version_flag) {
if (long_header_type_ == quic::INITIAL) {
header.retry_token_length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_1;
}
header.length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_2;
}
quic::QuicAckFrame ack(MakeAckFrame(largest_received));
ack.ack_delay_time = quic::QuicTime::Delta::Zero();
for (uint64_t i = smallest_received; i <= largest_received; ++i) {
ack.received_packet_times.push_back(
std::make_pair(quic::QuicPacketNumber(i), clock_->Now()));
}
if (largest_received > 0) {
ack.packets.AddRange(quic::QuicPacketNumber(1),
quic::QuicPacketNumber(largest_received + 1));
}
quic::QuicFrames frames;
frames.push_back(quic::QuicFrame(&ack));
DVLOG(1) << "Adding frame: " << frames.back();
frames.push_back(quic::QuicFrame(quic::QuicPingFrame()));
DVLOG(1) << "Adding frame: " << frames.back();
return MakeMultipleFramesPacket(header, frames, nullptr);
}
std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakeRstPacket(
uint64_t num,
bool include_version,
quic::QuicStreamId stream_id,
quic::QuicRstStreamErrorCode error_code) {
return MakeRstPacket(num, include_version, stream_id, error_code, 0,
/*include_stop_sending_if_v99=*/true);
}
std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakeRstPacket(
uint64_t num,
bool include_version,
quic::QuicStreamId stream_id,
quic::QuicRstStreamErrorCode error_code,
size_t bytes_written,
bool include_stop_sending_if_v99) {
quic::QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.destination_connection_id_included = HasDestinationConnectionId();
header.source_connection_id = connection_id_;
header.source_connection_id_included = HasSourceConnectionId();
header.reset_flag = false;
header.version_flag = ShouldIncludeVersion(include_version);
header.long_packet_type = long_header_type_;
header.packet_number_length = GetPacketNumberLength();
header.packet_number = quic::QuicPacketNumber(num);
if (quic::QuicVersionHasLongHeaderLengths(version_) && header.version_flag) {
if (long_header_type_ == quic::INITIAL) {
header.retry_token_length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_1;
}
header.length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_2;
}
quic::QuicFrames frames;
quic::QuicRstStreamFrame rst(1, stream_id, error_code, bytes_written);
frames.push_back(quic::QuicFrame(&rst));
DVLOG(1) << "Adding frame: " << frames.back();
// The STOP_SENDING frame must be outside of the if (version==99) so that it
// stays in scope until the packet is built.
quic::QuicStopSendingFrame stop(1, stream_id, error_code);
if (include_stop_sending_if_v99 && version_ == quic::QUIC_VERSION_99) {
frames.push_back(quic::QuicFrame(&stop));
DVLOG(1) << "Adding frame: " << frames.back();
}
return MakeMultipleFramesPacket(header, frames, nullptr);
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeStreamIdBlockedPacket(uint64_t num,
bool include_version,
quic::QuicStreamId stream_id) {
quic::QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.destination_connection_id_included = HasDestinationConnectionId();
header.source_connection_id = connection_id_;
header.source_connection_id_included = HasSourceConnectionId();
header.reset_flag = false;
header.version_flag = ShouldIncludeVersion(include_version);
header.long_packet_type = long_header_type_;
header.packet_number_length = GetPacketNumberLength();
header.packet_number = quic::QuicPacketNumber(num);
if (quic::QuicVersionHasLongHeaderLengths(version_) && header.version_flag) {
if (long_header_type_ == quic::INITIAL) {
header.retry_token_length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_1;
}
header.length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_2;
}
quic::QuicStreamIdBlockedFrame frame(1, stream_id);
DVLOG(1) << "Adding frame: " << quic::QuicFrame(frame);
return MakePacket(header, quic::QuicFrame(frame));
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeMaxStreamIdPacket(uint64_t num,
bool include_version,
quic::QuicStreamId stream_id) {
quic::QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.destination_connection_id_included = HasDestinationConnectionId();
header.source_connection_id = connection_id_;
header.source_connection_id_included = HasSourceConnectionId();
header.reset_flag = false;
header.version_flag = ShouldIncludeVersion(include_version);
header.long_packet_type = long_header_type_;
header.packet_number_length = GetPacketNumberLength();
header.packet_number = quic::QuicPacketNumber(num);
if (quic::QuicVersionHasLongHeaderLengths(version_) && header.version_flag) {
if (long_header_type_ == quic::INITIAL) {
header.retry_token_length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_1;
}
header.length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_2;
}
quic::QuicMaxStreamIdFrame frame(1, stream_id);
DVLOG(1) << "Adding frame: " << quic::QuicFrame(frame);
return MakePacket(header, quic::QuicFrame(frame));
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeRstAndRequestHeadersPacket(
uint64_t num,
bool include_version,
quic::QuicStreamId rst_stream_id,
quic::QuicRstStreamErrorCode rst_error_code,
quic::QuicStreamId stream_id,
bool fin,
spdy::SpdyPriority priority,
spdy::SpdyHeaderBlock headers,
quic::QuicStreamId parent_stream_id,
size_t* spdy_headers_frame_length,
quic::QuicStreamOffset* offset) {
quic::QuicRstStreamFrame rst_frame(1, rst_stream_id, rst_error_code, 0);
spdy::SpdySerializedFrame spdy_frame = MakeSpdyHeadersFrame(
stream_id, fin, priority, std::move(headers), parent_stream_id);
if (spdy_headers_frame_length) {
*spdy_headers_frame_length = spdy_frame.size();
}
quic::QuicStreamOffset header_offset = 0;
if (offset != nullptr) {
header_offset = *offset;
*offset += spdy_frame.size();
}
quic::QuicStreamFrame headers_frame(
quic::QuicUtils::GetHeadersStreamId(version_), false, header_offset,
quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
quic::QuicFrames frames;
frames.push_back(quic::QuicFrame(&rst_frame));
DVLOG(1) << "Adding frame: " << frames.back();
// The STOP_SENDING frame must be outside of the if (version==99) so that it
// stays in scope until the packet is built.
quic::QuicStopSendingFrame stop(1, rst_stream_id, rst_error_code);
if (version_ == quic::QUIC_VERSION_99) {
frames.push_back(quic::QuicFrame(&stop));
DVLOG(1) << "Adding frame: " << frames.back();
}
frames.push_back(quic::QuicFrame(headers_frame));
DVLOG(1) << "Adding frame: " << frames.back();
InitializeHeader(num, include_version);
return MakeMultipleFramesPacket(header_, frames, nullptr);
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeAckAndRstPacket(
uint64_t num,
bool include_version,
quic::QuicStreamId stream_id,
quic::QuicRstStreamErrorCode error_code,
uint64_t largest_received,
uint64_t smallest_received,
uint64_t least_unacked,
bool send_feedback) {
return MakeAckAndRstPacket(num, include_version, stream_id, error_code,
largest_received, smallest_received, least_unacked,
send_feedback, 0,
/*include_stop_sending_if_v99=*/true);
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeAckAndRstPacket(
uint64_t num,
bool include_version,
quic::QuicStreamId stream_id,
quic::QuicRstStreamErrorCode error_code,
uint64_t largest_received,
uint64_t smallest_received,
uint64_t least_unacked,
bool send_feedback,
size_t bytes_written,
bool include_stop_sending_if_v99) {
quic::QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.destination_connection_id_included = HasDestinationConnectionId();
header.source_connection_id = connection_id_;
header.source_connection_id_included = HasSourceConnectionId();
header.reset_flag = false;
header.version_flag = ShouldIncludeVersion(include_version);
header.long_packet_type = long_header_type_;
header.packet_number_length = GetPacketNumberLength();
header.packet_number = quic::QuicPacketNumber(num);
if (quic::QuicVersionHasLongHeaderLengths(version_) && header.version_flag) {
if (long_header_type_ == quic::INITIAL) {
header.retry_token_length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_1;
}
header.length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_2;
}
quic::QuicAckFrame ack(MakeAckFrame(largest_received));
ack.ack_delay_time = quic::QuicTime::Delta::Zero();
for (uint64_t i = smallest_received; i <= largest_received; ++i) {
ack.received_packet_times.push_back(
std::make_pair(quic::QuicPacketNumber(i), clock_->Now()));
}
if (largest_received > 0) {
ack.packets.AddRange(quic::QuicPacketNumber(1),
quic::QuicPacketNumber(largest_received + 1));
}
quic::QuicFrames frames;
frames.push_back(quic::QuicFrame(&ack));
DVLOG(1) << "Adding frame: " << frames.back();
quic::QuicRstStreamFrame rst(1, stream_id, error_code, bytes_written);
frames.push_back(quic::QuicFrame(&rst));
DVLOG(1) << "Adding frame: " << frames.back();
// The STOP_SENDING frame must be outside of the if (version==99) so that it
// stays in scope until the packet is built.
quic::QuicStopSendingFrame stop(1, stream_id, error_code);
if (version_ == quic::QUIC_VERSION_99 && include_stop_sending_if_v99) {
frames.push_back(quic::QuicFrame(&stop));
DVLOG(1) << "Adding frame: " << frames.back();
}
return MakeMultipleFramesPacket(header, frames, nullptr);
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeRstAckAndConnectionClosePacket(
uint64_t num,
bool include_version,
quic::QuicStreamId stream_id,
quic::QuicRstStreamErrorCode error_code,
quic::QuicTime::Delta ack_delay_time,
uint64_t largest_received,
uint64_t smallest_received,
uint64_t least_unacked,
quic::QuicErrorCode quic_error,
const std::string& quic_error_details) {
quic::QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.destination_connection_id_included = HasDestinationConnectionId();
header.source_connection_id = connection_id_;
header.source_connection_id_included = HasSourceConnectionId();
header.reset_flag = false;
header.version_flag = ShouldIncludeVersion(include_version);
header.long_packet_type = long_header_type_;
header.packet_number_length = GetPacketNumberLength();
header.packet_number = quic::QuicPacketNumber(num);
if (quic::QuicVersionHasLongHeaderLengths(version_) && header.version_flag) {
if (long_header_type_ == quic::INITIAL) {
header.retry_token_length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_1;
}
header.length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_2;
}
quic::QuicFrames frames;
quic::QuicRstStreamFrame rst(1, stream_id, error_code, 0);
frames.push_back(quic::QuicFrame(&rst));
DVLOG(1) << "Adding frame: " << frames.back();
// The STOP_SENDING frame must be outside of the if (version==99) so that it
// stays in scope until the packet is built.
quic::QuicStopSendingFrame stop(
1, stream_id, static_cast<quic::QuicApplicationErrorCode>(error_code));
if (version_ == quic::QUIC_VERSION_99) {
frames.push_back(quic::QuicFrame(&stop));
DVLOG(1) << "Adding frame: " << frames.back();
}
quic::QuicAckFrame ack(MakeAckFrame(largest_received));
ack.ack_delay_time = ack_delay_time;
for (uint64_t i = smallest_received; i <= largest_received; ++i) {
ack.received_packet_times.push_back(
std::make_pair(quic::QuicPacketNumber(i), clock_->Now()));
}
if (largest_received > 0) {
ack.packets.AddRange(quic::QuicPacketNumber(1),
quic::QuicPacketNumber(largest_received + 1));
}
frames.push_back(quic::QuicFrame(&ack));
DVLOG(1) << "Adding frame: " << frames.back();
quic::QuicConnectionCloseFrame close;
close.error_code = quic_error;
close.error_details = quic_error_details;
frames.push_back(quic::QuicFrame(&close));
DVLOG(1) << "Adding frame: " << frames.back();
return MakeMultipleFramesPacket(header, frames, nullptr);
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeAckAndConnectionClosePacket(
uint64_t num,
bool include_version,
quic::QuicTime::Delta ack_delay_time,
uint64_t largest_received,
uint64_t smallest_received,
uint64_t least_unacked,
quic::QuicErrorCode quic_error,
const std::string& quic_error_details) {
quic::QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.destination_connection_id_included = HasDestinationConnectionId();
header.source_connection_id = connection_id_;
header.source_connection_id_included = HasSourceConnectionId();
header.reset_flag = false;
header.version_flag = ShouldIncludeVersion(include_version);
header.long_packet_type = long_header_type_;
header.packet_number_length = GetPacketNumberLength();
header.packet_number = quic::QuicPacketNumber(num);
if (quic::QuicVersionHasLongHeaderLengths(version_) && header.version_flag) {
if (long_header_type_ == quic::INITIAL) {
header.retry_token_length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_1;
}
header.length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_2;
}
quic::QuicAckFrame ack(MakeAckFrame(largest_received));
ack.ack_delay_time = ack_delay_time;
for (uint64_t i = smallest_received; i <= largest_received; ++i) {
ack.received_packet_times.push_back(
std::make_pair(quic::QuicPacketNumber(i), clock_->Now()));
}
if (largest_received > 0) {
ack.packets.AddRange(quic::QuicPacketNumber(1),
quic::QuicPacketNumber(largest_received + 1));
}
quic::QuicFrames frames;
frames.push_back(quic::QuicFrame(&ack));
DVLOG(1) << "Adding frame: " << frames.back();
quic::QuicConnectionCloseFrame close;
close.error_code = quic_error;
close.error_details = quic_error_details;
frames.push_back(quic::QuicFrame(&close));
DVLOG(1) << "Adding frame: " << frames.back();
return MakeMultipleFramesPacket(header, frames, nullptr);
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeConnectionClosePacket(
uint64_t num,
bool include_version,
quic::QuicErrorCode quic_error,
const std::string& quic_error_details) {
quic::QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.destination_connection_id_included = HasDestinationConnectionId();
header.source_connection_id = connection_id_;
header.source_connection_id_included = HasSourceConnectionId();
header.reset_flag = false;
header.version_flag = ShouldIncludeVersion(include_version);
header.long_packet_type = long_header_type_;
header.packet_number_length = GetPacketNumberLength();
header.packet_number = quic::QuicPacketNumber(num);
if (quic::QuicVersionHasLongHeaderLengths(version_) && header.version_flag) {
if (long_header_type_ == quic::INITIAL) {
header.retry_token_length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_1;
}
header.length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_2;
}
quic::QuicConnectionCloseFrame close;
close.error_code = quic_error;
close.error_details = quic_error_details;
return MakePacket(header, quic::QuicFrame(&close));
}
std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakeGoAwayPacket(
uint64_t num,
quic::QuicErrorCode error_code,
std::string reason_phrase) {
quic::QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.destination_connection_id_included = HasDestinationConnectionId();
header.source_connection_id = connection_id_;
header.source_connection_id_included = HasSourceConnectionId();
header.reset_flag = false;
header.version_flag = ShouldIncludeVersion(false);
header.long_packet_type = long_header_type_;
header.packet_number_length = GetPacketNumberLength();
header.packet_number = quic::QuicPacketNumber(num);
if (quic::QuicVersionHasLongHeaderLengths(version_) && header.version_flag) {
if (long_header_type_ == quic::INITIAL) {
header.retry_token_length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_1;
}
header.length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_2;
}
quic::QuicGoAwayFrame goaway;
goaway.error_code = error_code;
goaway.last_good_stream_id = 0;
goaway.reason_phrase = reason_phrase;
return MakePacket(header, quic::QuicFrame(&goaway));
}
std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakeAckPacket(
uint64_t packet_number,
uint64_t largest_received,
uint64_t smallest_received,
uint64_t least_unacked,
bool send_feedback) {
return MakeAckPacket(packet_number, 1, largest_received, smallest_received,
least_unacked, send_feedback,
quic::QuicTime::Delta::Zero());
}
std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakeAckPacket(
uint64_t packet_number,
uint64_t first_received,
uint64_t largest_received,
uint64_t smallest_received,
uint64_t least_unacked,
bool send_feedback) {
return MakeAckPacket(packet_number, first_received, largest_received,
smallest_received, least_unacked, send_feedback,
quic::QuicTime::Delta::Zero());
}
std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakeAckPacket(
uint64_t packet_number,
uint64_t largest_received,
uint64_t smallest_received,
uint64_t least_unacked,
bool send_feedback,
quic::QuicTime::Delta ack_delay_time) {
return MakeAckPacket(packet_number, 1, largest_received, smallest_received,
least_unacked, send_feedback, ack_delay_time);
}
std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakeAckPacket(
uint64_t packet_number,
uint64_t first_received,
uint64_t largest_received,
uint64_t smallest_received,
uint64_t least_unacked,
bool send_feedback,
quic::QuicTime::Delta ack_delay_time) {
quic::QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.destination_connection_id_included = HasDestinationConnectionId();
header.source_connection_id = connection_id_;
header.source_connection_id_included = HasSourceConnectionId();
header.reset_flag = false;
header.version_flag = ShouldIncludeVersion(false);
header.long_packet_type = long_header_type_;
header.packet_number_length = GetPacketNumberLength();
header.packet_number = quic::QuicPacketNumber(packet_number);
if (quic::QuicVersionHasLongHeaderLengths(version_) && header.version_flag) {
if (long_header_type_ == quic::INITIAL) {
header.retry_token_length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_1;
}
header.length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_2;
}
quic::QuicAckFrame ack(MakeAckFrame(largest_received));
ack.ack_delay_time = ack_delay_time;
for (uint64_t i = smallest_received; i <= largest_received; ++i) {
ack.received_packet_times.push_back(
std::make_pair(quic::QuicPacketNumber(i), clock_->Now()));
}
if (largest_received > 0) {
DCHECK_GE(largest_received, first_received);
ack.packets.AddRange(quic::QuicPacketNumber(first_received),
quic::QuicPacketNumber(largest_received + 1));
}
quic::QuicFramer framer(quic::test::SupportedVersions(quic::ParsedQuicVersion(
quic::PROTOCOL_QUIC_CRYPTO, version_)),
clock_->Now(), perspective_);
quic::QuicFrames frames;
quic::QuicFrame ack_frame(&ack);
frames.push_back(ack_frame);
DVLOG(1) << "Adding frame: " << frames.back();
std::unique_ptr<quic::QuicPacket> packet(
quic::test::BuildUnsizedDataPacket(&framer, header, frames));
char buffer[quic::kMaxPacketSize];
size_t encrypted_size =
framer.EncryptPayload(quic::ENCRYPTION_NONE, header.packet_number,
*packet, buffer, quic::kMaxPacketSize);
EXPECT_NE(0u, encrypted_size);
quic::QuicReceivedPacket encrypted(buffer, encrypted_size, clock_->Now(),
false);
return encrypted.Clone();
}
// Returns a newly created packet to send kData on stream 1.
std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakeDataPacket(
uint64_t packet_number,
quic::QuicStreamId stream_id,
bool should_include_version,
bool fin,
quic::QuicStreamOffset offset,
quic::QuicStringPiece data) {
InitializeHeader(packet_number, should_include_version);
quic::QuicStreamFrame frame(stream_id, fin, offset, data);
DVLOG(1) << "Adding frame: " << frame;
return MakePacket(header_, quic::QuicFrame(frame));
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeMultipleDataFramesPacket(
uint64_t packet_number,
quic::QuicStreamId stream_id,
bool should_include_version,
bool fin,
quic::QuicStreamOffset offset,
const std::vector<std::string>& data_writes) {
InitializeHeader(packet_number, should_include_version);
quic::QuicFrames data_frames;
for (size_t i = 0; i < data_writes.size(); ++i) {
bool is_fin = fin && (i == data_writes.size() - 1);
quic::QuicFrame quic_frame(quic::QuicStreamFrame(
stream_id, is_fin, offset, quic::QuicStringPiece(data_writes[i])));
DVLOG(1) << "Adding frame: " << quic_frame;
data_frames.push_back(quic_frame);
offset += data_writes[i].length();
}
return MakeMultipleFramesPacket(header_, data_frames, nullptr);
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeAckAndDataPacket(uint64_t packet_number,
bool include_version,
quic::QuicStreamId stream_id,
uint64_t largest_received,
uint64_t smallest_received,
uint64_t least_unacked,
bool fin,
quic::QuicStreamOffset offset,
quic::QuicStringPiece data) {
InitializeHeader(packet_number, include_version);
quic::QuicAckFrame ack(MakeAckFrame(largest_received));
ack.ack_delay_time = quic::QuicTime::Delta::Zero();
for (uint64_t i = smallest_received; i <= largest_received; ++i) {
ack.received_packet_times.push_back(
std::make_pair(quic::QuicPacketNumber(i), clock_->Now()));
}
if (largest_received > 0) {
ack.packets.AddRange(quic::QuicPacketNumber(1),
quic::QuicPacketNumber(largest_received + 1));
}
quic::QuicFrames frames;
frames.push_back(quic::QuicFrame(&ack));
DVLOG(1) << "Adding frame: " << frames.back();
frames.push_back(
quic::QuicFrame(quic::QuicStreamFrame(stream_id, fin, offset, data)));
DVLOG(1) << "Adding frame: " << frames.back();
return MakeMultipleFramesPacket(header_, frames, nullptr);
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeAckAndMultipleDataFramesPacket(
uint64_t packet_number,
bool include_version,
quic::QuicStreamId stream_id,
uint64_t largest_received,
uint64_t smallest_received,
uint64_t least_unacked,
bool fin,
quic::QuicStreamOffset offset,
const std::vector<std::string>& data_writes) {
InitializeHeader(packet_number, include_version);
quic::QuicAckFrame ack(MakeAckFrame(largest_received));
ack.ack_delay_time = quic::QuicTime::Delta::Zero();
for (uint64_t i = smallest_received; i <= largest_received; ++i) {
ack.received_packet_times.push_back(
std::make_pair(quic::QuicPacketNumber(i), clock_->Now()));
}
if (largest_received > 0) {
ack.packets.AddRange(quic::QuicPacketNumber(1),
quic::QuicPacketNumber(largest_received + 1));
}
quic::QuicFrames frames;
frames.push_back(quic::QuicFrame(&ack));
DVLOG(1) << "Adding frame: " << frames.back();
for (size_t i = 0; i < data_writes.size(); ++i) {
bool is_fin = fin && (i == data_writes.size() - 1);
quic::QuicFrame quic_frame(quic::QuicStreamFrame(
stream_id, is_fin, offset, quic::QuicStringPiece(data_writes[i])));
DVLOG(1) << "Adding frame: " << quic_frame;
frames.push_back(quic_frame);
offset += data_writes[i].length();
}
return MakeMultipleFramesPacket(header_, frames, nullptr);
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeRequestHeadersAndMultipleDataFramesPacket(
uint64_t packet_number,
quic::QuicStreamId stream_id,
bool should_include_version,
bool fin,
spdy::SpdyPriority priority,
spdy::SpdyHeaderBlock headers,
quic::QuicStreamId parent_stream_id,
quic::QuicStreamOffset* header_stream_offset,
size_t* spdy_headers_frame_length,
const std::vector<std::string>& data_writes) {
InitializeHeader(packet_number, should_include_version);
spdy::SpdySerializedFrame spdy_frame =
MakeSpdyHeadersFrame(stream_id, fin && data_writes.empty(), priority,
std::move(headers), parent_stream_id);
if (spdy_headers_frame_length) {
*spdy_headers_frame_length = spdy_frame.size();
}
quic::QuicFrames frames;
quic::QuicStreamOffset header_offset =
header_stream_offset == nullptr ? 0 : *header_stream_offset;
quic::QuicStreamFrame frame(
quic::QuicUtils::GetHeadersStreamId(version_), false, header_offset,
quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
frames.push_back(quic::QuicFrame(frame));
DVLOG(1) << "Adding frame: " << frames.back();
if (header_stream_offset != nullptr) {
*header_stream_offset += spdy_frame.size();
}
quic::QuicStreamOffset offset = 0;
// quic::QuicFrame takes a raw pointer. Use a std::vector here so we keep
// StreamFrames alive until MakeMultipleFramesPacket is done.
std::vector<std::unique_ptr<quic::QuicStreamFrame>> stream_frames;
for (size_t i = 0; i < data_writes.size(); ++i) {
bool is_fin = fin && (i == data_writes.size() - 1);
quic::QuicFrame quic_frame(quic::QuicStreamFrame(
stream_id, is_fin, offset, quic::QuicStringPiece(data_writes[i])));
DVLOG(1) << "Adding frame: " << quic_frame;
frames.push_back(quic_frame);
offset += data_writes[i].length();
}
return MakeMultipleFramesPacket(header_, frames, nullptr);
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeRequestHeadersPacket(
uint64_t packet_number,
quic::QuicStreamId stream_id,
bool should_include_version,
bool fin,
spdy::SpdyPriority priority,
spdy::SpdyHeaderBlock headers,
quic::QuicStreamId parent_stream_id,
size_t* spdy_headers_frame_length) {
return MakeRequestHeadersPacket(
packet_number, stream_id, should_include_version, fin, priority,
std::move(headers), parent_stream_id, spdy_headers_frame_length, nullptr);
}
// If |offset| is provided, will use the value when creating the packet.
// Will also update the value after packet creation.
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeRequestHeadersPacket(
uint64_t packet_number,
quic::QuicStreamId stream_id,
bool should_include_version,
bool fin,
spdy::SpdyPriority priority,
spdy::SpdyHeaderBlock headers,
quic::QuicStreamId parent_stream_id,
size_t* spdy_headers_frame_length,
quic::QuicStreamOffset* offset) {
std::string unused_stream_data;
return MakeRequestHeadersPacketAndSaveData(
packet_number, stream_id, should_include_version, fin, priority,
std::move(headers), parent_stream_id, spdy_headers_frame_length, offset,
&unused_stream_data);
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeRequestHeadersPacketAndSaveData(
uint64_t packet_number,
quic::QuicStreamId stream_id,
bool should_include_version,
bool fin,
spdy::SpdyPriority priority,
spdy::SpdyHeaderBlock headers,
quic::QuicStreamId parent_stream_id,
size_t* spdy_headers_frame_length,
quic::QuicStreamOffset* offset,
std::string* stream_data) {
InitializeHeader(packet_number, should_include_version);
spdy::SpdySerializedFrame spdy_frame = MakeSpdyHeadersFrame(
stream_id, fin, priority, std::move(headers), parent_stream_id);
*stream_data = std::string(spdy_frame.data(), spdy_frame.size());
if (spdy_headers_frame_length)
*spdy_headers_frame_length = spdy_frame.size();
if (offset != nullptr) {
quic::QuicStreamFrame frame(
quic::QuicUtils::GetHeadersStreamId(version_), false, *offset,
quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
*offset += spdy_frame.size();
return MakePacket(header_, quic::QuicFrame(frame));
} else {
quic::QuicStreamFrame frame(
quic::QuicUtils::GetHeadersStreamId(version_), false, 0,
quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
return MakePacket(header_, quic::QuicFrame(frame));
}
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeRequestHeadersAndRstPacket(
uint64_t packet_number,
quic::QuicStreamId stream_id,
bool should_include_version,
bool fin,
spdy::SpdyPriority priority,
spdy::SpdyHeaderBlock headers,
quic::QuicStreamId parent_stream_id,
size_t* spdy_headers_frame_length,
quic::QuicStreamOffset* header_stream_offset,
quic::QuicRstStreamErrorCode error_code,
size_t bytes_written) {
spdy::SpdySerializedFrame spdy_frame = MakeSpdyHeadersFrame(
stream_id, fin, priority, std::move(headers), parent_stream_id);
if (spdy_headers_frame_length) {
*spdy_headers_frame_length = spdy_frame.size();
}
quic::QuicStreamOffset header_offset = 0;
if (header_stream_offset != nullptr) {
header_offset = *header_stream_offset;
*header_stream_offset += spdy_frame.size();
}
quic::QuicStreamFrame headers_frame(
quic::QuicUtils::GetHeadersStreamId(version_), false, header_offset,
quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
quic::QuicRstStreamFrame rst_frame(1, stream_id, error_code, bytes_written);
quic::QuicFrames frames;
frames.push_back(quic::QuicFrame(headers_frame));
DVLOG(1) << "Adding frame: " << frames.back();
frames.push_back(quic::QuicFrame(&rst_frame));
DVLOG(1) << "Adding frame: " << frames.back();
// The STOP_SENDING frame must be outside of the if (version==99) so that it
// stays in scope until the packet is built.
quic::QuicStopSendingFrame stop(1, stream_id, error_code);
if (version_ == quic::QUIC_VERSION_99) {
frames.push_back(quic::QuicFrame(&stop));
DVLOG(1) << "Adding frame: " << frames.back();
}
InitializeHeader(packet_number, should_include_version);
return MakeMultipleFramesPacket(header_, frames, nullptr);
}
spdy::SpdySerializedFrame QuicTestPacketMaker::MakeSpdyHeadersFrame(
quic::QuicStreamId stream_id,
bool fin,
spdy::SpdyPriority priority,
spdy::SpdyHeaderBlock headers,
quic::QuicStreamId parent_stream_id) {
spdy::SpdyHeadersIR headers_frame(stream_id, std::move(headers));
headers_frame.set_fin(fin);
headers_frame.set_weight(spdy::Spdy3PriorityToHttp2Weight(priority));
headers_frame.set_has_priority(true);
if (client_headers_include_h2_stream_dependency_) {
headers_frame.set_parent_stream_id(parent_stream_id);
headers_frame.set_exclusive(true);
} else {
headers_frame.set_parent_stream_id(0);
headers_frame.set_exclusive(false);
}
return spdy_request_framer_.SerializeFrame(headers_frame);
}
// Convenience method for calling MakeRequestHeadersPacket with nullptr for
// |spdy_headers_frame_length|.
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeRequestHeadersPacketWithOffsetTracking(
uint64_t packet_number,
quic::QuicStreamId stream_id,
bool should_include_version,
bool fin,
spdy::SpdyPriority priority,
spdy::SpdyHeaderBlock headers,
quic::QuicStreamId parent_stream_id,
quic::QuicStreamOffset* offset) {
return MakeRequestHeadersPacket(
packet_number, stream_id, should_include_version, fin, priority,
std::move(headers), parent_stream_id, nullptr, offset);
}
// If |offset| is provided, will use the value when creating the packet.
// Will also update the value after packet creation.
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakePushPromisePacket(
uint64_t packet_number,
quic::QuicStreamId stream_id,
quic::QuicStreamId promised_stream_id,
bool should_include_version,
bool fin,
spdy::SpdyHeaderBlock headers,
size_t* spdy_headers_frame_length,
quic::QuicStreamOffset* offset) {
InitializeHeader(packet_number, should_include_version);
spdy::SpdySerializedFrame spdy_frame;
spdy::SpdyPushPromiseIR promise_frame(stream_id, promised_stream_id,
std::move(headers));
promise_frame.set_fin(fin);
spdy_frame = spdy_request_framer_.SerializeFrame(promise_frame);
if (spdy_headers_frame_length) {
*spdy_headers_frame_length = spdy_frame.size();
}
if (offset != nullptr) {
quic::QuicStreamFrame frame(
quic::QuicUtils::GetHeadersStreamId(version_), false, *offset,
quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
*offset += spdy_frame.size();
return MakePacket(header_, quic::QuicFrame(frame));
} else {
quic::QuicStreamFrame frame(
quic::QuicUtils::GetHeadersStreamId(version_), false, 0,
quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
return MakePacket(header_, quic::QuicFrame(frame));
}
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeForceHolDataPacket(uint64_t packet_number,
quic::QuicStreamId stream_id,
bool should_include_version,
bool fin,
quic::QuicStreamOffset* offset,
quic::QuicStringPiece data) {
spdy::SpdyDataIR spdy_data(stream_id, data);
spdy_data.set_fin(fin);
spdy::SpdySerializedFrame spdy_frame(
spdy_request_framer_.SerializeFrame(spdy_data));
InitializeHeader(packet_number, should_include_version);
quic::QuicStreamFrame quic_frame(
quic::QuicUtils::GetHeadersStreamId(version_), false, *offset,
quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
*offset += spdy_frame.size();
return MakePacket(header_, quic::QuicFrame(quic_frame));
}
// If |offset| is provided, will use the value when creating the packet.
// Will also update the value after packet creation.
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeResponseHeadersPacket(
uint64_t packet_number,
quic::QuicStreamId stream_id,
bool should_include_version,
bool fin,
spdy::SpdyHeaderBlock headers,
size_t* spdy_headers_frame_length,
quic::QuicStreamOffset* offset) {
InitializeHeader(packet_number, should_include_version);
spdy::SpdySerializedFrame spdy_frame;
spdy::SpdyHeadersIR headers_frame(stream_id, std::move(headers));
headers_frame.set_fin(fin);
spdy_frame = spdy_response_framer_.SerializeFrame(headers_frame);
if (spdy_headers_frame_length) {
*spdy_headers_frame_length = spdy_frame.size();
}
if (offset != nullptr) {
quic::QuicStreamFrame frame(
quic::QuicUtils::GetHeadersStreamId(version_), false, *offset,
quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
*offset += spdy_frame.size();
return MakePacket(header_, quic::QuicFrame(frame));
} else {
quic::QuicStreamFrame frame(
quic::QuicUtils::GetHeadersStreamId(version_), false, 0,
quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
return MakePacket(header_, quic::QuicFrame(frame));
}
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeResponseHeadersPacket(
uint64_t packet_number,
quic::QuicStreamId stream_id,
bool should_include_version,
bool fin,
spdy::SpdyHeaderBlock headers,
size_t* spdy_headers_frame_length) {
return MakeResponseHeadersPacket(
packet_number, stream_id, should_include_version, fin, std::move(headers),
spdy_headers_frame_length, nullptr);
}
// Convenience method for calling MakeResponseHeadersPacket with nullptr for
// |spdy_headers_frame_length|.
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeResponseHeadersPacketWithOffsetTracking(
uint64_t packet_number,
quic::QuicStreamId stream_id,
bool should_include_version,
bool fin,
spdy::SpdyHeaderBlock headers,
quic::QuicStreamOffset* offset) {
return MakeResponseHeadersPacket(packet_number, stream_id,
should_include_version, fin,
std::move(headers), nullptr, offset);
}
spdy::SpdyHeaderBlock QuicTestPacketMaker::GetRequestHeaders(
const std::string& method,
const std::string& scheme,
const std::string& path) {
spdy::SpdyHeaderBlock headers;
headers[":method"] = method;
headers[":authority"] = host_;
headers[":scheme"] = scheme;
headers[":path"] = path;
return headers;
}
spdy::SpdyHeaderBlock QuicTestPacketMaker::ConnectRequestHeaders(
const std::string& host_port) {
spdy::SpdyHeaderBlock headers;
headers[":method"] = "CONNECT";
headers[":authority"] = host_port;
return headers;
}
spdy::SpdyHeaderBlock QuicTestPacketMaker::GetResponseHeaders(
const std::string& status) {
spdy::SpdyHeaderBlock headers;
headers[":status"] = status;
headers["content-type"] = "text/plain";
return headers;
}
spdy::SpdyHeaderBlock QuicTestPacketMaker::GetResponseHeaders(
const std::string& status,
const std::string& alt_svc) {
spdy::SpdyHeaderBlock headers;
headers[":status"] = status;
headers["alt-svc"] = alt_svc;
headers["content-type"] = "text/plain";
return headers;
}
std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakePacket(
const quic::QuicPacketHeader& header,
const quic::QuicFrame& frame) {
quic::QuicFrames frames;
frames.push_back(frame);
return MakeMultipleFramesPacket(header, frames, nullptr);
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeMultipleFramesPacket(
const quic::QuicPacketHeader& header,
const quic::QuicFrames& frames,
quic::QuicStreamFrameDataProducer* data_producer) {
quic::QuicFramer framer(quic::test::SupportedVersions(quic::ParsedQuicVersion(
quic::PROTOCOL_QUIC_CRYPTO, version_)),
clock_->Now(), perspective_);
if (data_producer != nullptr) {
framer.set_data_producer(data_producer);
}
size_t max_plaintext_size =
framer.GetMaxPlaintextSize(quic::kDefaultMaxPacketSize);
std::unique_ptr<quic::QuicPacket> packet(quic::test::BuildUnsizedDataPacket(
&framer, header, frames, max_plaintext_size));
char buffer[quic::kMaxPacketSize];
size_t encrypted_size =
framer.EncryptPayload(quic::ENCRYPTION_NONE, header.packet_number,
*packet, buffer, quic::kMaxPacketSize);
EXPECT_NE(0u, encrypted_size);
quic::QuicReceivedPacket encrypted(buffer, encrypted_size, clock_->Now(),
false);
return encrypted.Clone();
}
void QuicTestPacketMaker::InitializeHeader(uint64_t packet_number,
bool should_include_version) {
header_.destination_connection_id = connection_id_;
header_.destination_connection_id_included = HasDestinationConnectionId();
header_.source_connection_id = connection_id_;
header_.source_connection_id_included = HasSourceConnectionId();
header_.reset_flag = false;
header_.version_flag = ShouldIncludeVersion(should_include_version);
header_.long_packet_type = long_header_type_;
header_.packet_number_length = GetPacketNumberLength();
header_.packet_number = quic::QuicPacketNumber(packet_number);
if (quic::QuicVersionHasLongHeaderLengths(version_) &&
should_include_version) {
if (long_header_type_ == quic::INITIAL) {
header_.retry_token_length_length =
quic::VARIABLE_LENGTH_INTEGER_LENGTH_1;
}
header_.length_length = quic::VARIABLE_LENGTH_INTEGER_LENGTH_2;
}
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeInitialSettingsPacket(uint64_t packet_number,
quic::QuicStreamOffset* offset) {
std::string unused_data;
return MakeInitialSettingsPacketAndSaveData(packet_number, offset,
&unused_data);
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeInitialSettingsPacketAndSaveData(
uint64_t packet_number,
quic::QuicStreamOffset* offset,
std::string* stream_data) {
spdy::SpdySettingsIR settings_frame;
settings_frame.AddSetting(spdy::SETTINGS_MAX_HEADER_LIST_SIZE,
quic::kDefaultMaxUncompressedHeaderSize);
spdy::SpdySerializedFrame spdy_frame(
spdy_request_framer_.SerializeFrame(settings_frame));
InitializeHeader(packet_number, /*should_include_version*/ true);
*stream_data = std::string(spdy_frame.data(), spdy_frame.size());
if (offset != nullptr) {
quic::QuicStreamFrame quic_frame(
quic::QuicUtils::GetHeadersStreamId(version_), false, *offset,
quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
*offset += spdy_frame.size();
return MakePacket(header_, quic::QuicFrame(quic_frame));
}
quic::QuicStreamFrame quic_frame(
quic::QuicUtils::GetHeadersStreamId(version_), false, 0,
quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
return MakePacket(header_, quic::QuicFrame(quic_frame));
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakePriorityPacket(uint64_t packet_number,
bool should_include_version,
quic::QuicStreamId id,
quic::QuicStreamId parent_stream_id,
spdy::SpdyPriority priority,
quic::QuicStreamOffset* offset) {
if (!client_headers_include_h2_stream_dependency_) {
parent_stream_id = 0;
}
int weight = spdy::Spdy3PriorityToHttp2Weight(priority);
bool exclusive = client_headers_include_h2_stream_dependency_;
spdy::SpdyPriorityIR priority_frame(id, parent_stream_id, weight, exclusive);
spdy::SpdySerializedFrame spdy_frame(
spdy_request_framer_.SerializeFrame(priority_frame));
quic::QuicStreamOffset header_offset = 0;
if (offset != nullptr) {
header_offset = *offset;
*offset += spdy_frame.size();
}
quic::QuicStreamFrame quic_frame(
quic::QuicUtils::GetHeadersStreamId(version_), false, header_offset,
quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
DVLOG(1) << "Adding frame: " << quic::QuicFrame(quic_frame);
InitializeHeader(packet_number, should_include_version);
return MakePacket(header_, quic::QuicFrame(quic_frame));
}
std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeAckAndMultiplePriorityFramesPacket(
uint64_t packet_number,
bool should_include_version,
uint64_t largest_received,
uint64_t smallest_received,
uint64_t least_unacked,
const std::vector<Http2StreamDependency>& priority_frames,
quic::QuicStreamOffset* offset) {
quic::QuicAckFrame ack(MakeAckFrame(largest_received));
ack.ack_delay_time = quic::QuicTime::Delta::Zero();
for (uint64_t i = smallest_received; i <= largest_received; ++i) {
ack.received_packet_times.push_back(
std::make_pair(quic::QuicPacketNumber(i), clock_->Now()));
}
if (largest_received > 0) {
ack.packets.AddRange(quic::QuicPacketNumber(1),
quic::QuicPacketNumber(largest_received + 1));
}
quic::QuicFrames frames;
frames.push_back(quic::QuicFrame(&ack));
DVLOG(1) << "Adding frame: " << frames.back();
const bool exclusive = client_headers_include_h2_stream_dependency_;
quic::QuicStreamOffset header_offset = 0;
if (offset == nullptr) {
offset = &header_offset;
}
// Keep SpdySerializedFrames alive until MakeMultipleFramesPacket is done.
std::vector<std::unique_ptr<spdy::SpdySerializedFrame>> spdy_frames;
for (const Http2StreamDependency& info : priority_frames) {
spdy::SpdyPriorityIR priority_frame(
info.stream_id, info.parent_stream_id,
spdy::Spdy3PriorityToHttp2Weight(info.spdy_priority), exclusive);
spdy_frames.push_back(std::make_unique<spdy::SpdySerializedFrame>(
spdy_request_framer_.SerializeFrame(priority_frame)));
spdy::SpdySerializedFrame* spdy_frame = spdy_frames.back().get();
quic::QuicStreamFrame stream_frame(
quic::QuicUtils::GetHeadersStreamId(version_), false, *offset,
quic::QuicStringPiece(spdy_frame->data(), spdy_frame->size()));
*offset += spdy_frame->size();
frames.push_back(quic::QuicFrame(stream_frame));
DVLOG(1) << "Adding frame: " << frames.back();
}
InitializeHeader(packet_number, should_include_version);
return MakeMultipleFramesPacket(header_, frames, nullptr);
}
void QuicTestPacketMaker::SetEncryptionLevel(quic::EncryptionLevel level) {
encryption_level_ = level;
switch (level) {
case quic::ENCRYPTION_NONE:
long_header_type_ = quic::INITIAL;
break;
case quic::ENCRYPTION_ZERO_RTT:
long_header_type_ = quic::ZERO_RTT_PROTECTED;
break;
case quic::ENCRYPTION_FORWARD_SECURE:
long_header_type_ = quic::INVALID_PACKET_TYPE;
break;
default:
QUIC_BUG << quic::QuicUtils::EncryptionLevelToString(level);
long_header_type_ = quic::INVALID_PACKET_TYPE;
}
}
bool QuicTestPacketMaker::ShouldIncludeVersion(bool include_version) const {
if (version_ > quic::QUIC_VERSION_43) {
return encryption_level_ < quic::ENCRYPTION_FORWARD_SECURE;
}
return include_version;
}
quic::QuicPacketNumberLength QuicTestPacketMaker::GetPacketNumberLength()
const {
if (version_ > quic::QUIC_VERSION_43 &&
encryption_level_ < quic::ENCRYPTION_FORWARD_SECURE &&
version_ != quic::QUIC_VERSION_99) {
return quic::PACKET_4BYTE_PACKET_NUMBER;
}
return quic::PACKET_1BYTE_PACKET_NUMBER;
}
quic::QuicConnectionIdIncluded QuicTestPacketMaker::HasDestinationConnectionId()
const {
if (perspective_ == quic::Perspective::IS_SERVER &&
version_ > quic::QUIC_VERSION_43) {
return quic::CONNECTION_ID_ABSENT;
}
return quic::CONNECTION_ID_PRESENT;
}
quic::QuicConnectionIdIncluded QuicTestPacketMaker::HasSourceConnectionId()
const {
if (perspective_ == quic::Perspective::IS_SERVER &&
version_ > quic::QUIC_VERSION_43 &&
encryption_level_ < quic::ENCRYPTION_FORWARD_SECURE) {
return quic::CONNECTION_ID_PRESENT;
}
return quic::CONNECTION_ID_ABSENT;
}
} // namespace test
} // namespace net