relnote: On server side, do not process the first initial QUIC packet received from a client if the UDP datagram is < 1200 bytes. Instead, send a connection close with PROTOCOL_VIOLATION if the version is supported. Protected by quic_reloadable_flag_quic_donot_process_small_initial_packets. PiperOrigin-RevId: 270157435 Change-Id: Id0faa750300b2e75c7e87cc05dd8635c580f01ba
diff --git a/quic/core/http/quic_spdy_client_session_test.cc b/quic/core/http/quic_spdy_client_session_test.cc index 3e951b3..306f6f5 100644 --- a/quic/core/http/quic_spdy_client_session_test.cc +++ b/quic/core/http/quic_spdy_client_session_test.cc
@@ -517,7 +517,7 @@ QuicConnectionId source_connection_id = connection_id; std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket( destination_connection_id, source_connection_id, false, false, 100, - "data", CONNECTION_ID_ABSENT, CONNECTION_ID_ABSENT, + "data", true, CONNECTION_ID_ABSENT, CONNECTION_ID_ABSENT, PACKET_4BYTE_PACKET_NUMBER, &versions, Perspective::IS_SERVER)); std::unique_ptr<QuicReceivedPacket> received( ConstructReceivedPacket(*packet, QuicTime::Zero()));
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc index beb70ca..3187c78 100644 --- a/quic/core/quic_dispatcher.cc +++ b/quic/core/quic_dispatcher.cc
@@ -32,6 +32,9 @@ namespace { +// Minimal INITIAL packet length sent by clients is 1200. +const QuicPacketLength kMinClientInitialPacketLength = 1200; + // An alarm that informs the QuicDispatcher to delete old sessions. class DeleteSessionsAlarm : public QuicAlarm::Delegate { public: @@ -142,11 +145,35 @@ framer_.set_data_producer(nullptr); } + // Serializes a packet containing CONNECTION_CLOSE frame and send it (without + // adding connection to the time wait). + void StatelesslyCloseConnection(const QuicSocketAddress& self_address, + const QuicSocketAddress& peer_address, + QuicErrorCode error_code, + const std::string& error_details) { + SerializeConnectionClosePacket(error_code, error_details); + + for (const auto& packet : *collector_.packets()) { + time_wait_list_manager_->SendPacket(self_address, peer_address, *packet); + } + } + // Generates a packet containing a CONNECTION_CLOSE frame specifying // |error_code| and |error_details| and add the connection to time wait. void CloseConnection(QuicErrorCode error_code, const std::string& error_details, bool ietf_quic) { + SerializeConnectionClosePacket(error_code, error_details); + + time_wait_list_manager_->AddConnectionIdToTimeWait( + server_connection_id_, ietf_quic, + QuicTimeWaitListManager::SEND_TERMINATION_PACKETS, + quic::ENCRYPTION_INITIAL, collector_.packets()); + } + + private: + void SerializeConnectionClosePacket(QuicErrorCode error_code, + const std::string& error_details) { QuicConnectionCloseFrame* frame = new QuicConnectionCloseFrame( framer_.transport_version(), error_code, error_details, /*transport_close_frame_type=*/0); @@ -158,13 +185,8 @@ } creator_.FlushCurrentPacket(); DCHECK_EQ(1u, collector_.packets()->size()); - time_wait_list_manager_->AddConnectionIdToTimeWait( - server_connection_id_, ietf_quic, - QuicTimeWaitListManager::SEND_TERMINATION_PACKETS, - quic::ENCRYPTION_INITIAL, collector_.packets()); } - private: QuicConnectionId server_connection_id_; QuicFramer framer_; // Set as the visitor of |creator_| to collect any generated packets. @@ -256,9 +278,9 @@ QuicStringPiece retry_token; error = QuicFramer::ParsePublicHeaderDispatcher( packet, expected_server_connection_id_length_, &packet_info.form, - &packet_info.version_flag, &packet_info.use_length_prefix, - &packet_info.version_label, &packet_info.version, - &packet_info.destination_connection_id, + &packet_info.long_packet_type, &packet_info.version_flag, + &packet_info.use_length_prefix, &packet_info.version_label, + &packet_info.version, &packet_info.destination_connection_id, &packet_info.source_connection_id, &retry_token_present, &retry_token, &detailed_error); } @@ -447,6 +469,24 @@ } return true; } + + if (GetQuicReloadableFlag(quic_use_parse_public_header) && + GetQuicReloadableFlag(quic_donot_process_small_initial_packets) && + crypto_config()->validate_chlo_size() && + packet_info.form == IETF_QUIC_LONG_HEADER_PACKET && + packet_info.long_packet_type == INITIAL && + packet_info.packet.length() < kMinClientInitialPacketLength) { + QUIC_RELOADABLE_FLAG_COUNT(quic_donot_process_small_initial_packets); + StatelessConnectionTerminator terminator( + packet_info.destination_connection_id, packet_info.version, + helper_.get(), time_wait_list_manager_.get()); + QUIC_DVLOG(1) << "Initial packet too small: " + << packet_info.packet.length(); + terminator.StatelesslyCloseConnection( + packet_info.self_address, packet_info.peer_address, + IETF_QUIC_PROTOCOL_VIOLATION, "Initial packet too small"); + return true; + } } return false;
diff --git a/quic/core/quic_dispatcher_test.cc b/quic/core/quic_dispatcher_test.cc index 34408e0..f2114c2 100644 --- a/quic/core/quic_dispatcher_test.cc +++ b/quic/core/quic_dispatcher_test.cc
@@ -262,7 +262,7 @@ QuicPacketNumberLength packet_number_length, uint64_t packet_number) { ProcessPacket(peer_address, server_connection_id, has_version_flag, - CurrentSupportedVersions().front(), data, + CurrentSupportedVersions().front(), data, true, server_connection_id_included, packet_number_length, packet_number); } @@ -273,11 +273,12 @@ bool has_version_flag, ParsedQuicVersion version, const std::string& data, + bool full_padding, QuicConnectionIdIncluded server_connection_id_included, QuicPacketNumberLength packet_number_length, uint64_t packet_number) { ProcessPacket(peer_address, server_connection_id, EmptyQuicConnectionId(), - has_version_flag, version, data, + has_version_flag, version, data, full_padding, server_connection_id_included, CONNECTION_ID_ABSENT, packet_number_length, packet_number); } @@ -289,6 +290,7 @@ bool has_version_flag, ParsedQuicVersion version, const std::string& data, + bool full_padding, QuicConnectionIdIncluded server_connection_id_included, QuicConnectionIdIncluded client_connection_id_included, QuicPacketNumberLength packet_number_length, @@ -296,7 +298,7 @@ ParsedQuicVersionVector versions(SupportedVersions(version)); std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket( server_connection_id, client_connection_id, has_version_flag, false, - packet_number, data, server_connection_id_included, + packet_number, data, full_padding, server_connection_id_included, client_connection_id_included, packet_number_length, &versions)); std::unique_ptr<QuicReceivedPacket> received_packet( ConstructReceivedPacket(*packet, mock_helper_.GetClock()->Now())); @@ -383,7 +385,7 @@ ShouldCreateOrBufferPacketForConnection( ReceivedPacketInfoConnectionIdEquals(connection_id))); ProcessPacket(client_address, connection_id, true, version, SerializeCHLO(), - CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1); + true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1); } void VerifyVersionNotSupported(ParsedQuicVersion version) { @@ -393,7 +395,7 @@ QuicStringPiece("hq"), _)) .Times(0); ProcessPacket(client_address, connection_id, true, version, SerializeCHLO(), - CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1); + true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1); } MockQuicConnectionHelper mock_helper_; @@ -439,7 +441,8 @@ client_address, TestConnectionId(1), true, ParsedQuicVersion(PROTOCOL_TLS1_3, CurrentSupportedVersions().front().transport_version), - SerializeCHLO(), CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1); + SerializeCHLO(), true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, + 1); } TEST_F(QuicDispatcherTest, ProcessPackets) { @@ -514,14 +517,15 @@ client_address, TestConnectionId(1), true, ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, CurrentSupportedVersions().front().transport_version), - SerializeCHLO(), CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1); + SerializeCHLO(), true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, + 1); // Packet number 256 with packet number length 1 would be considered as 0 in // dispatcher. ProcessPacket( client_address, TestConnectionId(1), false, ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, CurrentSupportedVersions().front().transport_version), - "", CONNECTION_ID_PRESENT, PACKET_1BYTE_PACKET_NUMBER, 256); + "", true, CONNECTION_ID_PRESENT, PACKET_1BYTE_PACKET_NUMBER, 256); } TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) { @@ -539,7 +543,7 @@ std::string chlo = SerializeCHLO() + std::string(1200, 'a'); DCHECK_LE(1200u, chlo.length()); ProcessPacket(client_address, TestConnectionId(1), true, - QuicVersionReservedForNegotiation(), chlo, + QuicVersionReservedForNegotiation(), chlo, true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1); } @@ -558,7 +562,7 @@ std::string chlo = SerializeCHLO() + std::string(1200, 'a'); DCHECK_LE(1200u, chlo.length()); ProcessPacket(client_address, TestConnectionId(1), TestConnectionId(2), true, - QuicVersionReservedForNegotiation(), chlo, + QuicVersionReservedForNegotiation(), chlo, true, CONNECTION_ID_PRESENT, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1); } @@ -578,7 +582,7 @@ std::string truncated_chlo = chlo.substr(0, 1100); DCHECK_EQ(1100u, truncated_chlo.length()); ProcessPacket(client_address, TestConnectionId(1), true, - QuicVersionReservedForNegotiation(), truncated_chlo, + QuicVersionReservedForNegotiation(), truncated_chlo, false, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1); } @@ -602,7 +606,7 @@ std::string truncated_chlo = chlo.substr(0, 1100); DCHECK_EQ(1100u, truncated_chlo.length()); ProcessPacket(client_address, TestConnectionId(1), true, - QuicVersionReservedForNegotiation(), truncated_chlo, + QuicVersionReservedForNegotiation(), truncated_chlo, true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1); } @@ -1327,6 +1331,68 @@ sizeof(connection_id_bytes)); } +TEST_F(QuicDispatcherTest, DoNotProcessSmallPacket) { + SetQuicReloadableFlag(quic_donot_process_small_initial_packets, true); + SetQuicReloadableFlag(quic_use_parse_public_header, true); + CreateTimeWaitListManager(); + QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); + + EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0); + EXPECT_CALL(*time_wait_list_manager_, SendPacket(_, _, _)).Times(1); + ProcessPacket(client_address, TestConnectionId(1), true, + CurrentSupportedVersions()[0], SerializeCHLO(), false, + CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1); +} + +TEST_F(QuicDispatcherTest, ProcessSmallCoalescedPacket) { + SetQuicReloadableFlag(quic_enable_version_99, true); + CreateTimeWaitListManager(); + QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); + + EXPECT_CALL(*time_wait_list_manager_, SendPacket(_, _, _)).Times(0); + + // clang-format off + char coalesced_packet[1200] = { + // first coalesced packet + // public flags (long header with packet type INITIAL and + // 4-byte packet number) + 0xC3, + // version + 'Q', '0', '9', '9', + // destination connection ID length + 0x08, + // destination connection ID + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // source connection ID length + 0x00, + // long header packet length + 0x05, + // packet number + 0x12, 0x34, 0x56, 0x78, + // Padding + 0x00, + // second coalesced packet + // public flags (long header with packet type ZERO_RTT_PROTECTED and + // 4-byte packet number) + 0xC3, + // version + 'Q', '0', '9', '9', + // destination connection ID length + 0x08, + // destination connection ID + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // source connection ID length + 0x00, + // long header packet length + 0x1E, + // packet number + 0x12, 0x34, 0x56, 0x79, + }; + // clang-format on + QuicReceivedPacket packet(coalesced_packet, 1200, QuicTime::Zero()); + dispatcher_->ProcessPacket(server_address_, client_address, packet); +} + // Verify the stopgap test: Packets with truncated connection IDs should be // dropped. class QuicDispatcherTestStrayPacketConnectionId : public QuicDispatcherTest {}; @@ -2118,7 +2184,7 @@ }))); } ProcessPacket(client_addr_, TestConnectionId(conn_id), true, version, - SerializeFullCHLO(), CONNECTION_ID_PRESENT, + SerializeFullCHLO(), true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1); }
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc index e33dc00..84dd00a 100644 --- a/quic/core/quic_framer.cc +++ b/quic/core/quic_framer.cc
@@ -6303,6 +6303,7 @@ const QuicEncryptedPacket& packet, uint8_t expected_destination_connection_id_length, PacketHeaderFormat* format, + QuicLongHeaderType* long_packet_type, bool* version_present, bool* has_length_prefix, QuicVersionLabel* version_label, @@ -6321,12 +6322,11 @@ const bool ietf_format = QuicUtils::IsIetfPacketHeader(first_byte); uint8_t unused_first_byte; QuicVariableLengthIntegerLength retry_token_length_length; - QuicLongHeaderType unused_log_packet_type; - const QuicErrorCode error_code = ParsePublicHeader( + QuicErrorCode error_code = ParsePublicHeader( &reader, expected_destination_connection_id_length, ietf_format, &unused_first_byte, format, version_present, has_length_prefix, version_label, parsed_version, destination_connection_id, - source_connection_id, &unused_log_packet_type, &retry_token_length_length, + source_connection_id, long_packet_type, &retry_token_length_length, retry_token, detailed_error); *retry_token_present = retry_token_length_length != VARIABLE_LENGTH_INTEGER_LENGTH_0;
diff --git a/quic/core/quic_framer.h b/quic/core/quic_framer.h index ffeeab1..3d4c063 100644 --- a/quic/core/quic_framer.h +++ b/quic/core/quic_framer.h
@@ -422,6 +422,7 @@ const QuicEncryptedPacket& packet, uint8_t expected_destination_connection_id_length, PacketHeaderFormat* format, + QuicLongHeaderType* long_packet_type, bool* version_present, bool* has_length_prefix, QuicVersionLabel* version_label,
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc index 9211d68..deb66d3 100644 --- a/quic/core/quic_framer_test.cc +++ b/quic/core/quic_framer_test.cc
@@ -1015,6 +1015,7 @@ CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER); PacketHeaderFormat format; + QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE; bool version_flag; QuicConnectionId destination_connection_id, source_connection_id; QuicVersionLabel version_label; @@ -1030,8 +1031,8 @@ QuicStringPiece retry_token; ParsedQuicVersion parsed_version = UnsupportedQuicVersion(); error_code = QuicFramer::ParsePublicHeaderDispatcher( - *encrypted, kQuicDefaultConnectionIdLength, &format, &version_flag, - &use_length_prefix, &version_label, &parsed_version, + *encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type, + &version_flag, &use_length_prefix, &version_label, &parsed_version, &destination_connection_id, &source_connection_id, &retry_token_present, &retry_token, &detailed_error); EXPECT_FALSE(retry_token_present); @@ -1086,6 +1087,7 @@ CheckFramingBoundaries(packet46, QUIC_INVALID_PACKET_HEADER); PacketHeaderFormat format; + QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE; bool version_flag; QuicConnectionId destination_connection_id, source_connection_id; QuicVersionLabel version_label; @@ -1101,8 +1103,8 @@ QuicStringPiece retry_token; ParsedQuicVersion parsed_version = UnsupportedQuicVersion(); error_code = QuicFramer::ParsePublicHeaderDispatcher( - *encrypted, kQuicDefaultConnectionIdLength, &format, &version_flag, - &use_length_prefix, &version_label, &parsed_version, + *encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type, + &version_flag, &use_length_prefix, &version_label, &parsed_version, &destination_connection_id, &source_connection_id, &retry_token_present, &retry_token, &detailed_error); EXPECT_EQ(retry_token_present, framer_.version().SupportsRetry()); @@ -1146,6 +1148,7 @@ QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false); PacketHeaderFormat format = GOOGLE_QUIC_PACKET; + QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE; bool version_flag = false; QuicConnectionId destination_connection_id, source_connection_id; QuicVersionLabel version_label = 0; @@ -1161,8 +1164,8 @@ QuicStringPiece retry_token; ParsedQuicVersion parsed_version = UnsupportedQuicVersion(); error_code = QuicFramer::ParsePublicHeaderDispatcher( - encrypted, kQuicDefaultConnectionIdLength, &format, &version_flag, - &use_length_prefix, &version_label, &parsed_version, + encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type, + &version_flag, &use_length_prefix, &version_label, &parsed_version, &destination_connection_id, &source_connection_id, &retry_token_present, &retry_token, &detailed_error); EXPECT_FALSE(retry_token_present); @@ -13152,6 +13155,7 @@ visitor_.header_.get()->destination_connection_id); PacketHeaderFormat format = GOOGLE_QUIC_PACKET; + QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE; bool version_present = false, has_length_prefix = false; QuicVersionLabel version_label = 0; ParsedQuicVersion parsed_version = QuicVersionReservedForNegotiation(); @@ -13162,8 +13166,8 @@ std::string detailed_error = "foobar"; QuicErrorCode parse_result = QuicFramer::ParsePublicHeaderDispatcher( - encrypted, kQuicDefaultConnectionIdLength, &format, &version_present, - &has_length_prefix, &version_label, &parsed_version, + encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type, + &version_present, &has_length_prefix, &version_label, &parsed_version, &destination_connection_id, &source_connection_id, &retry_token_present, &retry_token, &detailed_error); EXPECT_EQ(QUIC_NO_ERROR, parse_result); @@ -13302,6 +13306,7 @@ QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet), sizeof(packet)); PacketHeaderFormat format = GOOGLE_QUIC_PACKET; + QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE; bool version_present = false, has_length_prefix = true; QuicVersionLabel version_label = 33; ParsedQuicVersion parsed_version = UnsupportedQuicVersion(); @@ -13311,8 +13316,8 @@ QuicStringPiece retry_token; std::string detailed_error = "foobar"; QuicErrorCode header_parse_result = QuicFramer::ParsePublicHeaderDispatcher( - encrypted, kQuicDefaultConnectionIdLength, &format, &version_present, - &has_length_prefix, &version_label, &parsed_version, + encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type, + &version_present, &has_length_prefix, &version_label, &parsed_version, &destination_connection_id, &source_connection_id, &retry_token_present, &retry_token, &detailed_error); EXPECT_EQ(QUIC_NO_ERROR, header_parse_result); @@ -13380,6 +13385,7 @@ QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet), sizeof(packet)); PacketHeaderFormat format = GOOGLE_QUIC_PACKET; + QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE; bool version_present = false, has_length_prefix = false; QuicVersionLabel version_label = 33; ParsedQuicVersion parsed_version = UnsupportedQuicVersion(); @@ -13389,8 +13395,8 @@ QuicStringPiece retry_token; std::string detailed_error = "foobar"; QuicErrorCode header_parse_result = QuicFramer::ParsePublicHeaderDispatcher( - encrypted, kQuicDefaultConnectionIdLength, &format, &version_present, - &has_length_prefix, &version_label, &parsed_version, + encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type, + &version_present, &has_length_prefix, &version_label, &parsed_version, &destination_connection_id, &source_connection_id, &retry_token_present, &retry_token, &detailed_error); EXPECT_EQ(QUIC_NO_ERROR, header_parse_result);
diff --git a/quic/core/quic_packets.cc b/quic/core/quic_packets.cc index 0352056..139fcda 100644 --- a/quic/core/quic_packets.cc +++ b/quic/core/quic_packets.cc
@@ -502,6 +502,7 @@ peer_address(peer_address), packet(packet), form(GOOGLE_QUIC_PACKET), + long_packet_type(INVALID_PACKET_TYPE), version_flag(false), use_length_prefix(false), version_label(0),
diff --git a/quic/core/quic_packets.h b/quic/core/quic_packets.h index 5c34b64..7faa741 100644 --- a/quic/core/quic_packets.h +++ b/quic/core/quic_packets.h
@@ -437,6 +437,8 @@ // Fields below are populated by QuicFramer::ProcessPacketDispatcher. PacketHeaderFormat form; + // This is only used if the form is IETF_QUIC_LONG_HEADER_PACKET. + QuicLongHeaderType long_packet_type; bool version_flag; bool use_length_prefix; QuicVersionLabel version_label;
diff --git a/quic/core/quic_time_wait_list_manager.cc b/quic/core/quic_time_wait_list_manager.cc index b163185..b8becf6 100644 --- a/quic/core/quic_time_wait_list_manager.cc +++ b/quic/core/quic_time_wait_list_manager.cc
@@ -271,6 +271,14 @@ packet_context.get()); } +void QuicTimeWaitListManager::SendPacket(const QuicSocketAddress& self_address, + const QuicSocketAddress& peer_address, + const QuicEncryptedPacket& packet) { + SendOrQueuePacket(std::make_unique<QueuedPacket>(self_address, peer_address, + packet.Clone()), + nullptr); +} + std::unique_ptr<QuicEncryptedPacket> QuicTimeWaitListManager::BuildPublicReset( const QuicPublicResetPacket& packet) { return QuicFramer::BuildPublicResetPacket(packet);
diff --git a/quic/core/quic_time_wait_list_manager.h b/quic/core/quic_time_wait_list_manager.h index 9a807c0..e2a4594 100644 --- a/quic/core/quic_time_wait_list_manager.h +++ b/quic/core/quic_time_wait_list_manager.h
@@ -139,6 +139,11 @@ bool ietf_quic, std::unique_ptr<QuicPerPacketContext> packet_context); + // Called to send |packet|. + virtual void SendPacket(const QuicSocketAddress& self_address, + const QuicSocketAddress& peer_address, + const QuicEncryptedPacket& packet); + // Return a non-owning pointer to the packet writer. QuicPacketWriter* writer() { return writer_; }
diff --git a/quic/test_tools/mock_quic_time_wait_list_manager.h b/quic/test_tools/mock_quic_time_wait_list_manager.h index 6b2b6d0..b8a9776 100644 --- a/quic/test_tools/mock_quic_time_wait_list_manager.h +++ b/quic/test_tools/mock_quic_time_wait_list_manager.h
@@ -61,6 +61,11 @@ QuicConnectionId, bool, std::unique_ptr<QuicPerPacketContext>)); + + MOCK_METHOD3(SendPacket, + void(const QuicSocketAddress&, + const QuicSocketAddress&, + const QuicEncryptedPacket&)); }; } // namespace test
diff --git a/quic/test_tools/quic_test_utils.cc b/quic/test_tools/quic_test_utils.cc index 387dbe1..2637702 100644 --- a/quic/test_tools/quic_test_utils.cc +++ b/quic/test_tools/quic_test_utils.cc
@@ -867,10 +867,11 @@ ParsedQuicVersionVector* versions) { return ConstructEncryptedPacket( destination_connection_id, source_connection_id, version_flag, reset_flag, - packet_number, data, destination_connection_id_included, + packet_number, data, false, destination_connection_id_included, source_connection_id_included, packet_number_length, versions, Perspective::IS_CLIENT); } + QuicEncryptedPacket* ConstructEncryptedPacket( QuicConnectionId destination_connection_id, QuicConnectionId source_connection_id, @@ -878,6 +879,26 @@ bool reset_flag, uint64_t packet_number, const std::string& data, + bool full_padding, + QuicConnectionIdIncluded destination_connection_id_included, + QuicConnectionIdIncluded source_connection_id_included, + QuicPacketNumberLength packet_number_length, + ParsedQuicVersionVector* versions) { + return ConstructEncryptedPacket( + destination_connection_id, source_connection_id, version_flag, reset_flag, + packet_number, data, full_padding, destination_connection_id_included, + source_connection_id_included, packet_number_length, versions, + Perspective::IS_CLIENT); +} + +QuicEncryptedPacket* ConstructEncryptedPacket( + QuicConnectionId destination_connection_id, + QuicConnectionId source_connection_id, + bool version_flag, + bool reset_flag, + uint64_t packet_number, + const std::string& data, + bool full_padding, QuicConnectionIdIncluded destination_connection_id_included, QuicConnectionIdIncluded source_connection_id_included, QuicPacketNumberLength packet_number_length, @@ -922,14 +943,18 @@ QuicFrame frame(new QuicCryptoFrame(level, 0, data)); frames.push_back(frame); } - // We need a minimum number of bytes of encrypted payload. This will - // guarantee that we have at least that much. (It ignores the overhead of the - // stream/crypto framing, so it overpads slightly.) - size_t min_plaintext_size = - QuicPacketCreator::MinPlaintextPacketSize(version); - if (data.length() < min_plaintext_size) { - size_t padding_length = min_plaintext_size - data.length(); - frames.push_back(QuicFrame(QuicPaddingFrame(padding_length))); + if (full_padding) { + frames.push_back(QuicFrame(QuicPaddingFrame(-1))); + } else { + // We need a minimum number of bytes of encrypted payload. This will + // guarantee that we have at least that much. (It ignores the overhead of + // the stream/crypto framing, so it overpads slightly.) + size_t min_plaintext_size = + QuicPacketCreator::MinPlaintextPacketSize(version); + if (data.length() < min_plaintext_size) { + size_t padding_length = min_plaintext_size - data.length(); + frames.push_back(QuicFrame(QuicPaddingFrame(padding_length))); + } } std::unique_ptr<QuicPacket> packet(
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h index ba5e1cd..94f25fc 100644 --- a/quic/test_tools/quic_test_utils.h +++ b/quic/test_tools/quic_test_utils.h
@@ -82,12 +82,26 @@ bool reset_flag, uint64_t packet_number, const std::string& data, + bool full_padding, QuicConnectionIdIncluded destination_connection_id_included, QuicConnectionIdIncluded source_connection_id_included, QuicPacketNumberLength packet_number_length, ParsedQuicVersionVector* versions, Perspective perspective); +QuicEncryptedPacket* ConstructEncryptedPacket( + QuicConnectionId destination_connection_id, + QuicConnectionId source_connection_id, + bool version_flag, + bool reset_flag, + uint64_t packet_number, + const std::string& data, + bool full_padding, + QuicConnectionIdIncluded destination_connection_id_included, + QuicConnectionIdIncluded source_connection_id_included, + QuicPacketNumberLength packet_number_length, + ParsedQuicVersionVector* versions); + // Create an encrypted packet for testing. // If versions == nullptr, uses &AllSupportedVersions(). // Note that the packet is encrypted with NullEncrypter, so to decrypt the