diff --git a/quic/api/QuicTransportFunctions.cpp b/quic/api/QuicTransportFunctions.cpp index fd60bb7a6..c6344b8a3 100644 --- a/quic/api/QuicTransportFunctions.cpp +++ b/quic/api/QuicTransportFunctions.cpp @@ -1107,7 +1107,7 @@ WriteQuicDataResult writeCryptoAndAckDataToSocket( connection, srcConnId, dstConnId, - std::move(builder), + builder, LongHeader::typeToPacketNumberSpace(packetType), scheduler, congestionControlWritableBytes, @@ -1121,6 +1121,27 @@ WriteQuicDataResult writeCryptoAndAckDataToSocket( packetsWritten += writeResult.packetsWritten; bytesWritten += writeResult.bytesWritten; + if (connection.transportSettings.immediatelyRetransmitInitialPackets && + packetsWritten > 0 && packetsWritten < packetLimit) { + auto remainingLimit = packetLimit - packetsWritten; + auto cloneResult = writeProbingDataToSocket( + sock, + connection, + srcConnId, + dstConnId, + builder, + encryptionLevel, + LongHeader::typeToPacketNumberSpace(packetType), + scheduler, + packetsWritten < remainingLimit ? packetsWritten : remainingLimit, + cleartextCipher, + headerCipher, + version, + token); + probesWritten += cloneResult.probesWritten; + bytesWritten += cloneResult.bytesWritten; + } + VLOG_IF(10, packetsWritten || probesWritten) << nodeToString(connection.nodeType) << " written crypto and acks data type=" << packetType diff --git a/quic/api/test/QuicTransportFunctionsTest.cpp b/quic/api/test/QuicTransportFunctionsTest.cpp index 28d7beba5..4b22a9198 100644 --- a/quic/api/test/QuicTransportFunctionsTest.cpp +++ b/quic/api/test/QuicTransportFunctionsTest.cpp @@ -3372,6 +3372,38 @@ TEST_F(QuicTransportFunctionsTest, NoCryptoProbeWriteIfNoProbeCredit) { EXPECT_EQ(0, res.probesWritten); } +TEST_F(QuicTransportFunctionsTest, ImmediatelyRetransmitInitialPackets) { + auto conn = createConn(); + conn->transportSettings.immediatelyRetransmitInitialPackets = true; + auto cryptoStream = &conn->cryptoState->initialStream; + auto buf = buildRandomInputData(1600); + writeDataToQuicStream(*cryptoStream, buf->clone()); + EventBase evb; + std::shared_ptr qEvb = + std::make_shared(&evb); + auto socket = + std::make_unique>(qEvb); + auto rawSocket = socket.get(); + auto res = writeCryptoAndAckDataToSocket( + *rawSocket, + *conn, + *conn->clientConnectionId, + *conn->serverConnectionId, + LongHeader::Types::Initial, + *conn->initialWriteCipher, + *conn->initialHeaderCipher, + getVersion(*conn), + conn->transportSettings.writeConnectionDataPacketsLimit); + EXPECT_GE(res.bytesWritten, buf->computeChainDataLength()); + + EXPECT_EQ(2, res.packetsWritten); + EXPECT_EQ(2, res.probesWritten); + EXPECT_EQ(conn->udpSendPacketLen * 4, res.bytesWritten); + ASSERT_EQ(4, conn->outstandings.packets.size()); + ASSERT_EQ(2, cryptoStream->retransmissionBuffer.size()); + ASSERT_TRUE(cryptoStream->pendingWrites.empty()); +} + TEST_F(QuicTransportFunctionsTest, ResetNumProbePackets) { auto conn = createConn(); EventBase evb; diff --git a/quic/state/TransportSettings.h b/quic/state/TransportSettings.h index d3d383cfb..71f21f5f7 100644 --- a/quic/state/TransportSettings.h +++ b/quic/state/TransportSettings.h @@ -415,6 +415,7 @@ struct TransportSettings { // Raise read callbacks for all unidirectional streams first on data // reception. bool unidirectionalStreamsReadCallbacksFirst{false}; + bool immediatelyRetransmitInitialPackets{false}; }; } // namespace quic