// 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 #include #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "net/quic/mock_crypto_client_stream.h" #include "net/quic/quic_chromium_client_session.h" #include "net/quic/quic_http_utils.h" #include "net/third_party/quiche/src/quiche/quic/core/crypto/null_encrypter.h" #include "net/third_party/quiche/src/quiche/quic/core/http/http_constants.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_framer.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_stream.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h" #include "net/third_party/quiche/src/quiche/quic/test_tools/mock_random.h" #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h" namespace net::test { namespace { quic::QuicFrames CloneFrames(const quic::QuicFrames& frames) { quic::QuicFrames new_frames = frames; for (auto& frame : new_frames) { switch (frame.type) { // Frames smaller than a pointer are inlined, so don't need to be cloned. case quic::PADDING_FRAME: case quic::MTU_DISCOVERY_FRAME: case quic::PING_FRAME: case quic::MAX_STREAMS_FRAME: case quic::STOP_WAITING_FRAME: case quic::STREAMS_BLOCKED_FRAME: case quic::STREAM_FRAME: case quic::HANDSHAKE_DONE_FRAME: case quic::BLOCKED_FRAME: case quic::WINDOW_UPDATE_FRAME: case quic::STOP_SENDING_FRAME: case quic::PATH_CHALLENGE_FRAME: case quic::PATH_RESPONSE_FRAME: break; case quic::ACK_FRAME: frame.ack_frame = new quic::QuicAckFrame(*frame.ack_frame); break; case quic::RST_STREAM_FRAME: frame.rst_stream_frame = new quic::QuicRstStreamFrame(*frame.rst_stream_frame); break; case quic::CONNECTION_CLOSE_FRAME: frame.connection_close_frame = new quic::QuicConnectionCloseFrame(*frame.connection_close_frame); break; case quic::GOAWAY_FRAME: frame.goaway_frame = new quic::QuicGoAwayFrame(*frame.goaway_frame); break; case quic::NEW_CONNECTION_ID_FRAME: frame.new_connection_id_frame = new quic::QuicNewConnectionIdFrame(*frame.new_connection_id_frame); break; case quic::RETIRE_CONNECTION_ID_FRAME: frame.retire_connection_id_frame = new quic::QuicRetireConnectionIdFrame( *frame.retire_connection_id_frame); break; case quic::MESSAGE_FRAME: DCHECK(false) << "Message frame not supported"; // frame.message_frame = new // quic::QuicMessageFrame(*frame.message_frame); break; case quic::CRYPTO_FRAME: frame.crypto_frame = new quic::QuicCryptoFrame(*frame.crypto_frame); break; case quic::NEW_TOKEN_FRAME: frame.new_token_frame = new quic::QuicNewTokenFrame(*frame.new_token_frame); break; case quic::ACK_FREQUENCY_FRAME: frame.ack_frequency_frame = new quic::QuicAckFrequencyFrame(*frame.ack_frequency_frame); break; case quic::NUM_FRAME_TYPES: DCHECK(false) << "Cannot clone frame type: " << frame.type; } } return new_frames; } } // namespace QuicTestPacketMaker::QuicTestPacketMaker( quic::ParsedQuicVersion version, quic::QuicConnectionId connection_id, const quic::QuicClock* 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), qpack_encoder_(&decoder_stream_error_delegate_), perspective_(perspective), client_headers_include_h2_stream_dependency_( client_headers_include_h2_stream_dependency) { DCHECK(!(perspective_ == quic::Perspective::IS_SERVER && client_headers_include_h2_stream_dependency_)); qpack_encoder_.set_qpack_stream_sender_delegate( &encoder_stream_sender_delegate_); } QuicTestPacketMaker::~QuicTestPacketMaker() { for (auto& kv : saved_frames_) { quic::DeleteFrames(&(kv.second)); } } void QuicTestPacketMaker::set_hostname(const std::string& host) { host_.assign(host); } std::unique_ptr QuicTestPacketMaker::MakeConnectivityProbingPacket(uint64_t num, bool include_version) { InitializeHeader(num, include_version); if (!version_.HasIetfQuicFrames()) { AddQuicPingFrame(); } else if (perspective_ == quic::Perspective::IS_CLIENT) { AddQuicPathChallengeFrame(); } else { AddQuicPathResponseFrame(); } AddQuicPaddingFrame(); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakePingPacket( uint64_t num, bool include_version) { InitializeHeader(num, include_version); AddQuicPingFrame(); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeRetireConnectionIdPacket(uint64_t num, bool include_version, uint64_t sequence_number) { InitializeHeader(num, include_version); AddQuicRetireConnectionIdFrame(sequence_number); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeNewConnectionIdPacket( uint64_t num, bool include_version, const quic::QuicConnectionId& cid, uint64_t sequence_number, uint64_t retire_prior_to) { InitializeHeader(num, include_version); AddQuicNewConnectionIdFrame( cid, sequence_number, retire_prior_to, quic::QuicUtils::GenerateStatelessResetToken(cid)); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeAckAndNewConnectionIdPacket( uint64_t num, bool include_version, uint64_t largest_received, uint64_t smallest_received, const quic::QuicConnectionId& cid, uint64_t sequence_number, uint64_t retire_prior_to) { InitializeHeader(num, include_version); AddQuicAckFrame(largest_received, smallest_received); AddQuicNewConnectionIdFrame( cid, sequence_number, retire_prior_to, quic::QuicUtils::GenerateStatelessResetToken(cid)); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeDummyCHLOPacket(uint64_t packet_num) { SetEncryptionLevel(quic::ENCRYPTION_INITIAL); InitializeHeader(packet_num, /*include_version=*/true); quic::CryptoHandshakeMessage message = MockCryptoClientStream::GetDummyCHLOMessage(); const quic::QuicData& data = message.GetSerialized(); if (!QuicVersionUsesCryptoFrames(version_.transport_version)) { AddQuicStreamFrameWithOffset( quic::QuicUtils::GetCryptoStreamId(version_.transport_version), /*fin=*/false, /*offset=*/0, data.AsStringPiece()); } else { AddQuicCryptoFrame(quic::ENCRYPTION_INITIAL, 0, data.length()); data_producer_ = std::make_unique(); data_producer_->SaveCryptoData(quic::ENCRYPTION_INITIAL, 0, data.AsStringPiece()); } AddQuicPaddingFrame(); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeAckAndPingPacket(uint64_t num, bool include_version, uint64_t largest_received, uint64_t smallest_received) { InitializeHeader(num, include_version); AddQuicAckFrame(largest_received, smallest_received); AddQuicPingFrame(); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeAckAndRetireConnectionIdPacket( uint64_t num, bool include_version, uint64_t largest_received, uint64_t smallest_received, uint64_t sequence_number) { InitializeHeader(num, include_version); AddQuicAckFrame(largest_received, smallest_received); AddQuicRetireConnectionIdFrame(sequence_number); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeRetransmissionAndRetireConnectionIdPacket( uint64_t num, bool include_version, const std::vector& original_packet_numbers, uint64_t sequence_number) { InitializeHeader(num, include_version); for (auto it : original_packet_numbers) { for (auto frame : saved_frames_[quic::QuicPacketNumber(it)]) { frames_.push_back(frame); } } AddQuicRetireConnectionIdFrame(sequence_number); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeStreamsBlockedPacket( uint64_t num, bool include_version, quic::QuicStreamCount stream_count, bool unidirectional) { InitializeHeader(num, include_version); AddQuicStreamsBlockedFrame(1, stream_count, unidirectional); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeMaxStreamsPacket(uint64_t num, bool include_version, quic::QuicStreamCount stream_count, bool unidirectional) { InitializeHeader(num, include_version); AddQuicMaxStreamsFrame(1, stream_count, unidirectional); return BuildPacket(); } std::unique_ptr 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, /*include_stop_sending_if_v99=*/true); } std::unique_ptr QuicTestPacketMaker::MakeRstPacket( uint64_t num, bool include_version, quic::QuicStreamId stream_id, quic::QuicRstStreamErrorCode error_code, bool include_stop_sending_if_v99) { InitializeHeader(num, include_version); if (include_stop_sending_if_v99 && version_.HasIetfQuicFrames()) { AddQuicStopSendingFrame(stream_id, error_code); } if (!version_.HasIetfQuicFrames() || quic::QuicUtils::IsBidirectionalStreamId(stream_id, version_)) { AddQuicRstStreamFrame(stream_id, error_code); } return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeRstAndDataPacket( uint64_t num, bool include_version, quic::QuicStreamId rst_stream_id, quic::QuicRstStreamErrorCode rst_error_code, quic::QuicStreamId data_stream_id, absl::string_view data) { InitializeHeader(num, include_version); if (version_.HasIetfQuicFrames()) { AddQuicStopSendingFrame(rst_stream_id, rst_error_code); } AddQuicRstStreamFrame(rst_stream_id, rst_error_code); AddQuicStreamFrame(data_stream_id, /* fin = */ false, data); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeRetransmissionRstAndDataPacket( const std::vector& original_packet_numbers, uint64_t num, bool include_version, quic::QuicStreamId rst_stream_id, quic::QuicRstStreamErrorCode rst_error_code, quic::QuicStreamId data_stream_id, absl::string_view data) { DCHECK(save_packet_frames_); InitializeHeader(num, include_version); for (auto it : original_packet_numbers) { for (auto frame : saved_frames_[quic::QuicPacketNumber(it)]) { frames_.push_back(frame); } } if (version_.HasIetfQuicFrames()) { AddQuicStopSendingFrame(rst_stream_id, rst_error_code); } AddQuicRstStreamFrame(rst_stream_id, rst_error_code); AddQuicStreamFrame(data_stream_id, /* fin = */ false, data); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeDataAndRstPacket( uint64_t num, bool include_version, quic::QuicStreamId data_stream_id, absl::string_view data, quic::QuicStreamId rst_stream_id, quic::QuicRstStreamErrorCode rst_error_code) { InitializeHeader(num, include_version); AddQuicStreamFrame(data_stream_id, /* fin = */ false, data); if (version_.HasIetfQuicFrames()) { AddQuicStopSendingFrame(rst_stream_id, rst_error_code); } AddQuicRstStreamFrame(rst_stream_id, rst_error_code); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeDataRstAndAckPacket( uint64_t num, bool include_version, quic::QuicStreamId data_stream_id, absl::string_view data, quic::QuicStreamId rst_stream_id, quic::QuicRstStreamErrorCode rst_error_code, uint64_t largest_received, uint64_t smallest_received) { InitializeHeader(num, include_version); AddQuicAckFrame(largest_received, smallest_received); AddQuicStreamFrame(data_stream_id, /* fin = */ false, data); if (version_.HasIetfQuicFrames()) { AddQuicStopSendingFrame(rst_stream_id, rst_error_code); } AddQuicRstStreamFrame(rst_stream_id, rst_error_code); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeAckAndRstPacket( uint64_t num, bool include_version, quic::QuicStreamId stream_id, quic::QuicRstStreamErrorCode error_code, uint64_t largest_received, uint64_t smallest_received) { return MakeAckAndRstPacket(num, include_version, stream_id, error_code, largest_received, smallest_received, /*include_stop_sending_if_v99=*/true); } std::unique_ptr QuicTestPacketMaker::MakeAckAndRstPacket( uint64_t num, bool include_version, quic::QuicStreamId stream_id, quic::QuicRstStreamErrorCode error_code, uint64_t largest_received, uint64_t smallest_received, bool include_stop_sending_if_v99) { InitializeHeader(num, include_version); AddQuicAckFrame(largest_received, smallest_received); if (version_.HasIetfQuicFrames() && include_stop_sending_if_v99) { AddQuicStopSendingFrame(stream_id, error_code); } if (!version_.HasIetfQuicFrames() || quic::QuicUtils::IsBidirectionalStreamId(stream_id, version_)) { AddQuicRstStreamFrame(stream_id, error_code); } return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeRstAckAndConnectionClosePacket( uint64_t num, bool include_version, quic::QuicStreamId stream_id, quic::QuicRstStreamErrorCode error_code, uint64_t largest_received, uint64_t smallest_received, quic::QuicErrorCode quic_error, const std::string& quic_error_details) { InitializeHeader(num, include_version); AddQuicAckFrame(largest_received, smallest_received); if (version_.HasIetfQuicFrames()) { AddQuicStopSendingFrame(stream_id, error_code); } AddQuicRstStreamFrame(stream_id, error_code); AddQuicConnectionCloseFrame(quic_error, quic_error_details); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeRstAckAndDataPacket( uint64_t num, bool include_version, quic::QuicStreamId stream_id, quic::QuicRstStreamErrorCode error_code, uint64_t largest_received, uint64_t smallest_received, quic::QuicStreamId data_id, bool fin, absl::string_view data) { InitializeHeader(num, include_version); AddQuicRstStreamFrame(stream_id, error_code); AddQuicAckFrame(largest_received, smallest_received); AddQuicStreamFrame(data_id, fin, data); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeAckDataAndRst(uint64_t num, bool include_version, quic::QuicStreamId stream_id, quic::QuicRstStreamErrorCode error_code, uint64_t largest_received, uint64_t smallest_received, quic::QuicStreamId data_id, bool fin, absl::string_view data) { InitializeHeader(num, include_version); AddQuicAckFrame(largest_received, smallest_received); AddQuicStreamFrame(data_id, fin, data); AddQuicStopSendingFrame(stream_id, error_code); AddQuicRstStreamFrame(stream_id, error_code); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeAckRstAndDataPacket( uint64_t num, bool include_version, quic::QuicStreamId stream_id, quic::QuicRstStreamErrorCode error_code, uint64_t largest_received, uint64_t smallest_received, quic::QuicStreamId data_id, bool fin, absl::string_view data) { InitializeHeader(num, include_version); AddQuicAckFrame(largest_received, smallest_received); AddQuicRstStreamFrame(stream_id, error_code); AddQuicStreamFrame(data_id, fin, data); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeAckAndRetransmissionPacket( uint64_t packet_number, uint64_t first_received, uint64_t largest_received, uint64_t smallest_received, const std::vector& original_packet_numbers) { DCHECK(save_packet_frames_); InitializeHeader(packet_number, /*include_version=*/false); AddQuicAckFrame(first_received, largest_received, smallest_received); for (auto it : original_packet_numbers) { for (auto frame : saved_frames_[quic::QuicPacketNumber(it)]) { frames_.push_back(frame); } } return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeCombinedRetransmissionPacket( const std::vector& original_packet_numbers, uint64_t new_packet_number, bool should_include_version) { DCHECK(save_packet_frames_); InitializeHeader(new_packet_number, should_include_version); for (auto it : original_packet_numbers) { for (auto& frame : CloneFrames(saved_frames_[quic::QuicPacketNumber(it)])) { if (frame.type != quic::PADDING_FRAME) { frames_.push_back(frame); } } } return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeRstAndConnectionClosePacket( uint64_t num, bool include_version, quic::QuicStreamId stream_id, quic::QuicRstStreamErrorCode error_code, quic::QuicErrorCode quic_error, const std::string& quic_error_details) { InitializeHeader(num, include_version); if (version_.HasIetfQuicFrames()) { AddQuicStopSendingFrame(stream_id, error_code); } AddQuicRstStreamFrame(stream_id, error_code); AddQuicConnectionCloseFrame(quic_error, quic_error_details); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeDataRstAndConnectionClosePacket( uint64_t num, bool include_version, quic::QuicStreamId data_stream_id, absl::string_view data, quic::QuicStreamId rst_stream_id, quic::QuicRstStreamErrorCode error_code, quic::QuicErrorCode quic_error, const std::string& quic_error_details) { InitializeHeader(num, include_version); AddQuicStreamFrame(data_stream_id, /* fin = */ false, data); if (version_.HasIetfQuicFrames()) { AddQuicStopSendingFrame(rst_stream_id, error_code); } AddQuicRstStreamFrame(rst_stream_id, error_code); AddQuicConnectionCloseFrame(quic_error, quic_error_details); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeDataRstAckAndConnectionClosePacket( uint64_t num, bool include_version, quic::QuicStreamId data_stream_id, absl::string_view data, quic::QuicStreamId rst_stream_id, quic::QuicRstStreamErrorCode error_code, uint64_t largest_received, uint64_t smallest_received, quic::QuicErrorCode quic_error, const std::string& quic_error_details) { InitializeHeader(num, include_version); AddQuicAckFrame(largest_received, smallest_received); AddQuicStreamFrame(data_stream_id, /* fin = */ false, data); if (version_.HasIetfQuicFrames()) { AddQuicStopSendingFrame(rst_stream_id, error_code); } AddQuicRstStreamFrame(rst_stream_id, error_code); AddQuicConnectionCloseFrame(quic_error, quic_error_details); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeDataRstAckAndConnectionClosePacket( uint64_t num, bool include_version, quic::QuicStreamId data_stream_id, absl::string_view data, quic::QuicStreamId rst_stream_id, quic::QuicRstStreamErrorCode error_code, uint64_t largest_received, uint64_t smallest_received, quic::QuicErrorCode quic_error, const std::string& quic_error_details, uint64_t frame_type) { InitializeHeader(num, include_version); AddQuicStreamFrame(data_stream_id, /* fin = */ false, data); if (version_.HasIetfQuicFrames()) { AddQuicStopSendingFrame(rst_stream_id, error_code); } AddQuicRstStreamFrame(rst_stream_id, error_code); AddQuicAckFrame(largest_received, smallest_received); AddQuicConnectionCloseFrame(quic_error, quic_error_details, frame_type); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeStopSendingPacket( uint64_t num, bool include_version, quic::QuicStreamId stream_id, quic::QuicRstStreamErrorCode error_code) { DCHECK(version_.HasIetfQuicFrames()); InitializeHeader(num, include_version); AddQuicStopSendingFrame(stream_id, error_code); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeAckAndConnectionClosePacket( uint64_t num, bool include_version, uint64_t largest_received, uint64_t smallest_received, quic::QuicErrorCode quic_error, const std::string& quic_error_details, uint64_t frame_type) { InitializeHeader(num, include_version); AddQuicAckFrame(largest_received, smallest_received); AddQuicConnectionCloseFrame(quic_error, quic_error_details, frame_type); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeConnectionClosePacket( uint64_t num, bool include_version, quic::QuicErrorCode quic_error, const std::string& quic_error_details) { InitializeHeader(num, include_version); AddQuicConnectionCloseFrame(quic_error, quic_error_details); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeGoAwayPacket( uint64_t num, quic::QuicErrorCode error_code, std::string reason_phrase) { InitializeHeader(num, /*include_version=*/false); AddQuicGoAwayFrame(error_code, reason_phrase); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeAckPacket( uint64_t packet_number, uint64_t largest_received, uint64_t smallest_received) { return MakeAckPacket(packet_number, 1, largest_received, smallest_received); } std::unique_ptr QuicTestPacketMaker::MakeAckPacket( uint64_t packet_number, uint64_t first_received, uint64_t largest_received, uint64_t smallest_received) { InitializeHeader(packet_number, /*include_version=*/false); AddQuicAckFrame(first_received, largest_received, smallest_received); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeDataPacket( uint64_t packet_number, quic::QuicStreamId stream_id, bool should_include_version, bool fin, absl::string_view data) { InitializeHeader(packet_number, should_include_version); AddQuicStreamFrame(stream_id, fin, data); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeAckAndDataPacket(uint64_t packet_number, bool include_version, quic::QuicStreamId stream_id, uint64_t largest_received, uint64_t smallest_received, bool fin, absl::string_view data) { InitializeHeader(packet_number, include_version); AddQuicAckFrame(largest_received, smallest_received); AddQuicStreamFrame(stream_id, fin, data); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeAckRetransmissionAndDataPacket( uint64_t packet_number, bool include_version, const std::vector& original_packet_numbers, quic::QuicStreamId stream_id, uint64_t largest_received, uint64_t smallest_received, bool fin, absl::string_view data) { InitializeHeader(packet_number, include_version); AddQuicAckFrame(largest_received, smallest_received); for (auto it : original_packet_numbers) { for (auto frame : saved_frames_[quic::QuicPacketNumber(it)]) { frames_.push_back(frame); } } AddQuicStreamFrame(stream_id, fin, data); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeRequestHeadersAndMultipleDataFramesPacket( uint64_t packet_number, quic::QuicStreamId stream_id, bool should_include_version, bool fin, spdy::SpdyPriority priority, spdy::Http2HeaderBlock headers, quic::QuicStreamId parent_stream_id, size_t* spdy_headers_frame_length, const std::vector& data_writes) { InitializeHeader(packet_number, should_include_version); if (quic::VersionUsesHttp3(version_.transport_version)) { MaybeAddHttp3SettingsFrames(); if (priority != quic::QuicStream::kDefaultUrgency) { std::string priority_data = GenerateHttp3PriorityData(priority, stream_id); AddQuicStreamFrame(2, false, priority_data); } std::string data = QpackEncodeHeaders(stream_id, std::move(headers), spdy_headers_frame_length); for (const auto& data_write : data_writes) { data += data_write; } AddQuicStreamFrame(stream_id, fin, data); return BuildPacket(); } 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(); } AddQuicStreamFrame(GetHeadersStreamId(), false, absl::string_view(spdy_frame.data(), spdy_frame.size())); for (size_t i = 0; i < data_writes.size(); ++i) { bool is_fin = fin && (i == data_writes.size() - 1); AddQuicStreamFrame(stream_id, is_fin, absl::string_view(data_writes[i])); } return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeRequestHeadersPacket( uint64_t packet_number, quic::QuicStreamId stream_id, bool should_include_version, bool fin, spdy::SpdyPriority priority, spdy::Http2HeaderBlock headers, quic::QuicStreamId parent_stream_id, size_t* spdy_headers_frame_length) { InitializeHeader(packet_number, should_include_version); if (quic::VersionUsesHttp3(version_.transport_version)) { MaybeAddHttp3SettingsFrames(); if (priority != quic::QuicStream::kDefaultUrgency) { std::string priority_data = GenerateHttp3PriorityData(priority, stream_id); AddQuicStreamFrame(2, false, priority_data); } std::string data = QpackEncodeHeaders(stream_id, std::move(headers), spdy_headers_frame_length); AddQuicStreamFrame(stream_id, fin, data); return BuildPacket(); } 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(); AddQuicStreamFrame(GetHeadersStreamId(), false, absl::string_view(spdy_frame.data(), spdy_frame.size())); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeRetransmissionAndRequestHeadersPacket( const std::vector& original_packet_numbers, uint64_t packet_number, quic::QuicStreamId stream_id, bool should_include_version, bool fin, spdy::SpdyPriority priority, spdy::Http2HeaderBlock headers, quic::QuicStreamId parent_stream_id, size_t* spdy_headers_frame_length) { DCHECK(save_packet_frames_); InitializeHeader(packet_number, should_include_version); for (auto it : original_packet_numbers) { for (auto frame : saved_frames_[quic::QuicPacketNumber(it)]) { frames_.push_back(frame); } } if (quic::VersionUsesHttp3(version_.transport_version)) { MaybeAddHttp3SettingsFrames(); if (priority != quic::QuicStream::kDefaultUrgency) { std::string priority_data = GenerateHttp3PriorityData(priority, stream_id); AddQuicStreamFrame(2, false, priority_data); } std::string data = QpackEncodeHeaders(stream_id, std::move(headers), spdy_headers_frame_length); AddQuicStreamFrame(stream_id, fin, data); return BuildPacket(); } 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(); AddQuicStreamFrame(GetHeadersStreamId(), false, absl::string_view(spdy_frame.data(), spdy_frame.size())); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeRequestHeadersAndRstPacket( uint64_t packet_number, quic::QuicStreamId stream_id, bool should_include_version, bool fin, spdy::SpdyPriority priority, spdy::Http2HeaderBlock headers, quic::QuicStreamId parent_stream_id, size_t* spdy_headers_frame_length, quic::QuicRstStreamErrorCode error_code) { InitializeHeader(packet_number, should_include_version); if (quic::VersionUsesHttp3(version_.transport_version)) { MaybeAddHttp3SettingsFrames(); if (priority != quic::QuicStream::kDefaultUrgency) { std::string priority_data = GenerateHttp3PriorityData(priority, stream_id); AddQuicStreamFrame(2, false, priority_data); } std::string data = QpackEncodeHeaders(stream_id, std::move(headers), spdy_headers_frame_length); AddQuicStreamFrame(stream_id, fin, data); AddQuicStopSendingFrame(stream_id, error_code); AddQuicRstStreamFrame(stream_id, error_code); return BuildPacket(); } 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(); } AddQuicStreamFrame(GetHeadersStreamId(), false, absl::string_view(spdy_frame.data(), spdy_frame.size())); if (version_.HasIetfQuicFrames()) { AddQuicStopSendingFrame(stream_id, error_code); } AddQuicRstStreamFrame(stream_id, error_code); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakePushPromisePacket( uint64_t packet_number, quic::QuicStreamId stream_id, quic::QuicStreamId promised_stream_id, bool should_include_version, bool fin, spdy::Http2HeaderBlock headers, size_t* spdy_headers_frame_length) { InitializeHeader(packet_number, should_include_version); DCHECK(!quic::VersionUsesHttp3(version_.transport_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(); } AddQuicStreamFrame(GetHeadersStreamId(), false, absl::string_view(spdy_frame.data(), spdy_frame.size())); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeResponseHeadersPacket( uint64_t packet_number, quic::QuicStreamId stream_id, bool should_include_version, bool fin, spdy::Http2HeaderBlock headers, size_t* spdy_headers_frame_length) { InitializeHeader(packet_number, should_include_version); if (quic::VersionUsesHttp3(version_.transport_version)) { std::string data = QpackEncodeHeaders(stream_id, std::move(headers), spdy_headers_frame_length); AddQuicStreamFrame(stream_id, fin, data); return BuildPacket(); } 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(); } AddQuicStreamFrame(GetHeadersStreamId(), false, absl::string_view(spdy_frame.data(), spdy_frame.size())); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeInitialSettingsPacket(uint64_t packet_number) { InitializeHeader(packet_number, /*should_include_version*/ true); if (!quic::VersionUsesHttp3(version_.transport_version)) { spdy::SpdySettingsIR settings_frame; settings_frame.AddSetting(spdy::SETTINGS_MAX_HEADER_LIST_SIZE, kQuicMaxHeaderListSize); settings_frame.AddSetting(quic::SETTINGS_QPACK_BLOCKED_STREAMS, quic::kDefaultMaximumBlockedStreams); spdy::SpdySerializedFrame spdy_frame( spdy_request_framer_.SerializeFrame(settings_frame)); AddQuicStreamFrame(GetHeadersStreamId(), false, absl::string_view(spdy_frame.data(), spdy_frame.size())); return BuildPacket(); } MaybeAddHttp3SettingsFrames(); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakePriorityPacket(uint64_t packet_number, bool should_include_version, quic::QuicStreamId id, quic::QuicStreamId parent_stream_id, spdy::SpdyPriority priority) { InitializeHeader(packet_number, should_include_version); if (!client_headers_include_h2_stream_dependency_) { parent_stream_id = 0; } int weight = spdy::Spdy3PriorityToHttp2Weight(priority); bool exclusive = client_headers_include_h2_stream_dependency_; if (!VersionUsesHttp3(version_.transport_version)) { spdy::SpdyPriorityIR priority_frame(id, parent_stream_id, weight, exclusive); spdy::SpdySerializedFrame spdy_frame( spdy_request_framer_.SerializeFrame(priority_frame)); AddQuicStreamFrame(GetHeadersStreamId(), false, absl::string_view(spdy_frame.data(), spdy_frame.size())); return BuildPacket(); } if (priority != quic::QuicStream::kDefaultUrgency) { std::string priority_data = GenerateHttp3PriorityData(priority, id); AddQuicStreamFrame(2, false, priority_data); } return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeAckAndPriorityPacket( uint64_t packet_number, bool should_include_version, uint64_t largest_received, uint64_t smallest_received, quic::QuicStreamId id, quic::QuicStreamId parent_stream_id, spdy::SpdyPriority priority) { InitializeHeader(packet_number, should_include_version); AddQuicAckFrame(largest_received, smallest_received); if (!client_headers_include_h2_stream_dependency_) { parent_stream_id = 0; } int weight = spdy::Spdy3PriorityToHttp2Weight(priority); bool exclusive = client_headers_include_h2_stream_dependency_; if (!VersionUsesHttp3(version_.transport_version)) { spdy::SpdyPriorityIR priority_frame(id, parent_stream_id, weight, exclusive); spdy::SpdySerializedFrame spdy_frame( spdy_request_framer_.SerializeFrame(priority_frame)); AddQuicStreamFrame(GetHeadersStreamId(), false, absl::string_view(spdy_frame.data(), spdy_frame.size())); return BuildPacket(); } if (priority != quic::QuicStream::kDefaultUrgency) { std::string priority_data = GenerateHttp3PriorityData(priority, id); AddQuicStreamFrame(2, false, priority_data); } return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeAckAndPriorityUpdatePacket( uint64_t packet_number, bool should_include_version, uint64_t largest_received, uint64_t smallest_received, quic::QuicStreamId id, spdy::SpdyPriority priority) { InitializeHeader(packet_number, should_include_version); AddQuicAckFrame(largest_received, smallest_received); std::string priority_data = GenerateHttp3PriorityData(priority, id); AddQuicStreamFrame(2, false, priority_data); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeMultiplePriorityFramesPacket( uint64_t packet_number, bool should_include_version, const std::vector& priority_frames) { InitializeHeader(packet_number, should_include_version); const bool exclusive = client_headers_include_h2_stream_dependency_; std::string coalesced_data; for (const Http2StreamDependency& info : priority_frames) { spdy::SpdyPriorityIR priority_frame( info.stream_id, info.parent_stream_id, spdy::Spdy3PriorityToHttp2Weight(info.spdy_priority), exclusive); auto spdy_frame = spdy_request_framer_.SerializeFrame(priority_frame); coalesced_data += std::string(spdy_frame.data(), spdy_frame.size()); } AddQuicStreamFrame(quic::VersionUsesHttp3(version_.transport_version) ? GetFirstBidirectionalStreamId() : GetHeadersStreamId(), false, coalesced_data); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeAckAndMultiplePriorityFramesPacket( uint64_t packet_number, bool should_include_version, uint64_t largest_received, uint64_t smallest_received, const std::vector& priority_frames) { InitializeHeader(packet_number, should_include_version); AddQuicAckFrame(largest_received, smallest_received); const bool exclusive = client_headers_include_h2_stream_dependency_; std::string coalesced_data; for (const Http2StreamDependency& info : priority_frames) { spdy::SpdyPriorityIR priority_frame( info.stream_id, info.parent_stream_id, spdy::Spdy3PriorityToHttp2Weight(info.spdy_priority), exclusive); auto spdy_frame = spdy_request_framer_.SerializeFrame(priority_frame); coalesced_data += std::string(spdy_frame.data(), spdy_frame.size()); } AddQuicStreamFrame(quic::VersionUsesHttp3(version_.transport_version) ? GetFirstBidirectionalStreamId() : GetHeadersStreamId(), false, coalesced_data); return BuildPacket(); } std::unique_ptr QuicTestPacketMaker::MakeRetransmissionPacket(uint64_t original_packet_number, uint64_t new_packet_number, bool should_include_version) { DCHECK(save_packet_frames_); InitializeHeader(new_packet_number, should_include_version); return BuildPacketImpl( saved_frames_[quic::QuicPacketNumber(original_packet_number)], nullptr); } std::unique_ptr QuicTestPacketMaker::MakeStatelessResetPacket() { auto connection_id = quic::test::TestConnectionId(); return quic::QuicFramer::BuildIetfStatelessResetPacket( connection_id, quic::QuicFramer::GetMinStatelessResetPacketLength() + 1, quic::QuicUtils::GenerateStatelessResetToken(connection_id)); } void QuicTestPacketMaker::RemoveSavedStreamFrames( quic::QuicStreamId stream_id) { for (auto& kv : saved_frames_) { auto* it = kv.second.begin(); while (it != kv.second.end()) { if (it->type == quic::STREAM_FRAME && it->stream_frame.stream_id == stream_id) { it = kv.second.erase(it); } else { ++it; } } } } void QuicTestPacketMaker::SetEncryptionLevel(quic::EncryptionLevel level) { encryption_level_ = level; switch (level) { case quic::ENCRYPTION_INITIAL: 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: LOG(DFATAL) << quic::EncryptionLevelToString(level); long_header_type_ = quic::INVALID_PACKET_TYPE; } } spdy::Http2HeaderBlock QuicTestPacketMaker::GetRequestHeaders( const std::string& method, const std::string& scheme, const std::string& path) const { spdy::Http2HeaderBlock headers; headers[":method"] = method; headers[":authority"] = host_; headers[":scheme"] = scheme; headers[":path"] = path; return headers; } spdy::Http2HeaderBlock QuicTestPacketMaker::ConnectRequestHeaders( const std::string& host_port) const { spdy::Http2HeaderBlock headers; headers[":method"] = "CONNECT"; headers[":authority"] = host_port; return headers; } spdy::Http2HeaderBlock QuicTestPacketMaker::GetResponseHeaders( const std::string& status) const { spdy::Http2HeaderBlock headers; headers[":status"] = status; headers["content-type"] = "text/plain"; return headers; } spdy::Http2HeaderBlock QuicTestPacketMaker::GetResponseHeaders( const std::string& status, const std::string& alt_svc) const { spdy::Http2HeaderBlock headers; headers[":status"] = status; headers["alt-svc"] = alt_svc; headers["content-type"] = "text/plain"; return headers; } void QuicTestPacketMaker::Reset() { stream_offsets_.clear(); } std::string QuicTestPacketMaker::QpackEncodeHeaders( quic::QuicStreamId stream_id, spdy::Http2HeaderBlock headers, size_t* encoded_data_length) { DCHECK(quic::VersionUsesHttp3(version_.transport_version)); std::string data; std::string encoded_headers = qpack_encoder_.EncodeHeaderList(stream_id, headers, nullptr); // Generate HEADERS frame header. const std::string headers_frame_header = quic::HttpEncoder::SerializeHeadersFrameHeader(encoded_headers.size()); // Possible add a PUSH stream type. if (!quic::QuicUtils::IsBidirectionalStreamId(stream_id, version_) && stream_offsets_[stream_id] == 0) { // Push stream type header data += "\x01"; } // Add the HEADERS frame header. data += headers_frame_header; // Add the HEADERS frame payload. data += encoded_headers; // Compute the total data length. if (encoded_data_length) { *encoded_data_length = data.length(); } return data; } void QuicTestPacketMaker::InitializeHeader(uint64_t packet_number, bool should_include_version) { header_.destination_connection_id = DestinationConnectionId(); header_.destination_connection_id_included = HasDestinationConnectionId(); header_.source_connection_id = SourceConnectionId(); header_.source_connection_id_included = HasSourceConnectionId(); header_.reset_flag = false; header_.version_flag = ShouldIncludeVersion(should_include_version); if (quic::VersionHasIetfInvariantHeader(version_.transport_version)) { header_.form = header_.version_flag ? quic::IETF_QUIC_LONG_HEADER_PACKET : quic::IETF_QUIC_SHORT_HEADER_PACKET; } header_.long_packet_type = long_header_type_; header_.packet_number_length = GetPacketNumberLength(); header_.packet_number = quic::QuicPacketNumber(packet_number); if (quic::QuicVersionHasLongHeaderLengths(version_.transport_version) && header_.version_flag) { if (long_header_type_ == quic::INITIAL) { header_.retry_token_length_length = quiche::VARIABLE_LENGTH_INTEGER_LENGTH_1; } header_.length_length = quiche::VARIABLE_LENGTH_INTEGER_LENGTH_2; } } void QuicTestPacketMaker::AddQuicPaddingFrame() { quic::QuicPaddingFrame padding_frame; frames_.push_back(quic::QuicFrame(padding_frame)); DVLOG(1) << "Adding frame: " << frames_.back(); } void QuicTestPacketMaker::AddQuicPingFrame() { quic::QuicPingFrame ping_frame; frames_.push_back(quic::QuicFrame(ping_frame)); DVLOG(1) << "Adding frame: " << frames_.back(); } void QuicTestPacketMaker::AddQuicRetireConnectionIdFrame( uint64_t sequence_number) { auto* retire_cid_frame = new quic::QuicRetireConnectionIdFrame(); retire_cid_frame->sequence_number = sequence_number; frames_.push_back(quic::QuicFrame(retire_cid_frame)); DVLOG(1) << "Adding frame: " << frames_.back(); } void QuicTestPacketMaker::AddQuicNewConnectionIdFrame( const quic::QuicConnectionId& cid, uint64_t sequence_number, uint64_t retire_prior_to, quic::StatelessResetToken reset_token) { auto* new_cid_frame = new quic::QuicNewConnectionIdFrame(); new_cid_frame->connection_id = cid; new_cid_frame->sequence_number = sequence_number; new_cid_frame->retire_prior_to = retire_prior_to; new_cid_frame->stateless_reset_token = reset_token; frames_.push_back(quic::QuicFrame(new_cid_frame)); DVLOG(1) << "Adding frame: " << frames_.back(); } void QuicTestPacketMaker::AddQuicMaxStreamsFrame( quic::QuicControlFrameId control_frame_id, quic::QuicStreamCount stream_count, bool unidirectional) { quic::QuicMaxStreamsFrame max_streams_frame(control_frame_id, stream_count, unidirectional); frames_.push_back(quic::QuicFrame(max_streams_frame)); DVLOG(1) << "Adding frame: " << frames_.back(); } void QuicTestPacketMaker::AddQuicStreamsBlockedFrame( quic::QuicControlFrameId control_frame_id, quic::QuicStreamCount stream_count, bool unidirectional) { quic::QuicStreamsBlockedFrame streams_blocked_frame( control_frame_id, stream_count, unidirectional); frames_.push_back(quic::QuicFrame(streams_blocked_frame)); DVLOG(1) << "Adding frame: " << frames_.back(); } void QuicTestPacketMaker::AddQuicStreamFrame(quic::QuicStreamId stream_id, bool fin, absl::string_view data) { AddQuicStreamFrameWithOffset(stream_id, fin, stream_offsets_[stream_id], data); stream_offsets_[stream_id] += data.length(); } void QuicTestPacketMaker::AddQuicStreamFrameWithOffset( quic::QuicStreamId stream_id, bool fin, quic::QuicStreamOffset offset, absl::string_view data) { // Save the stream data so that callers can use temporary objects for data. saved_stream_data_.push_back(std::make_unique(data)); absl::string_view saved_data = *saved_stream_data_.back(); quic::QuicStreamFrame stream_frame(stream_id, fin, offset, saved_data); frames_.push_back(quic::QuicFrame(stream_frame)); DVLOG(1) << "Adding frame: " << frames_.back(); } void QuicTestPacketMaker::AddQuicAckFrame(uint64_t largest_received, uint64_t smallest_received) { AddQuicAckFrame(1, largest_received, smallest_received); } void QuicTestPacketMaker::AddQuicAckFrame(uint64_t first_received, uint64_t largest_received, uint64_t smallest_received) { auto* ack_frame = new quic::QuicAckFrame; ack_frame->largest_acked = quic::QuicPacketNumber(largest_received); ack_frame->ack_delay_time = quic::QuicTime::Delta::Zero(); for (uint64_t i = smallest_received; i <= largest_received; ++i) { ack_frame->received_packet_times.push_back( std::make_pair(quic::QuicPacketNumber(i), clock_->Now())); } if (largest_received > 0) { DCHECK_GE(largest_received, first_received); ack_frame->packets.AddRange(quic::QuicPacketNumber(first_received), quic::QuicPacketNumber(largest_received + 1)); } frames_.push_back(quic::QuicFrame(ack_frame)); DVLOG(1) << "Adding frame: " << frames_.back(); } void QuicTestPacketMaker::AddQuicRstStreamFrame( quic::QuicStreamId stream_id, quic::QuicRstStreamErrorCode error_code) { auto* rst_stream_frame = new quic::QuicRstStreamFrame( 1, stream_id, error_code, stream_offsets_[stream_id]); frames_.push_back(quic::QuicFrame(rst_stream_frame)); DVLOG(1) << "Adding frame: " << frames_.back(); } void QuicTestPacketMaker::AddQuicConnectionCloseFrame( quic::QuicErrorCode quic_error, const std::string& quic_error_details) { AddQuicConnectionCloseFrame(quic_error, quic_error_details, 0); } void QuicTestPacketMaker::AddQuicConnectionCloseFrame( quic::QuicErrorCode quic_error, const std::string& quic_error_details, uint64_t frame_type) { auto* close_frame = new quic::QuicConnectionCloseFrame( version_.transport_version, quic_error, quic::NO_IETF_QUIC_ERROR, quic_error_details, frame_type); frames_.push_back(quic::QuicFrame(close_frame)); DVLOG(1) << "Adding frame: " << frames_.back(); } void QuicTestPacketMaker::AddQuicGoAwayFrame(quic::QuicErrorCode error_code, std::string reason_phrase) { auto* goaway_frame = new quic::QuicGoAwayFrame(); goaway_frame->error_code = error_code; goaway_frame->last_good_stream_id = 0; goaway_frame->reason_phrase = reason_phrase; frames_.push_back(quic::QuicFrame(goaway_frame)); DVLOG(1) << "Adding frame: " << frames_.back(); } void QuicTestPacketMaker::AddQuicPathResponseFrame() { quic::test::MockRandom rand(0); quic::QuicPathFrameBuffer payload; rand.RandBytes(payload.data(), payload.size()); auto path_response_frame = quic::QuicPathResponseFrame(0, payload); frames_.push_back(quic::QuicFrame(path_response_frame)); DVLOG(1) << "Adding frame: " << frames_.back(); } void QuicTestPacketMaker::AddQuicPathChallengeFrame() { quic::test::MockRandom rand(0); quic::QuicPathFrameBuffer payload; rand.RandBytes(payload.data(), payload.size()); auto path_challenge_frame = quic::QuicPathChallengeFrame(0, payload); frames_.push_back(quic::QuicFrame(path_challenge_frame)); DVLOG(1) << "Adding frame: " << frames_.back(); } void QuicTestPacketMaker::AddQuicStopSendingFrame( quic::QuicStreamId stream_id, quic::QuicRstStreamErrorCode error_code) { auto stop_sending_frame = quic::QuicStopSendingFrame(1, stream_id, error_code); frames_.push_back(quic::QuicFrame(stop_sending_frame)); DVLOG(1) << "Adding frame: " << frames_.back(); } void QuicTestPacketMaker::AddQuicCryptoFrame( quic::EncryptionLevel level, quic::QuicStreamOffset offset, quic::QuicPacketLength data_length) { auto* crypto_frame = new quic::QuicCryptoFrame(level, offset, data_length); frames_.push_back(quic::QuicFrame(crypto_frame)); DVLOG(1) << "Adding frame: " << frames_.back(); } std::unique_ptr QuicTestPacketMaker::BuildPacket() { auto packet = BuildPacketImpl(frames_, data_producer_.get()); DeleteFrames(&frames_); data_producer_.reset(); return packet; } std::unique_ptr QuicTestPacketMaker::BuildPacketImpl( const quic::QuicFrames& frames, quic::QuicStreamFrameDataProducer* data_producer) { quic::QuicFramer framer(quic::test::SupportedVersions(version_), clock_->Now(), perspective_, quic::kQuicDefaultConnectionIdLength); if (encryption_level_ == quic::ENCRYPTION_INITIAL) { framer.SetInitialObfuscators(perspective_ == quic::Perspective::IS_CLIENT ? header_.destination_connection_id : header_.source_connection_id); } else { framer.SetEncrypter(encryption_level_, std::make_unique(perspective_)); } if (data_producer != nullptr) { framer.set_data_producer(data_producer); } quic::QuicFrames frames_copy = CloneFrames(frames); size_t max_plaintext_size = framer.GetMaxPlaintextSize(quic::kDefaultMaxPacketSize); if (version_.HasHeaderProtection()) { size_t packet_size = quic::GetPacketHeaderSize(version_.transport_version, header_); size_t frames_size = 0; for (size_t i = 0; i < frames.size(); ++i) { bool first_frame = i == 0; bool last_frame = i == frames.size() - 1; const size_t frame_size = framer.GetSerializedFrameLength( frames[i], max_plaintext_size - packet_size, first_frame, last_frame, header_.packet_number_length); packet_size += frame_size; frames_size += frame_size; } const size_t min_plaintext_packet_size = quic::QuicPacketCreator::MinPlaintextPacketSize(version_); if (frames_size < min_plaintext_packet_size) { const size_t expansion_on_new_frame = frames.empty() ? 0 : quic::QuicPacketCreator::ExpansionOnNewFrameWithLastFrame( frames.back(), version_.transport_version); const size_t padding_length = std::max(1 + expansion_on_new_frame, min_plaintext_packet_size - frames_size) - expansion_on_new_frame; CHECK_LE(padding_length + packet_size + expansion_on_new_frame, max_plaintext_size); frames_copy.push_back( quic::QuicFrame(quic::QuicPaddingFrame(padding_length))); } } std::unique_ptr packet(quic::test::BuildUnsizedDataPacket( &framer, header_, frames_copy, max_plaintext_size)); char buffer[quic::kMaxOutgoingPacketSize]; size_t encrypted_size = framer.EncryptPayload(encryption_level_, header_.packet_number, *packet, buffer, quic::kMaxOutgoingPacketSize); EXPECT_NE(0u, encrypted_size); quic::QuicReceivedPacket encrypted(buffer, encrypted_size, clock_->Now(), false); if (save_packet_frames_) { saved_frames_[header_.packet_number] = frames_copy; } else { saved_stream_data_.clear(); DeleteFrames(&frames_copy); } return encrypted.Clone(); } spdy::SpdySerializedFrame QuicTestPacketMaker::MakeSpdyHeadersFrame( quic::QuicStreamId stream_id, bool fin, spdy::SpdyPriority priority, spdy::Http2HeaderBlock 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); } bool QuicTestPacketMaker::ShouldIncludeVersion(bool include_version) const { if (version_.HasIetfInvariantHeader()) { return encryption_level_ < quic::ENCRYPTION_FORWARD_SECURE; } return include_version; } quic::QuicPacketNumberLength QuicTestPacketMaker::GetPacketNumberLength() const { if (version_.HasIetfInvariantHeader() && encryption_level_ < quic::ENCRYPTION_FORWARD_SECURE && !version_.SendsVariableLengthPacketNumberInLongHeader()) { return quic::PACKET_4BYTE_PACKET_NUMBER; } return quic::PACKET_1BYTE_PACKET_NUMBER; } quic::QuicConnectionId QuicTestPacketMaker::DestinationConnectionId() const { if (perspective_ == quic::Perspective::IS_SERVER) { return quic::EmptyQuicConnectionId(); } return connection_id_; } quic::QuicConnectionId QuicTestPacketMaker::SourceConnectionId() const { if (perspective_ == quic::Perspective::IS_CLIENT) { return quic::EmptyQuicConnectionId(); } return connection_id_; } quic::QuicConnectionIdIncluded QuicTestPacketMaker::HasDestinationConnectionId() const { if (!version_.SupportsClientConnectionIds() && perspective_ == quic::Perspective::IS_SERVER) { return quic::CONNECTION_ID_ABSENT; } return quic::CONNECTION_ID_PRESENT; } quic::QuicConnectionIdIncluded QuicTestPacketMaker::HasSourceConnectionId() const { if (version_.SupportsClientConnectionIds() || (perspective_ == quic::Perspective::IS_SERVER && encryption_level_ < quic::ENCRYPTION_FORWARD_SECURE)) { return quic::CONNECTION_ID_PRESENT; } return quic::CONNECTION_ID_ABSENT; } quic::QuicStreamId QuicTestPacketMaker::GetFirstBidirectionalStreamId() const { return quic::QuicUtils::GetFirstBidirectionalStreamId( version_.transport_version, perspective_); } quic::QuicStreamId QuicTestPacketMaker::GetHeadersStreamId() const { return quic::QuicUtils::GetHeadersStreamId(version_.transport_version); } std::string QuicTestPacketMaker::GenerateHttp3SettingsData() { quic::SettingsFrame settings; settings.values[quic::SETTINGS_MAX_FIELD_SECTION_SIZE] = kQuicMaxHeaderListSize; settings.values[quic::SETTINGS_QPACK_MAX_TABLE_CAPACITY] = quic::kDefaultQpackMaxDynamicTableCapacity; settings.values[quic::SETTINGS_QPACK_BLOCKED_STREAMS] = quic::kDefaultMaximumBlockedStreams; // Greased setting. settings.values[0x40] = 20; return quic::HttpEncoder::SerializeSettingsFrame(settings); } std::string QuicTestPacketMaker::GenerateHttp3PriorityData( spdy::SpdyPriority priority, quic::QuicStreamId stream_id) { quic::PriorityUpdateFrame priority_update; priority_update.prioritized_element_type = quic::REQUEST_STREAM; priority_update.prioritized_element_id = stream_id; priority_update.priority_field_value = base::StrCat({"u=", base::NumberToString(priority)}); return quic::HttpEncoder::SerializePriorityUpdateFrame(priority_update); } std::string QuicTestPacketMaker::GenerateHttp3GreaseData() { return quic::HttpEncoder::SerializeGreasingFrame(); } void QuicTestPacketMaker::MaybeAddHttp3SettingsFrames() { DCHECK(quic::VersionUsesHttp3(version_.transport_version)); quic::QuicStreamId stream_id = quic::QuicUtils::GetFirstUnidirectionalStreamId( version_.transport_version, perspective_); if (stream_offsets_[stream_id] != 0) return; // A stream frame containing stream type will be written on the control // stream first. std::string type(1, 0x00); std::string settings_data = GenerateHttp3SettingsData(); std::string grease_data = GenerateHttp3GreaseData(); // The type and the SETTINGS frame may be sent in multiple QUIC STREAM // frames. std::string data = type + settings_data + grease_data; AddQuicStreamFrame(stream_id, false, data); } } // namespace net::test