mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-08-08 09:42:06 +03:00
Move Quic packet header encoding out of builder constructor
Summary: Currently the packet builder contructor will encode the packet builder. This is fine when the builder creates its own output buffer. If later on we decides not to use this builder, or it fails to build packet, the buffer will be thrown away. But once the builder uses a buffer provided by caller, and will be reused, we can no longer just throw it away if we decide not to use this builder. So we have to delay the header encoding until we know we will use the builder. This is still not enough to solve the case where we want to use this builder, it builds, then it fails . For that, we will need to retreat the tail position of the IOBuf. Reviewed By: mjoras Differential Revision: D21000658 fbshipit-source-id: 4d758b3e260463b17c870618ba68bd4b898a7d4c
This commit is contained in:
committed by
Facebook GitHub Bot
parent
f36747c31b
commit
2a1529068d
@@ -82,26 +82,6 @@ class QuicPacketSchedulerTest : public Test {
|
||||
QuicVersion version{QuicVersion::MVFST};
|
||||
};
|
||||
|
||||
TEST_F(QuicPacketSchedulerTest, NoopScheduler) {
|
||||
QuicConnectionStateBase conn(QuicNodeType::Client);
|
||||
FrameScheduler scheduler("frame");
|
||||
EXPECT_FALSE(scheduler.hasData());
|
||||
|
||||
LongHeader header(
|
||||
LongHeader::Types::Initial,
|
||||
getTestConnectionId(1),
|
||||
getTestConnectionId(),
|
||||
0x1356,
|
||||
version);
|
||||
RegularQuicPacketBuilder builder(
|
||||
conn.udpSendPacketLen,
|
||||
std::move(header),
|
||||
conn.ackStates.initialAckState.largestAckedByPeer);
|
||||
|
||||
auto builtPacket = std::move(builder).buildPacket();
|
||||
EXPECT_TRUE(builtPacket.packet.frames.empty());
|
||||
}
|
||||
|
||||
TEST_F(QuicPacketSchedulerTest, CryptoPaddingInitialPacket) {
|
||||
QuicClientConnectionState conn(
|
||||
FizzClientQuicHandshakeContext::Builder().build());
|
||||
@@ -330,6 +310,7 @@ TEST_F(QuicPacketSchedulerTest, CryptoSchedulerOnlySingleLossFits) {
|
||||
conn.udpSendPacketLen,
|
||||
std::move(longHeader),
|
||||
conn.ackStates.handshakeAckState.largestAckedByPeer);
|
||||
builder.encodePacketHeader();
|
||||
PacketBuilderWrapper builderWrapper(builder, 13);
|
||||
CryptoStreamScheduler scheduler(
|
||||
conn, *getCryptoStream(*conn.cryptoState, EncryptionLevel::Handshake));
|
||||
@@ -394,6 +375,7 @@ TEST_F(QuicPacketSchedulerTest, StreamFrameSchedulerExists) {
|
||||
conn.udpSendPacketLen,
|
||||
std::move(shortHeader),
|
||||
conn.ackStates.appDataAckState.largestAckedByPeer);
|
||||
builder.encodePacketHeader();
|
||||
auto originalSpace = builder.remainingSpaceInPkt();
|
||||
conn.streamManager->queueWindowUpdate(stream->id);
|
||||
scheduler.writeWindowUpdates(builder);
|
||||
@@ -415,6 +397,7 @@ TEST_F(QuicPacketSchedulerTest, StreamFrameNoSpace) {
|
||||
conn.udpSendPacketLen,
|
||||
std::move(shortHeader),
|
||||
conn.ackStates.appDataAckState.largestAckedByPeer);
|
||||
builder.encodePacketHeader();
|
||||
PacketBuilderWrapper builderWrapper(builder, 2);
|
||||
auto originalSpace = builder.remainingSpaceInPkt();
|
||||
conn.streamManager->queueWindowUpdate(stream->id);
|
||||
@@ -436,6 +419,7 @@ TEST_F(QuicPacketSchedulerTest, StreamFrameSchedulerStreamNotExists) {
|
||||
conn.udpSendPacketLen,
|
||||
std::move(shortHeader),
|
||||
conn.ackStates.appDataAckState.largestAckedByPeer);
|
||||
builder.encodePacketHeader();
|
||||
auto originalSpace = builder.remainingSpaceInPkt();
|
||||
conn.streamManager->queueWindowUpdate(nonExistentStream);
|
||||
scheduler.writeWindowUpdates(builder);
|
||||
@@ -470,75 +454,6 @@ TEST_F(QuicPacketSchedulerTest, CloningSchedulerTest) {
|
||||
EXPECT_EQ(packetNum, *result.packetEvent);
|
||||
}
|
||||
|
||||
TEST_F(QuicPacketSchedulerTest, WriteOnlyOutstandingPacketsTest) {
|
||||
QuicClientConnectionState conn(
|
||||
FizzClientQuicHandshakeContext::Builder().build());
|
||||
FrameScheduler noopScheduler("frame");
|
||||
ASSERT_FALSE(noopScheduler.hasData());
|
||||
CloningScheduler cloningScheduler(noopScheduler, conn, "CopyCat", 0);
|
||||
EXPECT_FALSE(cloningScheduler.hasData());
|
||||
auto packetNum = addOutstandingPacket(conn);
|
||||
// There needs to have retransmittable frame for the rebuilder to work
|
||||
conn.outstandingPackets.back().packet.frames.push_back(
|
||||
MaxDataFrame(conn.flowControlState.advertisedMaxOffset));
|
||||
EXPECT_TRUE(cloningScheduler.hasData());
|
||||
|
||||
ASSERT_FALSE(noopScheduler.hasData());
|
||||
ShortHeader header(
|
||||
ProtectionType::KeyPhaseOne,
|
||||
conn.clientConnectionId.value_or(getTestConnectionId()),
|
||||
getNextPacketNum(conn, PacketNumberSpace::AppData));
|
||||
RegularQuicPacketBuilder regularBuilder(
|
||||
conn.udpSendPacketLen,
|
||||
std::move(header),
|
||||
conn.ackStates.appDataAckState.largestAckedByPeer);
|
||||
|
||||
// Create few frames
|
||||
ConnectionCloseFrame connCloseFrame(
|
||||
QuicErrorCode(TransportErrorCode::FRAME_ENCODING_ERROR),
|
||||
"The sun is in the sky.");
|
||||
MaxStreamsFrame maxStreamFrame(999, true);
|
||||
PingFrame pingFrame;
|
||||
AckBlocks ackBlocks;
|
||||
ackBlocks.insert(10, 100);
|
||||
ackBlocks.insert(200, 1000);
|
||||
AckFrameMetaData ackMeta(ackBlocks, 0us, kDefaultAckDelayExponent);
|
||||
|
||||
// Write those framses with a regular builder
|
||||
writeFrame(connCloseFrame, regularBuilder);
|
||||
writeFrame(QuicSimpleFrame(maxStreamFrame), regularBuilder);
|
||||
writeFrame(QuicSimpleFrame(pingFrame), regularBuilder);
|
||||
writeAckFrame(ackMeta, regularBuilder);
|
||||
|
||||
auto result = cloningScheduler.scheduleFramesForPacket(
|
||||
std::move(regularBuilder), kDefaultUDPSendPacketLen);
|
||||
EXPECT_TRUE(result.packetEvent.has_value() && result.packet.has_value());
|
||||
EXPECT_EQ(packetNum, *result.packetEvent);
|
||||
// written packet (result.packet) should not have any frame in the builder
|
||||
auto& writtenPacket = *result.packet;
|
||||
auto shortHeader = writtenPacket.packet.header.asShort();
|
||||
CHECK(shortHeader);
|
||||
EXPECT_EQ(ProtectionType::KeyPhaseOne, shortHeader->getProtectionType());
|
||||
EXPECT_EQ(
|
||||
conn.ackStates.appDataAckState.nextPacketNum,
|
||||
shortHeader->getPacketSequenceNum());
|
||||
|
||||
// Test that the only frame that's written is maxdataframe
|
||||
EXPECT_GE(writtenPacket.packet.frames.size(), 1);
|
||||
auto& writtenFrame = writtenPacket.packet.frames.at(0);
|
||||
auto maxDataFrame = writtenFrame.asMaxDataFrame();
|
||||
CHECK(maxDataFrame);
|
||||
for (auto& frame : writtenPacket.packet.frames) {
|
||||
bool present = false;
|
||||
/* the next four frames should not be written */
|
||||
present |= frame.asConnectionCloseFrame() ? true : false;
|
||||
present |= frame.asQuicSimpleFrame() ? true : false;
|
||||
present |= frame.asQuicSimpleFrame() ? true : false;
|
||||
present |= frame.asWriteAckFrame() ? true : false;
|
||||
ASSERT_FALSE(present);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(QuicPacketSchedulerTest, DoNotCloneProcessedClonedPacket) {
|
||||
QuicClientConnectionState conn(
|
||||
FizzClientQuicHandshakeContext::Builder().build());
|
||||
@@ -819,6 +734,7 @@ TEST_F(QuicPacketSchedulerTest, StreamFrameSchedulerAllFit) {
|
||||
conn.udpSendPacketLen,
|
||||
std::move(shortHeader),
|
||||
conn.ackStates.appDataAckState.largestAckedByPeer);
|
||||
builder.encodePacketHeader();
|
||||
auto stream1 =
|
||||
conn.streamManager->createNextBidirectionalStream().value()->id;
|
||||
auto stream2 =
|
||||
@@ -853,10 +769,11 @@ TEST_F(QuicPacketSchedulerTest, StreamFrameSchedulerRoundRobin) {
|
||||
ProtectionType::KeyPhaseZero,
|
||||
connId,
|
||||
getNextPacketNum(conn, PacketNumberSpace::AppData));
|
||||
RegularQuicPacketBuilder builder1(
|
||||
RegularQuicPacketBuilder builder(
|
||||
conn.udpSendPacketLen,
|
||||
std::move(shortHeader1),
|
||||
conn.ackStates.appDataAckState.largestAckedByPeer);
|
||||
builder.encodePacketHeader();
|
||||
auto stream1 =
|
||||
conn.streamManager->createNextBidirectionalStream().value()->id;
|
||||
auto stream2 =
|
||||
@@ -882,7 +799,7 @@ TEST_F(QuicPacketSchedulerTest, StreamFrameSchedulerRoundRobin) {
|
||||
false);
|
||||
// Force the wraparound initially.
|
||||
conn.schedulingState.nextScheduledStream = stream3 + 8;
|
||||
scheduler.writeStreams(builder1);
|
||||
scheduler.writeStreams(builder);
|
||||
EXPECT_EQ(conn.schedulingState.nextScheduledStream, 4);
|
||||
|
||||
// Should write frames for stream2, stream3, followed by stream1 again.
|
||||
@@ -986,10 +903,11 @@ TEST_F(QuicPacketSchedulerTest, StreamFrameSchedulerRoundRobinControl) {
|
||||
ProtectionType::KeyPhaseZero,
|
||||
connId,
|
||||
getNextPacketNum(conn, PacketNumberSpace::AppData));
|
||||
RegularQuicPacketBuilder builder1(
|
||||
RegularQuicPacketBuilder builder(
|
||||
conn.udpSendPacketLen,
|
||||
std::move(shortHeader1),
|
||||
conn.ackStates.appDataAckState.largestAckedByPeer);
|
||||
builder.encodePacketHeader();
|
||||
auto stream1 =
|
||||
conn.streamManager->createNextBidirectionalStream().value()->id;
|
||||
auto stream2 =
|
||||
@@ -1025,7 +943,7 @@ TEST_F(QuicPacketSchedulerTest, StreamFrameSchedulerRoundRobinControl) {
|
||||
false);
|
||||
// Force the wraparound initially.
|
||||
conn.schedulingState.nextScheduledStream = stream4 + 8;
|
||||
scheduler.writeStreams(builder1);
|
||||
scheduler.writeStreams(builder);
|
||||
EXPECT_EQ(conn.schedulingState.nextScheduledStream, stream3);
|
||||
EXPECT_EQ(conn.schedulingState.nextScheduledControlStream, stream2);
|
||||
|
||||
@@ -1071,6 +989,7 @@ TEST_F(QuicPacketSchedulerTest, StreamFrameSchedulerOneStream) {
|
||||
conn.udpSendPacketLen,
|
||||
std::move(shortHeader),
|
||||
conn.ackStates.appDataAckState.largestAckedByPeer);
|
||||
builder.encodePacketHeader();
|
||||
auto stream1 = conn.streamManager->createNextBidirectionalStream().value();
|
||||
writeDataToQuicStream(*stream1, folly::IOBuf::copyBuffer("some data"), false);
|
||||
scheduler.writeStreams(builder);
|
||||
|
Reference in New Issue
Block a user