mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-24 22:36:09 +03:00
1178 lines
45 KiB
C++
1178 lines
45 KiB
C++
|
// 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/quic_test_utils.h"
|
||
|
|
||
|
namespace net {
|
||
|
namespace test {
|
||
|
namespace {
|
||
|
|
||
|
quic::QuicAckFrame MakeAckFrame(quic::QuicPacketNumber largest_observed) {
|
||
|
quic::QuicAckFrame ack;
|
||
|
ack.largest_acked = 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::HANDSHAKE),
|
||
|
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(quic::QuicPacketNumber num,
|
||
|
bool include_version) {
|
||
|
quic::QuicPacketHeader header;
|
||
|
header.destination_connection_id = connection_id_;
|
||
|
header.destination_connection_id_length = GetDestinationConnectionIdLength();
|
||
|
header.source_connection_id = connection_id_;
|
||
|
header.source_connection_id_length = GetSourceConnectionIdLength();
|
||
|
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 = num;
|
||
|
|
||
|
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 =
|
||
|
framer.BuildConnectivityProbingPacket(header, buffer, max_plaintext_size);
|
||
|
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(
|
||
|
quic::QuicPacketNumber num,
|
||
|
bool include_version) {
|
||
|
quic::QuicPacketHeader header;
|
||
|
header.destination_connection_id = connection_id_;
|
||
|
header.destination_connection_id_length = GetDestinationConnectionIdLength();
|
||
|
header.source_connection_id = connection_id_;
|
||
|
header.source_connection_id_length = GetSourceConnectionIdLength();
|
||
|
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 = num;
|
||
|
|
||
|
quic::QuicPingFrame ping;
|
||
|
return MakePacket(header, quic::QuicFrame(ping));
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket>
|
||
|
QuicTestPacketMaker::MakeDummyCHLOPacket(quic::QuicPacketNumber packet_num) {
|
||
|
encryption_level_ = quic::ENCRYPTION_NONE;
|
||
|
SetLongHeaderType(quic::INITIAL);
|
||
|
InitializeHeader(packet_num, /*include_version=*/true);
|
||
|
|
||
|
quic::CryptoHandshakeMessage message =
|
||
|
MockCryptoClientStream::GetDummyCHLOMessage();
|
||
|
const quic::QuicData& data =
|
||
|
message.GetSerialized(quic::Perspective::IS_CLIENT);
|
||
|
|
||
|
quic::QuicFrames frames;
|
||
|
quic::QuicStreamFrame frame(
|
||
|
quic::kCryptoStreamId, /*fin=*/false, /*offset=*/0,
|
||
|
quic::QuicStringPiece(data.data(), data.length()));
|
||
|
frames.push_back(quic::QuicFrame(frame));
|
||
|
DVLOG(1) << "Adding frame: " << frames.back();
|
||
|
quic::QuicPaddingFrame padding;
|
||
|
frames.push_back(quic::QuicFrame(padding));
|
||
|
DVLOG(1) << "Adding frame: " << frames.back();
|
||
|
|
||
|
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);
|
||
|
std::unique_ptr<quic::QuicPacket> packet(quic::test::BuildUnsizedDataPacket(
|
||
|
&framer, header_, frames, max_plaintext_size));
|
||
|
|
||
|
char buffer[quic::kDefaultMaxPacketSize];
|
||
|
size_t encrypted_size =
|
||
|
framer.EncryptPayload(quic::ENCRYPTION_NONE, header_.packet_number,
|
||
|
*packet, buffer, quic::kDefaultMaxPacketSize);
|
||
|
EXPECT_EQ(quic::kDefaultMaxPacketSize, encrypted_size);
|
||
|
quic::QuicReceivedPacket encrypted(buffer, encrypted_size,
|
||
|
quic::QuicTime::Zero(), false);
|
||
|
return encrypted.Clone();
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket>
|
||
|
QuicTestPacketMaker::MakeAckAndPingPacket(
|
||
|
quic::QuicPacketNumber num,
|
||
|
bool include_version,
|
||
|
quic::QuicPacketNumber largest_received,
|
||
|
quic::QuicPacketNumber smallest_received,
|
||
|
quic::QuicPacketNumber least_unacked) {
|
||
|
quic::QuicPacketHeader header;
|
||
|
header.destination_connection_id = connection_id_;
|
||
|
header.destination_connection_id_length = GetDestinationConnectionIdLength();
|
||
|
header.source_connection_id = connection_id_;
|
||
|
header.source_connection_id_length = GetSourceConnectionIdLength();
|
||
|
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 = num;
|
||
|
|
||
|
quic::QuicAckFrame ack(MakeAckFrame(largest_received));
|
||
|
ack.ack_delay_time = quic::QuicTime::Delta::Zero();
|
||
|
for (quic::QuicPacketNumber i = smallest_received; i <= largest_received;
|
||
|
++i) {
|
||
|
ack.received_packet_times.push_back(std::make_pair(i, clock_->Now()));
|
||
|
}
|
||
|
if (largest_received > 0) {
|
||
|
ack.packets.AddRange(1, largest_received + 1);
|
||
|
}
|
||
|
quic::QuicFrames frames;
|
||
|
frames.push_back(quic::QuicFrame(&ack));
|
||
|
DVLOG(1) << "Adding frame: " << frames.back();
|
||
|
|
||
|
quic::QuicStopWaitingFrame stop_waiting;
|
||
|
if (version_ == quic::QUIC_VERSION_35) {
|
||
|
stop_waiting.least_unacked = least_unacked;
|
||
|
frames.push_back(quic::QuicFrame(&stop_waiting));
|
||
|
DVLOG(1) << "Adding frame: " << frames.back();
|
||
|
}
|
||
|
|
||
|
frames.push_back(quic::QuicFrame(quic::QuicPingFrame()));
|
||
|
DVLOG(1) << "Adding frame: " << frames.back();
|
||
|
|
||
|
quic::QuicFramer framer(quic::test::SupportedVersions(quic::ParsedQuicVersion(
|
||
|
quic::PROTOCOL_QUIC_CRYPTO, version_)),
|
||
|
clock_->Now(), perspective_);
|
||
|
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,
|
||
|
quic::QuicTime::Zero(), false);
|
||
|
return encrypted.Clone();
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakeRstPacket(
|
||
|
quic::QuicPacketNumber num,
|
||
|
bool include_version,
|
||
|
quic::QuicStreamId stream_id,
|
||
|
quic::QuicRstStreamErrorCode error_code) {
|
||
|
return MakeRstPacket(num, include_version, stream_id, error_code, 0);
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakeRstPacket(
|
||
|
quic::QuicPacketNumber num,
|
||
|
bool include_version,
|
||
|
quic::QuicStreamId stream_id,
|
||
|
quic::QuicRstStreamErrorCode error_code,
|
||
|
size_t bytes_written) {
|
||
|
quic::QuicPacketHeader header;
|
||
|
header.destination_connection_id = connection_id_;
|
||
|
header.destination_connection_id_length = GetDestinationConnectionIdLength();
|
||
|
header.source_connection_id = connection_id_;
|
||
|
header.source_connection_id_length = GetSourceConnectionIdLength();
|
||
|
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 = num;
|
||
|
|
||
|
quic::QuicRstStreamFrame rst(1, stream_id, error_code, bytes_written);
|
||
|
DVLOG(1) << "Adding frame: " << quic::QuicFrame(&rst);
|
||
|
return MakePacket(header, quic::QuicFrame(&rst));
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket>
|
||
|
QuicTestPacketMaker::MakeRstAndRequestHeadersPacket(
|
||
|
quic::QuicPacketNumber 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::kHeadersStreamId, 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();
|
||
|
frames.push_back(quic::QuicFrame(headers_frame));
|
||
|
DVLOG(1) << "Adding frame: " << frames.back();
|
||
|
|
||
|
InitializeHeader(num, include_version);
|
||
|
return MakeMultipleFramesPacket(header_, frames);
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket>
|
||
|
QuicTestPacketMaker::MakeAckAndRstPacket(
|
||
|
quic::QuicPacketNumber num,
|
||
|
bool include_version,
|
||
|
quic::QuicStreamId stream_id,
|
||
|
quic::QuicRstStreamErrorCode error_code,
|
||
|
quic::QuicPacketNumber largest_received,
|
||
|
quic::QuicPacketNumber smallest_received,
|
||
|
quic::QuicPacketNumber least_unacked,
|
||
|
bool send_feedback) {
|
||
|
return MakeAckAndRstPacket(num, include_version, stream_id, error_code,
|
||
|
largest_received, smallest_received, least_unacked,
|
||
|
send_feedback, 0);
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket>
|
||
|
QuicTestPacketMaker::MakeAckAndRstPacket(
|
||
|
quic::QuicPacketNumber num,
|
||
|
bool include_version,
|
||
|
quic::QuicStreamId stream_id,
|
||
|
quic::QuicRstStreamErrorCode error_code,
|
||
|
quic::QuicPacketNumber largest_received,
|
||
|
quic::QuicPacketNumber smallest_received,
|
||
|
quic::QuicPacketNumber least_unacked,
|
||
|
bool send_feedback,
|
||
|
size_t bytes_written) {
|
||
|
quic::QuicPacketHeader header;
|
||
|
header.destination_connection_id = connection_id_;
|
||
|
header.destination_connection_id_length = GetDestinationConnectionIdLength();
|
||
|
header.source_connection_id = connection_id_;
|
||
|
header.source_connection_id_length = GetSourceConnectionIdLength();
|
||
|
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 = num;
|
||
|
|
||
|
quic::QuicAckFrame ack(MakeAckFrame(largest_received));
|
||
|
ack.ack_delay_time = quic::QuicTime::Delta::Zero();
|
||
|
for (quic::QuicPacketNumber i = smallest_received; i <= largest_received;
|
||
|
++i) {
|
||
|
ack.received_packet_times.push_back(std::make_pair(i, clock_->Now()));
|
||
|
}
|
||
|
if (largest_received > 0) {
|
||
|
ack.packets.AddRange(1, largest_received + 1);
|
||
|
}
|
||
|
quic::QuicFrames frames;
|
||
|
frames.push_back(quic::QuicFrame(&ack));
|
||
|
DVLOG(1) << "Adding frame: " << frames.back();
|
||
|
|
||
|
quic::QuicStopWaitingFrame stop_waiting;
|
||
|
if (version_ == quic::QUIC_VERSION_35) {
|
||
|
stop_waiting.least_unacked = least_unacked;
|
||
|
frames.push_back(quic::QuicFrame(&stop_waiting));
|
||
|
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[2];
|
||
|
DVLOG(1) << "Adding frame: " << frames.back();
|
||
|
|
||
|
quic::QuicFramer framer(quic::test::SupportedVersions(quic::ParsedQuicVersion(
|
||
|
quic::PROTOCOL_QUIC_CRYPTO, version_)),
|
||
|
clock_->Now(), perspective_);
|
||
|
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,
|
||
|
quic::QuicTime::Zero(), false);
|
||
|
return encrypted.Clone();
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket>
|
||
|
QuicTestPacketMaker::MakeAckAndConnectionClosePacket(
|
||
|
quic::QuicPacketNumber num,
|
||
|
bool include_version,
|
||
|
quic::QuicTime::Delta ack_delay_time,
|
||
|
quic::QuicPacketNumber largest_received,
|
||
|
quic::QuicPacketNumber smallest_received,
|
||
|
quic::QuicPacketNumber 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_length = GetDestinationConnectionIdLength();
|
||
|
header.source_connection_id = connection_id_;
|
||
|
header.source_connection_id_length = GetSourceConnectionIdLength();
|
||
|
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 = num;
|
||
|
|
||
|
quic::QuicAckFrame ack(MakeAckFrame(largest_received));
|
||
|
ack.ack_delay_time = ack_delay_time;
|
||
|
for (quic::QuicPacketNumber i = smallest_received; i <= largest_received;
|
||
|
++i) {
|
||
|
ack.received_packet_times.push_back(std::make_pair(i, clock_->Now()));
|
||
|
}
|
||
|
if (largest_received > 0) {
|
||
|
ack.packets.AddRange(1, largest_received + 1);
|
||
|
}
|
||
|
quic::QuicFrames frames;
|
||
|
frames.push_back(quic::QuicFrame(&ack));
|
||
|
DVLOG(1) << "Adding frame: " << frames.back();
|
||
|
|
||
|
quic::QuicStopWaitingFrame stop_waiting;
|
||
|
if (version_ == quic::QUIC_VERSION_35) {
|
||
|
stop_waiting.least_unacked = least_unacked;
|
||
|
frames.push_back(quic::QuicFrame(&stop_waiting));
|
||
|
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();
|
||
|
|
||
|
quic::QuicFramer framer(quic::test::SupportedVersions(quic::ParsedQuicVersion(
|
||
|
quic::PROTOCOL_QUIC_CRYPTO, version_)),
|
||
|
clock_->Now(), perspective_);
|
||
|
|
||
|
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();
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket>
|
||
|
QuicTestPacketMaker::MakeConnectionClosePacket(
|
||
|
quic::QuicPacketNumber 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_length = GetDestinationConnectionIdLength();
|
||
|
header.source_connection_id = connection_id_;
|
||
|
header.source_connection_id_length = GetSourceConnectionIdLength();
|
||
|
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 = num;
|
||
|
|
||
|
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(
|
||
|
quic::QuicPacketNumber num,
|
||
|
quic::QuicErrorCode error_code,
|
||
|
std::string reason_phrase) {
|
||
|
quic::QuicPacketHeader header;
|
||
|
header.destination_connection_id = connection_id_;
|
||
|
header.destination_connection_id_length = GetDestinationConnectionIdLength();
|
||
|
header.source_connection_id = connection_id_;
|
||
|
header.source_connection_id_length = GetSourceConnectionIdLength();
|
||
|
header.reset_flag = false;
|
||
|
header.version_flag = ShouldIncludeVersion(false);
|
||
|
header.long_packet_type = long_header_type_;
|
||
|
header.packet_number_length = GetPacketNumberLength();
|
||
|
header.packet_number = num;
|
||
|
|
||
|
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(
|
||
|
quic::QuicPacketNumber packet_number,
|
||
|
quic::QuicPacketNumber largest_received,
|
||
|
quic::QuicPacketNumber smallest_received,
|
||
|
quic::QuicPacketNumber 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(
|
||
|
quic::QuicPacketNumber packet_number,
|
||
|
quic::QuicPacketNumber first_received,
|
||
|
quic::QuicPacketNumber largest_received,
|
||
|
quic::QuicPacketNumber smallest_received,
|
||
|
quic::QuicPacketNumber 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(
|
||
|
quic::QuicPacketNumber packet_number,
|
||
|
quic::QuicPacketNumber largest_received,
|
||
|
quic::QuicPacketNumber smallest_received,
|
||
|
quic::QuicPacketNumber 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(
|
||
|
quic::QuicPacketNumber packet_number,
|
||
|
quic::QuicPacketNumber first_received,
|
||
|
quic::QuicPacketNumber largest_received,
|
||
|
quic::QuicPacketNumber smallest_received,
|
||
|
quic::QuicPacketNumber least_unacked,
|
||
|
bool send_feedback,
|
||
|
quic::QuicTime::Delta ack_delay_time) {
|
||
|
quic::QuicPacketHeader header;
|
||
|
header.destination_connection_id = connection_id_;
|
||
|
header.destination_connection_id_length = GetDestinationConnectionIdLength();
|
||
|
header.source_connection_id = connection_id_;
|
||
|
header.source_connection_id_length = GetSourceConnectionIdLength();
|
||
|
header.reset_flag = false;
|
||
|
header.version_flag = ShouldIncludeVersion(false);
|
||
|
header.long_packet_type = long_header_type_;
|
||
|
header.packet_number_length = GetPacketNumberLength();
|
||
|
header.packet_number = packet_number;
|
||
|
|
||
|
quic::QuicAckFrame ack(MakeAckFrame(largest_received));
|
||
|
ack.ack_delay_time = ack_delay_time;
|
||
|
for (quic::QuicPacketNumber i = smallest_received; i <= largest_received;
|
||
|
++i) {
|
||
|
ack.received_packet_times.push_back(std::make_pair(i, clock_->Now()));
|
||
|
}
|
||
|
if (largest_received > 0) {
|
||
|
DCHECK_GE(largest_received, first_received);
|
||
|
ack.packets.AddRange(first_received, 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();
|
||
|
|
||
|
quic::QuicStopWaitingFrame stop_waiting;
|
||
|
if (version_ == quic::QUIC_VERSION_35) {
|
||
|
stop_waiting.least_unacked = least_unacked;
|
||
|
frames.push_back(quic::QuicFrame(&stop_waiting));
|
||
|
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(
|
||
|
quic::QuicPacketNumber 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(
|
||
|
quic::QuicPacketNumber 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);
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket>
|
||
|
QuicTestPacketMaker::MakeAckAndDataPacket(
|
||
|
quic::QuicPacketNumber packet_number,
|
||
|
bool include_version,
|
||
|
quic::QuicStreamId stream_id,
|
||
|
quic::QuicPacketNumber largest_received,
|
||
|
quic::QuicPacketNumber smallest_received,
|
||
|
quic::QuicPacketNumber 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 (quic::QuicPacketNumber i = smallest_received; i <= largest_received;
|
||
|
++i) {
|
||
|
ack.received_packet_times.push_back(std::make_pair(i, clock_->Now()));
|
||
|
}
|
||
|
if (largest_received > 0) {
|
||
|
ack.packets.AddRange(1, largest_received + 1);
|
||
|
}
|
||
|
quic::QuicFrames frames;
|
||
|
frames.push_back(quic::QuicFrame(&ack));
|
||
|
DVLOG(1) << "Adding frame: " << frames.back();
|
||
|
|
||
|
quic::QuicStopWaitingFrame stop_waiting;
|
||
|
if (version_ == quic::QUIC_VERSION_35) {
|
||
|
stop_waiting.least_unacked = least_unacked;
|
||
|
frames.push_back(quic::QuicFrame(&stop_waiting));
|
||
|
DVLOG(1) << "Adding frame: " << frames.back();
|
||
|
}
|
||
|
|
||
|
frames.push_back(
|
||
|
quic::QuicFrame(quic::QuicStreamFrame(stream_id, fin, offset, data)));
|
||
|
|
||
|
return MakeMultipleFramesPacket(header_, frames);
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket>
|
||
|
QuicTestPacketMaker::MakeRequestHeadersAndMultipleDataFramesPacket(
|
||
|
quic::QuicPacketNumber 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::kHeadersStreamId, 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);
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket>
|
||
|
QuicTestPacketMaker::MakeRequestHeadersPacket(
|
||
|
quic::QuicPacketNumber 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(
|
||
|
quic::QuicPacketNumber 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(
|
||
|
quic::QuicPacketNumber 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::kHeadersStreamId, 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::kHeadersStreamId, false, 0,
|
||
|
quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
|
||
|
|
||
|
return MakePacket(header_, quic::QuicFrame(frame));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket>
|
||
|
QuicTestPacketMaker::MakeRequestHeadersAndRstPacket(
|
||
|
quic::QuicPacketNumber 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::kHeadersStreamId, 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();
|
||
|
|
||
|
InitializeHeader(packet_number, should_include_version);
|
||
|
return MakeMultipleFramesPacket(header_, frames);
|
||
|
}
|
||
|
|
||
|
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(
|
||
|
quic::QuicPacketNumber 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(
|
||
|
quic::QuicPacketNumber 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::kHeadersStreamId, 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::kHeadersStreamId, false, 0,
|
||
|
quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
|
||
|
return MakePacket(header_, quic::QuicFrame(frame));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket>
|
||
|
QuicTestPacketMaker::MakeForceHolDataPacket(
|
||
|
quic::QuicPacketNumber 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::kHeadersStreamId, 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(
|
||
|
quic::QuicPacketNumber 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::kHeadersStreamId, 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::kHeadersStreamId, false, 0,
|
||
|
quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
|
||
|
return MakePacket(header_, quic::QuicFrame(frame));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket>
|
||
|
QuicTestPacketMaker::MakeResponseHeadersPacket(
|
||
|
quic::QuicPacketNumber 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(
|
||
|
quic::QuicPacketNumber 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);
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket>
|
||
|
QuicTestPacketMaker::MakeMultipleFramesPacket(
|
||
|
const quic::QuicPacketHeader& header,
|
||
|
const quic::QuicFrames& frames) {
|
||
|
quic::QuicFramer framer(quic::test::SupportedVersions(quic::ParsedQuicVersion(
|
||
|
quic::PROTOCOL_QUIC_CRYPTO, version_)),
|
||
|
clock_->Now(), perspective_);
|
||
|
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();
|
||
|
}
|
||
|
|
||
|
void QuicTestPacketMaker::InitializeHeader(quic::QuicPacketNumber packet_number,
|
||
|
bool should_include_version) {
|
||
|
header_.destination_connection_id = connection_id_;
|
||
|
header_.destination_connection_id_length = GetDestinationConnectionIdLength();
|
||
|
header_.source_connection_id = connection_id_;
|
||
|
header_.source_connection_id_length = GetSourceConnectionIdLength();
|
||
|
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 = packet_number;
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket>
|
||
|
QuicTestPacketMaker::MakeInitialSettingsPacket(
|
||
|
quic::QuicPacketNumber packet_number,
|
||
|
quic::QuicStreamOffset* offset) {
|
||
|
std::string unused_data;
|
||
|
return MakeInitialSettingsPacketAndSaveData(packet_number, offset,
|
||
|
&unused_data);
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket>
|
||
|
QuicTestPacketMaker::MakeInitialSettingsPacketAndSaveData(
|
||
|
quic::QuicPacketNumber 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::kHeadersStreamId, 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::kHeadersStreamId, false, 0,
|
||
|
quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
|
||
|
return MakePacket(header_, quic::QuicFrame(quic_frame));
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<quic::QuicReceivedPacket>
|
||
|
QuicTestPacketMaker::MakePriorityPacket(quic::QuicPacketNumber 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::kHeadersStreamId, 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(
|
||
|
quic::QuicPacketNumber packet_number,
|
||
|
bool should_include_version,
|
||
|
quic::QuicPacketNumber largest_received,
|
||
|
quic::QuicPacketNumber smallest_received,
|
||
|
quic::QuicPacketNumber 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 (quic::QuicPacketNumber i = smallest_received; i <= largest_received;
|
||
|
++i) {
|
||
|
ack.received_packet_times.push_back(std::make_pair(i, clock_->Now()));
|
||
|
}
|
||
|
if (largest_received > 0) {
|
||
|
ack.packets.AddRange(1, largest_received + 1);
|
||
|
}
|
||
|
quic::QuicFrames frames;
|
||
|
frames.push_back(quic::QuicFrame(&ack));
|
||
|
DVLOG(1) << "Adding frame: " << frames.back();
|
||
|
|
||
|
quic::QuicStopWaitingFrame stop_waiting;
|
||
|
if (version_ == quic::QUIC_VERSION_35) {
|
||
|
stop_waiting.least_unacked = least_unacked;
|
||
|
frames.push_back(quic::QuicFrame(&stop_waiting));
|
||
|
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::kHeadersStreamId, 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);
|
||
|
}
|
||
|
|
||
|
void QuicTestPacketMaker::SetEncryptionLevel(quic::EncryptionLevel level) {
|
||
|
encryption_level_ = level;
|
||
|
}
|
||
|
|
||
|
void QuicTestPacketMaker::SetLongHeaderType(quic::QuicLongHeaderType type) {
|
||
|
long_header_type_ = 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) {
|
||
|
return quic::PACKET_4BYTE_PACKET_NUMBER;
|
||
|
}
|
||
|
return quic::PACKET_1BYTE_PACKET_NUMBER;
|
||
|
}
|
||
|
|
||
|
quic::QuicConnectionIdLength
|
||
|
QuicTestPacketMaker::GetDestinationConnectionIdLength() const {
|
||
|
if (perspective_ == quic::Perspective::IS_SERVER &&
|
||
|
version_ > quic::QUIC_VERSION_43) {
|
||
|
return quic::PACKET_0BYTE_CONNECTION_ID;
|
||
|
}
|
||
|
return quic::PACKET_8BYTE_CONNECTION_ID;
|
||
|
}
|
||
|
|
||
|
quic::QuicConnectionIdLength QuicTestPacketMaker::GetSourceConnectionIdLength()
|
||
|
const {
|
||
|
if (perspective_ == quic::Perspective::IS_SERVER &&
|
||
|
version_ > quic::QUIC_VERSION_43 &&
|
||
|
encryption_level_ < quic::ENCRYPTION_FORWARD_SECURE) {
|
||
|
return quic::PACKET_8BYTE_CONNECTION_ID;
|
||
|
}
|
||
|
return quic::PACKET_0BYTE_CONNECTION_ID;
|
||
|
}
|
||
|
|
||
|
} // namespace test
|
||
|
} // namespace net
|