1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-08-08 09:42:06 +03:00

Use custom variant type for write frames

Summary:
Use the custom variant type for write frames as well, now that
we use them for read frames.

Reviewed By: mjoras

Differential Revision: D17776862

fbshipit-source-id: 47093146d0f1565c22e5393ed012c70e2e23d279
This commit is contained in:
Subodh Iyengar
2019-10-07 22:41:31 -07:00
committed by Facebook Github Bot
parent 233346268e
commit 68c332acb1
22 changed files with 1201 additions and 994 deletions

View File

@@ -203,9 +203,9 @@ void updateConnection(
conn.qLogger->addPacket(packet, encodedSize);
}
for (const auto& frame : packet.frames) {
folly::variant_match(
frame,
[&](const WriteStreamFrame& writeStreamFrame) {
switch (frame.type()) {
case QuicWriteFrame::Type::WriteStreamFrame_E: {
const WriteStreamFrame& writeStreamFrame = *frame.asWriteStreamFrame();
retransmittable = true;
auto stream = CHECK_NOTNULL(
conn.streamManager->getStream(writeStreamFrame.streamId));
@@ -223,8 +223,10 @@ void updateConnection(
conn.streamManager->updateWritableStreams(*stream);
}
conn.streamManager->updateLossStreams(*stream);
},
[&](const WriteCryptoFrame& writeCryptoFrame) {
break;
}
case QuicWriteFrame::Type::WriteCryptoFrame_E: {
const WriteCryptoFrame& writeCryptoFrame = *frame.asWriteCryptoFrame();
retransmittable = true;
auto protectionType = packet.header.getProtectionType();
// NewSessionTicket is sent in crypto frame encrypted with 1-rtt key,
@@ -232,8 +234,7 @@ void updateConnection(
isHandshake =
(protectionType == ProtectionType::Initial ||
protectionType == ProtectionType::Handshake);
auto encryptionLevel =
protectionTypeToEncryptionLevel(protectionType);
auto encryptionLevel = protectionTypeToEncryptionLevel(protectionType);
handleStreamWritten(
conn,
*getCryptoStream(*conn.cryptoState, encryptionLevel),
@@ -242,8 +243,10 @@ void updateConnection(
false,
packetNum,
packetNumberSpace);
},
[&](const WriteAckFrame& writeAckFrame) {
break;
}
case QuicWriteFrame::Type::WriteAckFrame_E: {
const WriteAckFrame& writeAckFrame = *frame.asWriteAckFrame();
DCHECK(!ackFrameCounter++)
<< "Send more than one WriteAckFrame " << conn;
auto largestAckedPacketWritten = writeAckFrame.ackBlocks.back().end;
@@ -255,8 +258,10 @@ void updateConnection(
conn,
getAckState(conn, packetNumberSpace),
largestAckedPacketWritten);
},
[&](const RstStreamFrame& rstStreamFrame) {
break;
}
case QuicWriteFrame::Type::RstStreamFrame_E: {
const RstStreamFrame& rstStreamFrame = *frame.asRstStreamFrame();
retransmittable = true;
VLOG(10) << nodeToString(conn.nodeType)
<< " sent reset streams in packetNum=" << packetNum << " "
@@ -271,8 +276,10 @@ void updateConnection(
DCHECK(packetEvent.hasValue())
<< " reset missing from pendingEvents for non-clone packet";
}
},
[&](const MaxDataFrame& maxDataFrame) {
break;
}
case QuicWriteFrame::Type::MaxDataFrame_E: {
const MaxDataFrame& maxDataFrame = *frame.asMaxDataFrame();
CHECK(!connWindowUpdateSent++)
<< "Send more than one connection window update " << conn;
VLOG(10) << nodeToString(conn.nodeType)
@@ -280,12 +287,15 @@ void updateConnection(
<< conn;
retransmittable = true;
VLOG(10) << nodeToString(conn.nodeType)
<< " sent conn window update in packetNum=" << packetNum
<< " " << conn;
<< " sent conn window update in packetNum=" << packetNum << " "
<< conn;
onConnWindowUpdateSent(
conn, packetNum, maxDataFrame.maximumData, sentTime);
},
[&](const MaxStreamDataFrame& maxStreamDataFrame) {
break;
}
case QuicWriteFrame::Type::MaxStreamDataFrame_E: {
const MaxStreamDataFrame& maxStreamDataFrame =
*frame.asMaxStreamDataFrame();
auto stream = CHECK_NOTNULL(
conn.streamManager->getStream(maxStreamDataFrame.streamId));
retransmittable = true;
@@ -294,15 +304,28 @@ void updateConnection(
<< " stream=" << maxStreamDataFrame.streamId << " " << conn;
onStreamWindowUpdateSent(
*stream, packetNum, maxStreamDataFrame.maximumData, sentTime);
},
[&](const StreamDataBlockedFrame& streamBlockedFrame) {
break;
}
case QuicWriteFrame::Type::StreamDataBlockedFrame_E: {
const StreamDataBlockedFrame& streamBlockedFrame =
*frame.asStreamDataBlockedFrame();
VLOG(10) << nodeToString(conn.nodeType)
<< " sent blocked stream frame packetNum=" << packetNum
<< " " << conn;
<< " sent blocked stream frame packetNum=" << packetNum << " "
<< conn;
retransmittable = true;
conn.streamManager->removeBlocked(streamBlockedFrame.streamId);
},
[&](const PaddingFrame&) {
break;
}
case QuicWriteFrame::Type::QuicSimpleFrame_E: {
const QuicSimpleFrame& simpleFrame = *frame.asQuicSimpleFrame();
retransmittable = true;
// We don't want this triggered for cloned frames.
if (!packetEvent.hasValue()) {
updateSimpleFrameOnPacketSent(conn, simpleFrame);
}
break;
}
case QuicWriteFrame::Type::PaddingFrame_E: {
// do not mark padding as retransmittable. There are several reasons
// for this:
// 1. We might need to pad ACK packets to make it so that we can
@@ -310,15 +333,11 @@ void updateConnection(
// count towards congestion window, so the padding frames in those
// ack packets should not count towards the window either
// 2. Of course we do not want to retransmit the ACK frames.
},
[&](const QuicSimpleFrame& simpleFrame) {
retransmittable = true;
// We don't want this triggered for cloned frames.
if (!packetEvent.hasValue()) {
updateSimpleFrameOnPacketSent(conn, simpleFrame);
break;
}
default:
retransmittable = true;
}
},
[&](const auto&) { retransmittable = true; });
}
// TODO: Now pureAck is equivalent to non retransmittable packet. This might

View File

@@ -366,7 +366,7 @@ TEST_F(QuicPacketSchedulerTest, WriteOnlyOutstandingPacketsTest) {
// Write those framses with a regular builder
writeFrame(connCloseFrame, regularBuilder);
writeFrame(maxStreamFrame, regularBuilder);
writeFrame(QuicSimpleFrame(maxStreamFrame), regularBuilder);
writeFrame(pingFrame, regularBuilder);
writeAckFrame(ackMeta, regularBuilder);
@@ -386,15 +386,15 @@ TEST_F(QuicPacketSchedulerTest, WriteOnlyOutstandingPacketsTest) {
// 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 = boost::get<MaxDataFrame>(&writtenFrame);
auto maxDataFrame = writtenFrame.asMaxDataFrame();
CHECK(maxDataFrame);
for (auto& frame : writtenPacket.packet.frames) {
bool present = false;
/* the next four frames should not be written */
present |= boost::get<ConnectionCloseFrame>(&frame) ? true : false;
present |= boost::get<QuicSimpleFrame>(&frame) ? true : false;
present |= boost::get<PingFrame>(&frame) ? true : false;
present |= boost::get<WriteAckFrame>(&frame) ? true : false;
present |= frame.asConnectionCloseFrame() ? true : false;
present |= frame.asQuicSimpleFrame() ? true : false;
present |= frame.asPingFrame() ? true : false;
present |= frame.asWriteAckFrame() ? true : false;
ASSERT_FALSE(present);
}
}
@@ -535,12 +535,10 @@ TEST_F(QuicPacketSchedulerTest, CloneSchedulerUseNormalSchedulerFirst) {
conn.ackStates.appDataAckState.nextPacketNum,
shortHeader.getPacketSequenceNum());
EXPECT_EQ(1, result.second->packet.frames.size());
folly::variant_match(
result.second->packet.frames.front(),
[&](const MaxDataFrame& frame) { EXPECT_EQ(2832, frame.maximumData); },
[&](const auto&) {
ASSERT_FALSE(true); // should not happen
});
MaxDataFrame* maxDataFrame =
result.second->packet.frames.front().asMaxDataFrame();
ASSERT_NE(maxDataFrame, nullptr);
EXPECT_EQ(2832, maxDataFrame->maximumData);
EXPECT_TRUE(folly::IOBufEqualTo{}(
*folly::IOBuf::copyBuffer("if you are the dealer"),
*result.second->header));
@@ -580,18 +578,25 @@ TEST_F(QuicPacketSchedulerTest, CloneWillGenerateNewWindowUpdate) {
EXPECT_EQ(expectedPacketEvent, *packetResult.first);
int32_t verifyConnWindowUpdate = 1, verifyStreamWindowUpdate = 1;
for (const auto& frame : packetResult.second->packet.frames) {
folly::variant_match(
frame,
[&](const MaxStreamDataFrame& maxStreamDataFrame) {
switch (frame.type()) {
case QuicWriteFrame::Type::MaxStreamDataFrame_E: {
const MaxStreamDataFrame& maxStreamDataFrame =
*frame.asMaxStreamDataFrame();
EXPECT_EQ(stream->id, maxStreamDataFrame.streamId);
verifyStreamWindowUpdate--;
},
[&](const MaxDataFrame&) { verifyConnWindowUpdate--; },
[&](const PaddingFrame&) {},
[&](const auto&) {
break;
}
case QuicWriteFrame::Type::MaxDataFrame_E: {
verifyConnWindowUpdate--;
break;
}
case QuicWriteFrame::Type::PaddingFrame_E: {
break;
}
default:
// should never happen
EXPECT_TRUE(false);
});
}
}
EXPECT_EQ(0, verifyStreamWindowUpdate);
EXPECT_EQ(0, verifyConnWindowUpdate);
@@ -600,15 +605,21 @@ TEST_F(QuicPacketSchedulerTest, CloneWillGenerateNewWindowUpdate) {
EXPECT_GE(packetResult.second->packet.frames.size(), 2);
uint32_t streamWindowUpdateCounter = 0;
uint32_t connWindowUpdateCounter = 0;
for (auto& streamFlowControl :
all_frames<MaxStreamDataFrame>(packetResult.second->packet.frames)) {
streamWindowUpdateCounter++;
EXPECT_EQ(1700, streamFlowControl.maximumData);
for (auto& frame : packetResult.second->packet.frames) {
auto streamFlowControl = frame.asMaxStreamDataFrame();
if (!streamFlowControl) {
continue;
}
streamWindowUpdateCounter++;
EXPECT_EQ(1700, streamFlowControl->maximumData);
}
for (auto& frame : packetResult.second->packet.frames) {
auto connFlowControl = frame.asMaxDataFrame();
if (!connFlowControl) {
continue;
}
for (auto& connFlowControl :
all_frames<MaxDataFrame>(packetResult.second->packet.frames)) {
connWindowUpdateCounter++;
EXPECT_EQ(3300, connFlowControl.maximumData);
EXPECT_EQ(3300, connFlowControl->maximumData);
}
EXPECT_EQ(1, connWindowUpdateCounter);
EXPECT_EQ(1, streamWindowUpdateCounter);

View File

@@ -1223,14 +1223,13 @@ TEST_F(QuicTransportFunctionsTest, NothingWritten) {
0);
}
template <class FrameType>
const FrameType& getFirstFrameInOutstandingPackets(
const std::deque<OutstandingPacket>& outstandingPackets) {
const QuicWriteFrame& getFirstFrameInOutstandingPackets(
const std::deque<OutstandingPacket>& outstandingPackets,
QuicWriteFrame::Type frameType) {
for (const auto& packet : outstandingPackets) {
for (const auto& frame : packet.packet.frames) {
auto decodedFrame = boost::get<FrameType>(&frame);
if (decodedFrame) {
return *decodedFrame;
if (frame.type() == frameType) {
return frame;
}
}
}
@@ -1272,8 +1271,10 @@ TEST_F(QuicTransportFunctionsTest, WriteBlockedFrameWhenBlocked) {
EXPECT_LT(sentBytes, 200);
EXPECT_GT(conn->ackStates.appDataAckState.nextPacketNum, originalNextSeq);
auto blocked = getFirstFrameInOutstandingPackets<StreamDataBlockedFrame>(
conn->outstandingPackets);
auto blocked = *getFirstFrameInOutstandingPackets(
conn->outstandingPackets,
QuicWriteFrame::Type::StreamDataBlockedFrame_E)
.asStreamDataBlockedFrame();
EXPECT_EQ(blocked.streamId, stream1->id);
// Since everything is blocked, we shouldn't write a blocked again, so we
@@ -1758,7 +1759,7 @@ TEST_F(QuicTransportFunctionsTest, UpdateConnectionCloneCounter) {
auto connWindowUpdate =
MaxDataFrame(conn->flowControlState.advertisedMaxOffset);
conn->pendingEvents.connWindowUpdate = true;
packet.packet.frames.push_back(connWindowUpdate);
packet.packet.frames.emplace_back(connWindowUpdate);
PacketEvent packetEvent = 100;
conn->outstandingPacketEvents.insert(packetEvent);
updateConnection(*conn, packetEvent, packet.packet, TimePoint(), 123);
@@ -1788,7 +1789,7 @@ TEST_F(QuicTransportFunctionsTest, ClonedBlocked) {
auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
auto stream = conn->streamManager->createNextBidirectionalStream().value();
StreamDataBlockedFrame blockedFrame(stream->id, 1000);
packet.packet.frames.push_back(blockedFrame);
packet.packet.frames.emplace_back(blockedFrame);
conn->outstandingPacketEvents.insert(packetEvent);
// This shall not crash
updateConnection(
@@ -1805,8 +1806,8 @@ TEST_F(QuicTransportFunctionsTest, TwoConnWindowUpdateWillCrash) {
auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
MaxDataFrame connWindowUpdate(
1000 + conn->flowControlState.advertisedMaxOffset);
packet.packet.frames.push_back(connWindowUpdate);
packet.packet.frames.push_back(connWindowUpdate);
packet.packet.frames.emplace_back(connWindowUpdate);
packet.packet.frames.emplace_back(connWindowUpdate);
conn->pendingEvents.connWindowUpdate = true;
EXPECT_DEATH(
updateConnection(
@@ -1859,7 +1860,7 @@ TEST_F(QuicTransportFunctionsTest, ClonedRst) {
auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
RstStreamFrame rstStreamFrame(
stream->id, GenericApplicationErrorCode::UNKNOWN, 0);
packet.packet.frames.push_back(rstStreamFrame);
packet.packet.frames.emplace_back(std::move(rstStreamFrame));
conn->outstandingPacketEvents.insert(packetEvent);
// This shall not crash
updateConnection(

View File

@@ -235,8 +235,7 @@ size_t bufLength(
void dropPackets(QuicServerConnectionState& conn) {
for (const auto& packet : conn.outstandingPackets) {
for (const auto& frame : packet.packet.frames) {
const WriteStreamFrame* streamFrame =
boost::get<WriteStreamFrame>(&frame);
const WriteStreamFrame* streamFrame = frame.asWriteStreamFrame();
if (!streamFrame) {
continue;
}
@@ -285,15 +284,18 @@ void verifyCorrectness(
bool finSet = false;
std::vector<uint64_t> offsets;
for (const auto& packet : conn.outstandingPackets) {
for (const auto& streamFrame :
all_frames<WriteStreamFrame>(packet.packet.frames)) {
if (streamFrame.streamId != id) {
for (const auto& frame : packet.packet.frames) {
auto streamFrame = frame.asWriteStreamFrame();
if (!streamFrame) {
continue;
}
offsets.push_back(streamFrame.offset);
endOffset = std::max(endOffset, streamFrame.offset + streamFrame.len);
totalLen += streamFrame.len;
finSet |= streamFrame.fin;
if (streamFrame->streamId != id) {
continue;
}
offsets.push_back(streamFrame->offset);
endOffset = std::max(endOffset, streamFrame->offset + streamFrame->len);
totalLen += streamFrame->len;
finSet |= streamFrame->fin;
}
}
auto stream = conn.streamManager->findStream(id);
@@ -592,8 +594,12 @@ TEST_F(QuicTransportTest, WriteFlowControl) {
auto& packet =
getFirstOutstandingPacket(conn, PacketNumberSpace::AppData)->packet;
bool blockedFound = false;
for (auto& blocked : all_frames<StreamDataBlockedFrame>(packet.frames)) {
EXPECT_EQ(blocked.streamId, streamId);
for (auto& frame : packet.frames) {
auto blocked = frame.asStreamDataBlockedFrame();
if (!blocked) {
continue;
}
EXPECT_EQ(blocked->streamId, streamId);
blockedFound = true;
}
EXPECT_TRUE(blockedFound);
@@ -782,10 +788,14 @@ TEST_F(QuicTransportTest, WriteImmediateAcks) {
EXPECT_GE(packet.frames.size(), 1);
bool ackFound = false;
for (auto& ackFrame : all_frames<WriteAckFrame>(packet.frames)) {
EXPECT_EQ(ackFrame.ackBlocks.size(), 1);
EXPECT_EQ(start, ackFrame.ackBlocks.front().start);
EXPECT_EQ(end, ackFrame.ackBlocks.front().end);
for (auto& frame : packet.frames) {
auto ackFrame = frame.asWriteAckFrame();
if (!ackFrame) {
continue;
}
EXPECT_EQ(ackFrame->ackBlocks.size(), 1);
EXPECT_EQ(start, ackFrame->ackBlocks.front().start);
EXPECT_EQ(end, ackFrame->ackBlocks.front().end);
ackFound = true;
}
EXPECT_TRUE(ackFound);
@@ -835,10 +845,14 @@ TEST_F(QuicTransportTest, WritePendingAckIfHavingData) {
EXPECT_GE(packet.frames.size(), 2);
bool ackFound = false;
for (auto& ackFrame : all_frames<WriteAckFrame>(packet.frames)) {
EXPECT_EQ(ackFrame.ackBlocks.size(), 1);
EXPECT_EQ(ackFrame.ackBlocks.front().start, start);
EXPECT_EQ(ackFrame.ackBlocks.front().end, end);
for (auto& frame : packet.frames) {
auto ackFrame = frame.asWriteAckFrame();
if (!ackFrame) {
continue;
}
EXPECT_EQ(ackFrame->ackBlocks.size(), 1);
EXPECT_EQ(ackFrame->ackBlocks.front().start, start);
EXPECT_EQ(ackFrame->ackBlocks.front().end, end);
ackFound = true;
}
EXPECT_TRUE(ackFound);
@@ -864,10 +878,14 @@ TEST_F(QuicTransportTest, RstStream) {
->packet;
EXPECT_GE(packet.frames.size(), 1);
bool rstFound = false;
for (auto& frame : all_frames<RstStreamFrame>(packet.frames)) {
EXPECT_EQ(streamId, frame.streamId);
EXPECT_EQ(0, frame.offset);
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, frame.errorCode);
for (auto& frame : packet.frames) {
auto rstFrame = frame.asRstStreamFrame();
if (!rstFrame) {
continue;
}
EXPECT_EQ(streamId, rstFrame->streamId);
EXPECT_EQ(0, rstFrame->offset);
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, rstFrame->errorCode);
rstFound = true;
}
EXPECT_TRUE(rstFound);
@@ -896,15 +914,20 @@ TEST_F(QuicTransportTest, StopSending) {
->packet;
EXPECT_EQ(14, packet.frames.size());
bool foundStopSending = false;
for (auto& simpleFrame : all_frames<QuicSimpleFrame>(packet.frames)) {
for (auto& frame : packet.frames) {
const QuicSimpleFrame* simpleFrame = frame.asQuicSimpleFrame();
if (!simpleFrame) {
continue;
}
folly::variant_match(
simpleFrame,
*simpleFrame,
[&](const StopSendingFrame& frame) {
EXPECT_EQ(streamId, frame.streamId);
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, frame.errorCode);
foundStopSending = true;
},
[&](auto&) {});
[&](auto&) {
});
}
EXPECT_TRUE(foundStopSending);
}
@@ -932,9 +955,13 @@ TEST_F(QuicTransportTest, SendPathChallenge) {
transport_->getConnectionState(), PacketNumberSpace::AppData)
->packet;
bool foundPathChallenge = false;
for (auto& simpleFrame : all_frames<QuicSimpleFrame>(packet.frames)) {
for (auto& frame : packet.frames) {
const QuicSimpleFrame* simpleFrame = frame.asQuicSimpleFrame();
if (!simpleFrame) {
continue;
}
folly::variant_match(
simpleFrame,
*simpleFrame,
[&](const PathChallengeFrame& frame) {
EXPECT_EQ(frame, pathChallenge);
foundPathChallenge = true;
@@ -1133,9 +1160,13 @@ TEST_F(QuicTransportTest, SendPathResponse) {
auto packet =
getLastOutstandingPacket(conn, PacketNumberSpace::AppData)->packet;
bool foundPathResponse = false;
for (auto& simpleFrame : all_frames<QuicSimpleFrame>(packet.frames)) {
for (auto& frame : packet.frames) {
const QuicSimpleFrame* simpleFrame = frame.asQuicSimpleFrame();
if (!simpleFrame) {
continue;
}
folly::variant_match(
simpleFrame,
*simpleFrame,
[&](const PathResponseFrame& frame) {
EXPECT_EQ(frame, pathResponse);
foundPathResponse = true;
@@ -1244,9 +1275,13 @@ TEST_F(QuicTransportTest, SendNewConnectionIdFrame) {
transport_->getConnectionState(), PacketNumberSpace::AppData)
->packet;
bool foundNewConnectionId = false;
for (auto& simpleFrame : all_frames<QuicSimpleFrame>(packet.frames)) {
for (auto& frame : packet.frames) {
const QuicSimpleFrame* simpleFrame = frame.asQuicSimpleFrame();
if (!simpleFrame) {
continue;
}
folly::variant_match(
simpleFrame,
*simpleFrame,
[&](const NewConnectionIdFrame& frame) {
EXPECT_EQ(frame, newConnId);
foundNewConnectionId = true;
@@ -1379,9 +1414,13 @@ TEST_F(QuicTransportTest, SendRetireConnectionIdFrame) {
transport_->getConnectionState(), PacketNumberSpace::AppData)
->packet;
bool foundRetireConnectionId = false;
for (auto& simpleFrame : all_frames<QuicSimpleFrame>(packet.frames)) {
for (auto& frame : packet.frames) {
const QuicSimpleFrame* simpleFrame = frame.asQuicSimpleFrame();
if (!simpleFrame) {
continue;
}
folly::variant_match(
simpleFrame,
*simpleFrame,
[&](const RetireConnectionIdFrame& frame) {
EXPECT_EQ(frame, retireConnId);
foundRetireConnectionId = true;
@@ -1500,10 +1539,14 @@ TEST_F(QuicTransportTest, RstWrittenStream) {
EXPECT_GE(packet.frames.size(), 1);
bool foundReset = false;
for (auto& frame : all_frames<RstStreamFrame>(packet.frames)) {
EXPECT_EQ(streamId, frame.streamId);
EXPECT_EQ(currentWriteOffset, frame.offset);
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, frame.errorCode);
for (auto& frame : packet.frames) {
auto rstStream = frame.asRstStreamFrame();
if (!rstStream) {
continue;
}
EXPECT_EQ(streamId, rstStream->streamId);
EXPECT_EQ(currentWriteOffset, rstStream->offset);
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, rstStream->errorCode);
foundReset = true;
}
EXPECT_TRUE(foundReset);
@@ -1530,9 +1573,13 @@ TEST_F(QuicTransportTest, RstStreamUDPWriteFailNonFatal) {
EXPECT_GE(packet.frames.size(), 1);
bool foundReset = false;
for (auto& frame : all_frames<RstStreamFrame>(packet.frames)) {
EXPECT_EQ(streamId, frame.streamId);
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, frame.errorCode);
for (auto& frame : packet.frames) {
auto rstStream = frame.asRstStreamFrame();
if (!rstStream) {
continue;
}
EXPECT_EQ(streamId, rstStream->streamId);
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, rstStream->errorCode);
foundReset = true;
}
EXPECT_TRUE(foundReset);
@@ -1596,10 +1643,14 @@ TEST_F(QuicTransportTest, WriteAfterSendRst) {
EXPECT_GE(packet.frames.size(), 1);
bool foundReset = false;
for (auto& frame : all_frames<RstStreamFrame>(packet.frames)) {
EXPECT_EQ(streamId, frame.streamId);
EXPECT_EQ(currentWriteOffset, frame.offset);
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, frame.errorCode);
for (auto& frame : packet.frames) {
auto rstFrame = frame.asRstStreamFrame();
if (!rstFrame) {
continue;
}
EXPECT_EQ(streamId, rstFrame->streamId);
EXPECT_EQ(currentWriteOffset, rstFrame->offset);
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, rstFrame->errorCode);
foundReset = true;
}
EXPECT_TRUE(foundReset);
@@ -1671,8 +1722,12 @@ TEST_F(QuicTransportTest, WriteWindowUpdate) {
getLastOutstandingPacket(conn, PacketNumberSpace::AppData)->packet;
EXPECT_GE(packet.frames.size(), 1);
bool connWindowFound = false;
for (auto& connWindowUpdate : all_frames<MaxDataFrame>(packet.frames)) {
EXPECT_EQ(100, connWindowUpdate.maximumData);
for (auto& frame : packet.frames) {
auto connWindowUpdate = frame.asMaxDataFrame();
if (!connWindowUpdate) {
continue;
}
EXPECT_EQ(100, connWindowUpdate->maximumData);
connWindowFound = true;
}
@@ -1702,7 +1757,7 @@ TEST_F(QuicTransportTest, WriteWindowUpdate) {
auto packet1 =
getLastOutstandingPacket(conn, PacketNumberSpace::AppData)->packet;
const MaxStreamDataFrame* streamWindowUpdate =
boost::get<MaxStreamDataFrame>(&packet1.frames.front());
packet1.frames.front().asMaxStreamDataFrame();
EXPECT_TRUE(streamWindowUpdate);
}
@@ -2278,7 +2333,7 @@ TEST_F(QuicTransportTest, WriteStreamFromMiddleOfMap) {
auto& packet = *getFirstOutstandingPacket(conn, PacketNumberSpace::AppData);
EXPECT_EQ(1, packet.packet.frames.size());
auto& frame = packet.packet.frames.front();
const WriteStreamFrame* streamFrame = boost::get<WriteStreamFrame>(&frame);
const WriteStreamFrame* streamFrame = frame.asWriteStreamFrame();
EXPECT_TRUE(streamFrame);
EXPECT_EQ(streamFrame->streamId, s1);
conn.outstandingPackets.clear();
@@ -2301,7 +2356,7 @@ TEST_F(QuicTransportTest, WriteStreamFromMiddleOfMap) {
auto& packet2 = *getFirstOutstandingPacket(conn, PacketNumberSpace::AppData);
EXPECT_EQ(1, packet2.packet.frames.size());
auto& frame2 = packet2.packet.frames.front();
const WriteStreamFrame* streamFrame2 = boost::get<WriteStreamFrame>(&frame2);
const WriteStreamFrame* streamFrame2 = frame2.asWriteStreamFrame();
EXPECT_TRUE(streamFrame2);
EXPECT_EQ(streamFrame2->streamId, s2);
conn.outstandingPackets.clear();
@@ -2324,10 +2379,10 @@ TEST_F(QuicTransportTest, WriteStreamFromMiddleOfMap) {
EXPECT_EQ(2, packet3.packet.frames.size());
auto& frame3 = packet3.packet.frames.front();
auto& frame4 = packet3.packet.frames.back();
const WriteStreamFrame* streamFrame3 = boost::get<WriteStreamFrame>(&frame3);
const WriteStreamFrame* streamFrame3 = frame3.asWriteStreamFrame();
EXPECT_TRUE(streamFrame3);
EXPECT_EQ(streamFrame3->streamId, s2);
const WriteStreamFrame* streamFrame4 = boost::get<WriteStreamFrame>(&frame4);
const WriteStreamFrame* streamFrame4 = frame4.asWriteStreamFrame();
EXPECT_TRUE(streamFrame4);
EXPECT_EQ(streamFrame4->streamId, s1);
transport_->close(folly::none);

View File

@@ -295,31 +295,36 @@ void QuicClientTransport::processPacketData(
// TODO: replace this with a better solution later.
cancelHandshakeCryptoStreamRetransmissions(*conn_->cryptoState);
}
folly::variant_match(
packetFrame,
[&](const WriteAckFrame& frame) {
switch (packetFrame.type()) {
case QuicWriteFrame::Type::WriteAckFrame_E: {
const WriteAckFrame& frame = *packetFrame.asWriteAckFrame();
DCHECK(!frame.ackBlocks.empty());
VLOG(4) << "Client received ack for largestAcked="
<< frame.ackBlocks.back().end << " " << *this;
commonAckVisitorForAckFrame(ackState, frame);
},
[&](const RstStreamFrame& frame) {
break;
}
case QuicWriteFrame::Type::RstStreamFrame_E: {
const RstStreamFrame& frame = *packetFrame.asRstStreamFrame();
VLOG(4) << "Client received ack for reset frame stream="
<< frame.streamId << " " << *this;
auto stream =
conn_->streamManager->getStream(frame.streamId);
auto stream = conn_->streamManager->getStream(frame.streamId);
if (stream) {
invokeStreamSendStateMachine(
*conn_, *stream, StreamEvents::RstAck(frame));
}
},
[&](const WriteStreamFrame& frame) {
break;
}
case QuicWriteFrame::Type::WriteStreamFrame_E: {
const WriteStreamFrame& frame =
*packetFrame.asWriteStreamFrame();
auto ackedStream =
conn_->streamManager->getStream(frame.streamId);
VLOG(4) << "Client got ack for stream=" << frame.streamId
<< " offset=" << frame.offset
<< " fin=" << frame.fin << " data=" << frame.len
<< " offset=" << frame.offset << " fin=" << frame.fin
<< " data=" << frame.len
<< " closed=" << (ackedStream == nullptr) << " "
<< *this;
if (ackedStream) {
@@ -328,18 +333,23 @@ void QuicClientTransport::processPacketData(
*ackedStream,
StreamEvents::AckStreamFrame(frame));
}
},
[&](const WriteCryptoFrame& frame) {
break;
}
case QuicWriteFrame::Type::WriteCryptoFrame_E: {
const WriteCryptoFrame& frame =
*packetFrame.asWriteCryptoFrame();
auto cryptoStream = getCryptoStream(
*conn_->cryptoState,
protectionTypeToEncryptionLevel(
outstandingProtectionType));
processCryptoStreamAck(
*cryptoStream, frame.offset, frame.len);
},
[&](const auto& /* frame */) {
// Ignore other frames.
});
break;
}
default:
// ignore other frames.
break;
}
},
markPacketLoss,
receiveTimePoint);

View File

@@ -167,6 +167,11 @@ class QuicClientTransport
void happyEyeballsConnAttemptDelayTimeoutExpired() noexcept;
void handleAckFrame(
const OutstandingPacket& outstandingPacket,
const QuicWriteFrame& packetFrame,
const ReadAckFrame&);
// From ClientHandshake::HandshakeCallback
void onNewCachedPsk(
fizz::client::NewCachedPsk& newCachedPsk) noexcept override;

View File

@@ -3934,12 +3934,11 @@ RegularQuicWritePacket* findPacketWithStream(
StreamId streamId) {
auto op = findOutstandingPacket(conn, [=](OutstandingPacket& packet) {
for (auto& frame : packet.packet.frames) {
bool tryPacket = folly::variant_match(
frame,
[streamId](WriteStreamFrame& streamFrame) {
return streamFrame.streamId == streamId;
},
[](auto&) { return false; });
bool tryPacket = false;
WriteStreamFrame* streamFrame = frame.asWriteStreamFrame();
if (streamFrame) {
tryPacket = streamFrame->streamId == streamId;
}
if (tryPacket) {
return true;
}

View File

@@ -53,9 +53,9 @@ folly::Optional<PacketEvent> PacketRebuilder::rebuildFromPacket(
iter != packet.packet.frames.cend();
iter++) {
const QuicWriteFrame& frame = *iter;
writeSuccess = folly::variant_match(
frame,
[&](const WriteAckFrame& ackFrame) {
switch (frame.type()) {
case QuicWriteFrame::Type::WriteAckFrame_E: {
const WriteAckFrame& ackFrame = *frame.asWriteAckFrame();
auto& packetHeader = builder_.getPacketHeader();
uint64_t ackDelayExponent =
(packetHeader.getHeaderForm() == HeaderForm::Long)
@@ -64,9 +64,11 @@ folly::Optional<PacketEvent> PacketRebuilder::rebuildFromPacket(
AckFrameMetaData meta(
ackFrame.ackBlocks, ackFrame.ackDelay, ackDelayExponent);
auto ackWriteResult = writeAckFrame(meta, builder_);
return ackWriteResult.hasValue();
},
[&](const WriteStreamFrame& streamFrame) {
writeSuccess = ackWriteResult.hasValue();
break;
}
case QuicWriteFrame::Type::WriteStreamFrame_E: {
const WriteStreamFrame& streamFrame = *frame.asWriteStreamFrame();
auto stream = conn_.streamManager->getStream(streamFrame.streamId);
if (stream && retransmittable(*stream)) {
auto streamData = cloneRetransmissionBuffer(streamFrame, stream);
@@ -83,17 +85,21 @@ folly::Optional<PacketEvent> PacketRebuilder::rebuildFromPacket(
if (ret) {
writeStreamFrameData(builder_, std::move(streamData), *dataLen);
notPureAck = true;
return true;
writeSuccess = true;
break;
}
return false;
writeSuccess = false;
break;
}
// If a stream is already Closed, we should not clone and resend this
// stream data. But should we abort the cloning of this packet and
// move on to the next packet? I'm gonna err on the aggressive side
// for now and call it success.
return true;
},
[&](const WriteCryptoFrame& cryptoFrame) {
writeSuccess = true;
break;
}
case QuicWriteFrame::Type::WriteCryptoFrame_E: {
const WriteCryptoFrame& cryptoFrame = *frame.asWriteCryptoFrame();
// initialStream and handshakeStream can only be in handshake packet,
// so they are not clonable
CHECK(!packet.isHandshake);
@@ -106,7 +112,8 @@ folly::Optional<PacketEvent> PacketRebuilder::rebuildFromPacket(
// No crypto data found to be cloned, just skip
if (!buf) {
return true;
writeSuccess = true;
break;
}
auto cryptoWriteResult =
writeCryptoFrame(cryptoFrame.offset, std::move(buf), builder_);
@@ -114,47 +121,60 @@ folly::Optional<PacketEvent> PacketRebuilder::rebuildFromPacket(
cryptoWriteResult->offset == cryptoFrame.offset &&
cryptoWriteResult->len == cryptoFrame.len;
notPureAck |= ret;
return ret;
},
[&](const MaxDataFrame&) {
writeSuccess = ret;
break;
}
case QuicWriteFrame::Type::MaxDataFrame_E: {
shouldWriteWindowUpdate = true;
auto ret = 0 != writeFrame(generateMaxDataFrame(conn_), builder_);
windowUpdateWritten |= ret;
notPureAck |= ret;
return true;
},
[&](const MaxStreamDataFrame& maxStreamDataFrame) {
writeSuccess = true;
break;
}
case QuicWriteFrame::Type::MaxStreamDataFrame_E: {
const MaxStreamDataFrame& maxStreamDataFrame =
*frame.asMaxStreamDataFrame();
auto stream =
conn_.streamManager->getStream(maxStreamDataFrame.streamId);
if (!stream || !stream->shouldSendFlowControl()) {
return true;
writeSuccess = true;
break;
}
shouldWriteWindowUpdate = true;
auto ret =
0 != writeFrame(generateMaxStreamDataFrame(*stream), builder_);
windowUpdateWritten |= ret;
notPureAck |= ret;
return true;
},
[&](const PaddingFrame& paddingFrame) {
return writeFrame(paddingFrame, builder_) != 0;
},
[&](const QuicSimpleFrame& simpleFrame) {
writeSuccess = true;
break;
}
case QuicWriteFrame::Type::PaddingFrame_E: {
const PaddingFrame& paddingFrame = *frame.asPaddingFrame();
writeSuccess = writeFrame(paddingFrame, builder_) != 0;
break;
}
case QuicWriteFrame::Type::QuicSimpleFrame_E: {
const QuicSimpleFrame& simpleFrame = *frame.asQuicSimpleFrame();
auto updatedSimpleFrame =
updateSimpleFrameOnPacketClone(conn_, simpleFrame);
if (!updatedSimpleFrame) {
return true;
writeSuccess = true;
break;
}
bool ret =
writeSimpleFrame(std::move(*updatedSimpleFrame), builder_) != 0;
notPureAck |= ret;
return ret;
},
[&](const auto& otherFrame) {
bool ret = writeFrame(otherFrame, builder_) != 0;
writeSuccess = ret;
break;
}
default: {
bool ret = writeFrame(QuicWriteFrame(frame), builder_) != 0;
notPureAck |= ret;
return ret;
});
writeSuccess = ret;
break;
}
}
if (!writeSuccess) {
return folly::none;
}

View File

@@ -339,7 +339,7 @@ size_t writeSimpleFrame(
} else {
builder.write(errorCode);
}
builder.appendFrame(std::move(stopSendingFrame));
builder.appendFrame(QuicSimpleFrame(std::move(stopSendingFrame)));
return stopSendingFrameSize;
}
// no space left in packet
@@ -358,7 +358,7 @@ size_t writeSimpleFrame(
builder.write(streamId);
builder.write(maximumData);
builder.write(minimumStreamOffset);
builder.appendFrame(std::move(minStreamDataFrame));
builder.appendFrame(QuicSimpleFrame(std::move(minStreamDataFrame)));
return minStreamDataFrameSize;
}
// no space left in packet
@@ -376,7 +376,8 @@ size_t writeSimpleFrame(
builder.write(frameType);
builder.write(streamId);
builder.write(minimumStreamOffset);
builder.appendFrame(std::move(expiredStreamDataFrame));
builder.appendFrame(
QuicSimpleFrame(std::move(expiredStreamDataFrame)));
return expiredStreamDataFrameSize;
}
// no space left in packet
@@ -389,7 +390,7 @@ size_t writeSimpleFrame(
if (packetSpaceCheck(spaceLeft, pathChallengeFrameSize)) {
builder.write(frameType);
builder.writeBE(pathChallengeFrame.pathData);
builder.appendFrame(std::move(pathChallengeFrame));
builder.appendFrame(QuicSimpleFrame(std::move(pathChallengeFrame)));
return pathChallengeFrameSize;
}
// no space left in packet
@@ -402,7 +403,7 @@ size_t writeSimpleFrame(
if (packetSpaceCheck(spaceLeft, pathResponseFrameSize)) {
builder.write(frameType);
builder.writeBE(pathResponseFrame.pathData);
builder.appendFrame(std::move(pathResponseFrame));
builder.appendFrame(QuicSimpleFrame(std::move(pathResponseFrame)));
return pathResponseFrameSize;
}
// no space left in packet
@@ -429,7 +430,7 @@ size_t writeSimpleFrame(
builder.push(
newConnectionIdFrame.token.data(),
newConnectionIdFrame.token.size());
builder.appendFrame(std::move(newConnectionIdFrame));
builder.appendFrame(QuicSimpleFrame(std::move(newConnectionIdFrame)));
return newConnectionIdFrameSize;
}
// no space left in packet
@@ -446,7 +447,7 @@ size_t writeSimpleFrame(
if (packetSpaceCheck(spaceLeft, maxStreamsFrameSize)) {
builder.write(intFrameType);
builder.write(streamCount);
builder.appendFrame(maxStreamsFrame);
builder.appendFrame(QuicSimpleFrame(maxStreamsFrame));
return maxStreamsFrameSize;
}
return size_t(0);
@@ -460,7 +461,7 @@ size_t writeSimpleFrame(
if (packetSpaceCheck(spaceLeft, retireConnectionIdFrameSize)) {
builder.write(frameType);
builder.write(sequence);
builder.appendFrame(retireConnectionIdFrame);
builder.appendFrame(QuicSimpleFrame(retireConnectionIdFrame));
return retireConnectionIdFrameSize;
}
// no space left in packet
@@ -473,9 +474,9 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
uint64_t spaceLeft = builder.remainingSpaceInPkt();
return folly::variant_match(
frame,
[&](PaddingFrame& paddingFrame) {
switch (frame.type()) {
case QuicWriteFrame::Type::PaddingFrame_E: {
PaddingFrame& paddingFrame = *frame.asPaddingFrame();
QuicInteger intFrameType(static_cast<uint8_t>(FrameType::PADDING));
if (packetSpaceCheck(spaceLeft, intFrameType.getSize())) {
builder.write(intFrameType);
@@ -483,8 +484,9 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
return intFrameType.getSize();
}
return size_t(0);
},
[&](PingFrame& pingFrame) {
}
case QuicWriteFrame::Type::PingFrame_E: {
PingFrame& pingFrame = *frame.asPingFrame();
QuicInteger intFrameType(static_cast<uint8_t>(FrameType::PING));
if (packetSpaceCheck(spaceLeft, intFrameType.getSize())) {
builder.write(intFrameType);
@@ -493,8 +495,9 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
}
// no space left in packet
return size_t(0);
},
[&](RstStreamFrame& rstStreamFrame) {
}
case QuicWriteFrame::Type::RstStreamFrame_E: {
RstStreamFrame& rstStreamFrame = *frame.asRstStreamFrame();
QuicInteger intFrameType(static_cast<uint8_t>(FrameType::RST_STREAM));
QuicInteger streamId(rstStreamFrame.streamId);
QuicInteger offset(rstStreamFrame.offset);
@@ -520,8 +523,9 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
}
// no space left in packet
return size_t(0);
},
[&](MaxDataFrame& maxDataFrame) {
}
case QuicWriteFrame::Type::MaxDataFrame_E: {
MaxDataFrame& maxDataFrame = *frame.asMaxDataFrame();
QuicInteger intFrameType(static_cast<uint8_t>(FrameType::MAX_DATA));
QuicInteger maximumData(maxDataFrame.maximumData);
auto frameSize = intFrameType.getSize() + maximumData.getSize();
@@ -533,8 +537,9 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
}
// no space left in packet
return size_t(0);
},
[&](MaxStreamDataFrame& maxStreamDataFrame) {
}
case QuicWriteFrame::Type::MaxStreamDataFrame_E: {
MaxStreamDataFrame& maxStreamDataFrame = *frame.asMaxStreamDataFrame();
QuicInteger intFrameType(
static_cast<uint8_t>(FrameType::MAX_STREAM_DATA));
QuicInteger streamId(maxStreamDataFrame.streamId);
@@ -550,8 +555,9 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
}
// no space left in packet
return size_t(0);
},
[&](DataBlockedFrame& blockedFrame) {
}
case QuicWriteFrame::Type::DataBlockedFrame_E: {
DataBlockedFrame& blockedFrame = *frame.asDataBlockedFrame();
QuicInteger intFrameType(static_cast<uint8_t>(FrameType::DATA_BLOCKED));
QuicInteger dataLimit(blockedFrame.dataLimit);
auto blockedFrameSize = intFrameType.getSize() + dataLimit.getSize();
@@ -563,8 +569,10 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
}
// no space left in packet
return size_t(0);
},
[&](StreamDataBlockedFrame& streamBlockedFrame) {
}
case QuicWriteFrame::Type::StreamDataBlockedFrame_E: {
StreamDataBlockedFrame& streamBlockedFrame =
*frame.asStreamDataBlockedFrame();
QuicInteger intFrameType(
static_cast<uint8_t>(FrameType::STREAM_DATA_BLOCKED));
QuicInteger streamId(streamBlockedFrame.streamId);
@@ -580,15 +588,15 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
}
// no space left in packet
return size_t(0);
},
[&](StreamsBlockedFrame& streamsBlockedFrame) {
}
case QuicWriteFrame::Type::StreamsBlockedFrame_E: {
StreamsBlockedFrame& streamsBlockedFrame = *frame.asStreamsBlockedFrame();
auto frameType = streamsBlockedFrame.isForBidirectionalStream()
? FrameType::STREAMS_BLOCKED_BIDI
: FrameType::STREAMS_BLOCKED_UNI;
QuicInteger intFrameType(static_cast<FrameTypeType>(frameType));
QuicInteger streamId(streamsBlockedFrame.streamLimit);
auto streamBlockedFrameSize =
intFrameType.getSize() + streamId.getSize();
auto streamBlockedFrameSize = intFrameType.getSize() + streamId.getSize();
if (packetSpaceCheck(spaceLeft, streamBlockedFrameSize)) {
builder.write(intFrameType);
builder.write(streamId);
@@ -597,8 +605,10 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
}
// no space left in packet
return size_t(0);
},
[&](ConnectionCloseFrame& connectionCloseFrame) {
}
case QuicWriteFrame::Type::ConnectionCloseFrame_E: {
ConnectionCloseFrame& connectionCloseFrame =
*frame.asConnectionCloseFrame();
QuicInteger intFrameType(
static_cast<uint8_t>(FrameType::CONNECTION_CLOSE));
QuicInteger reasonLength(connectionCloseFrame.reasonPhrase.size());
@@ -632,8 +642,10 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
}
// no space left in packet
return size_t(0);
},
[&](ApplicationCloseFrame& applicationCloseFrame) {
}
case QuicWriteFrame::Type::ApplicationCloseFrame_E: {
ApplicationCloseFrame& applicationCloseFrame =
*frame.asApplicationCloseFrame();
QuicInteger intFrameType(
static_cast<uint8_t>(FrameType::APPLICATION_CLOSE));
QuicInteger reasonLength(applicationCloseFrame.reasonPhrase.size());
@@ -662,17 +674,18 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
}
// no space left in packet
return size_t(0);
},
[&](QuicSimpleFrame& simpleFrame) {
return writeSimpleFrame(std::move(simpleFrame), builder);
},
[&](auto&) -> size_t {
}
case QuicWriteFrame::Type::QuicSimpleFrame_E: {
return writeSimpleFrame(std::move(*frame.asQuicSimpleFrame()), builder);
}
default: {
// TODO add support for: RETIRE_CONNECTION_ID and NEW_TOKEN frames
auto errorStr = folly::to<std::string>(
"Unknown / unsupported frame type received at ", __func__);
VLOG(2) << errorStr;
throw QuicTransportException(
errorStr, TransportErrorCode::FRAME_ENCODING_ERROR);
});
}
}
}
} // namespace quic

View File

@@ -592,22 +592,25 @@ using QuicSimpleFrame = boost::variant<
DECLARE_VARIANT_TYPE(QuicFrame, QUIC_FRAME)
#define QUIC_WRITE_FRAME(F, ...) \
F(PaddingFrame, __VA_ARGS__) \
F(RstStreamFrame, __VA_ARGS__) \
F(ConnectionCloseFrame, __VA_ARGS__) \
F(ApplicationCloseFrame, __VA_ARGS__) \
F(MaxDataFrame, __VA_ARGS__) \
F(MaxStreamDataFrame, __VA_ARGS__) \
F(PingFrame, __VA_ARGS__) \
F(DataBlockedFrame, __VA_ARGS__) \
F(StreamDataBlockedFrame, __VA_ARGS__) \
F(StreamsBlockedFrame, __VA_ARGS__) \
F(WriteAckFrame, __VA_ARGS__) \
F(WriteStreamFrame, __VA_ARGS__) \
F(WriteCryptoFrame, __VA_ARGS__) \
F(QuicSimpleFrame, __VA_ARGS__) \
F(NoopFrame, __VA_ARGS__)
// Types of frames which are written.
using QuicWriteFrame = boost::variant<
PaddingFrame,
RstStreamFrame,
ConnectionCloseFrame,
ApplicationCloseFrame,
MaxDataFrame,
MaxStreamDataFrame,
PingFrame,
DataBlockedFrame,
StreamDataBlockedFrame,
StreamsBlockedFrame,
WriteAckFrame,
WriteStreamFrame,
WriteCryptoFrame,
QuicSimpleFrame>;
DECLARE_VARIANT_TYPE(QuicWriteFrame, QUIC_WRITE_FRAME)
enum class HeaderForm : bool {
Long = 1,

View File

@@ -80,7 +80,7 @@ TEST_F(QuicPacketRebuilderTest, RebuildPacket) {
// Write them with a regular builder
writeFrame(connCloseFrame, regularBuilder1);
writeFrame(maxStreamsFrame, regularBuilder1);
writeFrame(QuicSimpleFrame(maxStreamsFrame), regularBuilder1);
writeFrame(pingFrame, regularBuilder1);
writeAckFrame(ackMeta, regularBuilder1);
writeStreamFrameHeader(
@@ -123,44 +123,61 @@ TEST_F(QuicPacketRebuilderTest, RebuildPacket) {
stream->currentReadOffset + stream->flowControlState.windowSize,
stream->flowControlState.advertisedMaxOffset);
for (const auto& frame : packet2.packet.frames) {
folly::variant_match(
frame,
[](const ConnectionCloseFrame& closeFrame) {
switch (frame.type()) {
case QuicWriteFrame::Type::ConnectionCloseFrame_E: {
const ConnectionCloseFrame& closeFrame =
*frame.asConnectionCloseFrame();
EXPECT_EQ(
TransportErrorCode::FRAME_ENCODING_ERROR, closeFrame.errorCode);
EXPECT_EQ("The sun is in the sky.", closeFrame.reasonPhrase);
EXPECT_EQ(FrameType::ACK, closeFrame.closingFrameType);
},
[](const QuicSimpleFrame& simpleFrame) {
break;
}
case QuicWriteFrame::Type::QuicSimpleFrame_E: {
const QuicSimpleFrame& simpleFrame = *frame.asQuicSimpleFrame();
auto maxStreamFrame = boost::get<MaxStreamsFrame>(simpleFrame);
EXPECT_EQ(4321, maxStreamFrame.maxStreams);
},
[](const PingFrame& ping) { EXPECT_EQ(PingFrame(), ping); },
[](const WriteAckFrame& ack) {
break;
}
case QuicWriteFrame::Type::PingFrame_E: {
const PingFrame& ping = *frame.asPingFrame();
EXPECT_EQ(PingFrame(), ping);
break;
}
case QuicWriteFrame::Type::WriteAckFrame_E: {
const WriteAckFrame& ack = *frame.asWriteAckFrame();
EXPECT_EQ(Interval<PacketNum>(10, 100), ack.ackBlocks.front());
EXPECT_EQ(Interval<PacketNum>(200, 1000), ack.ackBlocks.back());
},
[&buf, &streamId](const WriteStreamFrame& streamFrame) {
break;
}
case QuicWriteFrame::Type::WriteStreamFrame_E: {
const WriteStreamFrame& streamFrame = *frame.asWriteStreamFrame();
EXPECT_EQ(streamId, streamFrame.streamId);
EXPECT_EQ(0, streamFrame.offset);
EXPECT_EQ(buf->computeChainDataLength(), streamFrame.len);
EXPECT_EQ(true, streamFrame.fin);
},
[&cryptoOffset, &cryptoBuf](const WriteCryptoFrame& frame) {
EXPECT_EQ(frame.offset, cryptoOffset);
EXPECT_EQ(frame.len, cryptoBuf->computeChainDataLength());
},
[&expectedConnFlowControlValue](const MaxDataFrame& maxData) {
break;
}
case QuicWriteFrame::Type::WriteCryptoFrame_E: {
const WriteCryptoFrame& cryptoFrame = *frame.asWriteCryptoFrame();
EXPECT_EQ(cryptoFrame.offset, cryptoOffset);
EXPECT_EQ(cryptoFrame.len, cryptoBuf->computeChainDataLength());
break;
}
case QuicWriteFrame::Type::MaxDataFrame_E: {
const MaxDataFrame& maxData = *frame.asMaxDataFrame();
EXPECT_EQ(expectedConnFlowControlValue, maxData.maximumData);
},
[&streamId, &expectedStreamFlowControlValue](
const MaxStreamDataFrame& maxStreamData) {
break;
}
case QuicWriteFrame::Type::MaxStreamDataFrame_E: {
const MaxStreamDataFrame& maxStreamData = *frame.asMaxStreamDataFrame();
EXPECT_EQ(streamId, maxStreamData.streamId);
EXPECT_EQ(expectedStreamFlowControlValue, maxStreamData.maximumData);
},
[](const auto&) {
break;
}
default:
EXPECT_TRUE(false); /* should never happen*/
});
}
}
EXPECT_TRUE(folly::IOBufEqualTo()(*packet1.header, *packet2.header));
// TODO: I don't have a good way to verify body without decode them
@@ -286,17 +303,14 @@ TEST_F(QuicPacketRebuilderTest, RebuildDataStreamAndEmptyCryptoStream) {
// rebuilder writes frames to regularBuilder2
EXPECT_EQ(packet1.packet.frames.size(), packet2.packet.frames.size() + 1);
for (const auto& frame : packet2.packet.frames) {
folly::variant_match(
frame,
[&buf, &streamId](const WriteStreamFrame& streamFrame) {
EXPECT_EQ(streamId, streamFrame.streamId);
EXPECT_EQ(0, streamFrame.offset);
EXPECT_EQ(buf->computeChainDataLength(), streamFrame.len);
EXPECT_EQ(true, streamFrame.fin);
},
[](const auto&) {
const WriteStreamFrame* streamFrame = frame.asWriteStreamFrame();
if (!streamFrame) {
EXPECT_TRUE(false); /* should never happen*/
});
}
EXPECT_EQ(streamId, streamFrame->streamId);
EXPECT_EQ(0, streamFrame->offset);
EXPECT_EQ(buf->computeChainDataLength(), streamFrame->len);
EXPECT_EQ(true, streamFrame->fin);
}
EXPECT_TRUE(folly::IOBufEqualTo()(*packet1.header, *packet2.header));
}

View File

@@ -127,7 +127,7 @@ TEST_F(QuicWriteCodecTest, WriteStreamFrameToEmptyPacket) {
auto regularPacket = std::move(builtOut.first);
EXPECT_EQ(regularPacket.frames.size(), 1);
auto resultFrame = boost::get<WriteStreamFrame>(regularPacket.frames.back());
auto& resultFrame = *regularPacket.frames.back().asWriteStreamFrame();
EXPECT_EQ(resultFrame.streamId, streamId);
EXPECT_EQ(resultFrame.offset, offset);
EXPECT_EQ(resultFrame.len, 10);
@@ -174,7 +174,7 @@ TEST_F(QuicWriteCodecTest, WriteStreamFrameToPartialPacket) {
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = std::move(builtOut.first);
EXPECT_EQ(regularPacket.frames.size(), 1);
auto resultFrame = boost::get<WriteStreamFrame>(regularPacket.frames.back());
auto& resultFrame = *regularPacket.frames.back().asWriteStreamFrame();
EXPECT_EQ(resultFrame.streamId, streamId);
EXPECT_EQ(resultFrame.offset, offset);
EXPECT_EQ(resultFrame.len, 20);
@@ -241,14 +241,14 @@ TEST_F(QuicWriteCodecTest, WriteTwoStreamFrames) {
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = std::move(builtOut.first);
EXPECT_EQ(regularPacket.frames.size(), 2);
auto resultFrame = boost::get<WriteStreamFrame>(regularPacket.frames.front());
auto& resultFrame = *regularPacket.frames.front().asWriteStreamFrame();
EXPECT_EQ(resultFrame.streamId, streamId1);
EXPECT_EQ(resultFrame.offset, offset1);
EXPECT_EQ(resultFrame.len, 30);
outputBuf->trimStart(8);
EXPECT_TRUE(folly::IOBufEqualTo()(inputBuf, outputBuf));
auto resultFrame2 = boost::get<WriteStreamFrame>(regularPacket.frames.back());
auto& resultFrame2 = *regularPacket.frames.back().asWriteStreamFrame();
EXPECT_EQ(resultFrame2.streamId, streamId2);
EXPECT_EQ(resultFrame2.offset, offset2);
EXPECT_EQ(resultFrame2.len, remainingSpace - 7);
@@ -307,7 +307,7 @@ TEST_F(QuicWriteCodecTest, WriteStreamFramePartialData) {
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(regularPacket.frames.size(), 1);
auto resultFrame = boost::get<WriteStreamFrame>(regularPacket.frames.back());
auto& resultFrame = *regularPacket.frames.back().asWriteStreamFrame();
EXPECT_EQ(resultFrame.streamId, streamId);
EXPECT_EQ(resultFrame.offset, offset);
EXPECT_EQ(resultFrame.len, 33);
@@ -385,7 +385,7 @@ TEST_F(QuicWriteCodecTest, WriteStreamSpaceForOneByte) {
auto regularPacket = builtOut.first;
EXPECT_EQ(regularPacket.frames.size(), 1);
auto resultFrame = boost::get<WriteStreamFrame>(regularPacket.frames.back());
auto& resultFrame = *regularPacket.frames.back().asWriteStreamFrame();
EXPECT_EQ(resultFrame.streamId, streamId);
EXPECT_EQ(resultFrame.offset, offset);
EXPECT_EQ(resultFrame.len, 1);
@@ -430,7 +430,7 @@ TEST_F(QuicWriteCodecTest, WriteFinToEmptyPacket) {
auto regularPacket = builtOut.first;
EXPECT_EQ(regularPacket.frames.size(), 1);
auto resultFrame = boost::get<WriteStreamFrame>(regularPacket.frames.back());
auto& resultFrame = *regularPacket.frames.back().asWriteStreamFrame();
EXPECT_EQ(resultFrame.streamId, streamId);
EXPECT_EQ(resultFrame.offset, offset);
EXPECT_EQ(inputBuf->computeChainDataLength(), resultFrame.len);
@@ -592,8 +592,7 @@ TEST_F(QuicWriteCodecTest, AckFrameVeryLargeAckRange) {
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(regularPacket.frames.size(), 1);
WriteAckFrame ackFrame =
boost::get<WriteAckFrame>(regularPacket.frames.back());
WriteAckFrame& ackFrame = *regularPacket.frames.back().asWriteAckFrame();
EXPECT_EQ(ackFrame.ackBlocks.size(), 1);
EXPECT_EQ(ackFrame.ackBlocks.front().start, 1);
@@ -640,8 +639,7 @@ TEST_F(QuicWriteCodecTest, WriteSimpleAckFrame) {
EXPECT_EQ(kDefaultUDPSendPacketLen - 11, pktBuilder.remainingSpaceInPkt());
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
WriteAckFrame ackFrame =
boost::get<WriteAckFrame>(regularPacket.frames.back());
WriteAckFrame& ackFrame = *regularPacket.frames.back().asWriteAckFrame();
EXPECT_EQ(ackFrame.ackBlocks.size(), 2);
auto iter = ackFrame.ackBlocks.cbegin();
EXPECT_EQ(iter->start, 101);
@@ -675,8 +673,7 @@ TEST_F(QuicWriteCodecTest, WriteAckFrameWillSaveAckDelay) {
writeAckFrame(meta, pktBuilder);
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
WriteAckFrame ackFrame =
boost::get<WriteAckFrame>(regularPacket.frames.back());
WriteAckFrame& ackFrame = *regularPacket.frames.back().asWriteAckFrame();
EXPECT_EQ(ackDelay, ackFrame.ackDelay);
}
@@ -714,8 +711,7 @@ TEST_F(QuicWriteCodecTest, VerifyNumAckBlocksSizeAccounted) {
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(regularPacket.frames.size(), 1);
WriteAckFrame ackFrame =
boost::get<WriteAckFrame>(regularPacket.frames.back());
WriteAckFrame& ackFrame = *regularPacket.frames.back().asWriteAckFrame();
EXPECT_EQ(ackFrame.ackBlocks.size(), 64);
EXPECT_EQ(ackFrame.ackBlocks.front().start, 746);
@@ -787,8 +783,7 @@ TEST_F(QuicWriteCodecTest, OnlyAckLargestPacket) {
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(regularPacket.frames.size(), 1);
WriteAckFrame ackFrame =
boost::get<WriteAckFrame>(regularPacket.frames.back());
WriteAckFrame& ackFrame = *regularPacket.frames.back().asWriteAckFrame();
EXPECT_EQ(ackFrame.ackBlocks.size(), 1);
EXPECT_EQ(ackFrame.ackBlocks.front().start, 1000);
EXPECT_EQ(ackFrame.ackBlocks.front().end, 1000);
@@ -838,8 +833,7 @@ TEST_F(QuicWriteCodecTest, WriteSomeAckBlocks) {
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(regularPacket.frames.size(), 1);
WriteAckFrame ackFrame =
boost::get<WriteAckFrame>(regularPacket.frames.back());
WriteAckFrame& ackFrame = *regularPacket.frames.back().asWriteAckFrame();
EXPECT_EQ(ackFrame.ackBlocks.size(), 14);
// Verify the on wire bytes via decoder:
@@ -886,8 +880,7 @@ TEST_F(QuicWriteCodecTest, OnlyHasSpaceForFirstAckBlock) {
EXPECT_EQ(ackFrameWriteResult.bytesWritten, 7);
EXPECT_EQ(pktBuilder.remainingSpaceInPkt(), 3);
auto builtOut = std::move(pktBuilder).buildPacket();
WriteAckFrame ackFrame =
boost::get<WriteAckFrame>(builtOut.first.frames.back());
WriteAckFrame& ackFrame = *builtOut.first.frames.back().asWriteAckFrame();
EXPECT_EQ(ackFrame.ackBlocks.size(), 1);
EXPECT_EQ(ackFrame.ackBlocks.front().start, 1000);
EXPECT_EQ(ackFrame.ackBlocks.front().end, 1000);
@@ -917,7 +910,7 @@ TEST_F(QuicWriteCodecTest, WriteMaxStreamData) {
auto regularPacket = builtOut.first;
EXPECT_EQ(bytesWritten, 3);
auto& resultMaxStreamDataFrame =
boost::get<MaxStreamDataFrame>(regularPacket.frames[0]);
*regularPacket.frames[0].asMaxStreamDataFrame();
EXPECT_EQ(id, resultMaxStreamDataFrame.streamId);
EXPECT_EQ(offset, resultMaxStreamDataFrame.maximumData);
@@ -949,7 +942,7 @@ TEST_F(QuicWriteCodecTest, WriteMaxData) {
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(bytesWritten, 3);
auto& resultMaxDataFrame = boost::get<MaxDataFrame>(regularPacket.frames[0]);
auto& resultMaxDataFrame = *regularPacket.frames[0].asMaxDataFrame();
EXPECT_EQ(1000, resultMaxDataFrame.maximumData);
auto wireBuf = std::move(builtOut.second);
@@ -975,7 +968,8 @@ TEST_F(QuicWriteCodecTest, WriteMaxStreamId) {
uint64_t maxStream = i;
bool isBidirectional = true;
MaxStreamsFrame maxStreamsFrame(maxStream, isBidirectional);
auto bytesWritten = writeFrame(maxStreamsFrame, pktBuilder);
auto bytesWritten =
writeFrame(QuicSimpleFrame(maxStreamsFrame), pktBuilder);
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
@@ -983,7 +977,7 @@ TEST_F(QuicWriteCodecTest, WriteMaxStreamId) {
// 1 byte for the type and up to 2 bytes for the stream count.
EXPECT_EQ(1 + streamCountSize, bytesWritten);
auto& resultMaxStreamIdFrame = boost::get<MaxStreamsFrame>(
boost::get<QuicSimpleFrame>(regularPacket.frames[0]));
*regularPacket.frames[0].asQuicSimpleFrame());
EXPECT_EQ(i, resultMaxStreamIdFrame.maxStreams);
auto wireBuf = std::move(builtOut.second);
@@ -1003,7 +997,8 @@ TEST_F(QuicWriteCodecTest, WriteUniMaxStreamId) {
uint64_t maxStream = i;
bool isBidirectional = false;
MaxStreamsFrame maxStreamsFrame(maxStream, isBidirectional);
auto bytesWritten = writeFrame(maxStreamsFrame, pktBuilder);
auto bytesWritten =
writeFrame(QuicSimpleFrame(maxStreamsFrame), pktBuilder);
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
@@ -1011,7 +1006,7 @@ TEST_F(QuicWriteCodecTest, WriteUniMaxStreamId) {
// 1 byte for the type and up to 2 bytes for the stream count.
EXPECT_EQ(1 + streamCountSize, bytesWritten);
auto& resultMaxStreamIdFrame = boost::get<MaxStreamsFrame>(
boost::get<QuicSimpleFrame>(regularPacket.frames[0]));
*regularPacket.frames[0].asQuicSimpleFrame());
EXPECT_EQ(i, resultMaxStreamIdFrame.maxStreams);
auto wireBuf = std::move(builtOut.second);
@@ -1030,7 +1025,7 @@ TEST_F(QuicWriteCodecTest, NoSpaceForMaxStreamId) {
setupCommonExpects(pktBuilder);
StreamId maxStream = 0x1234;
MaxStreamsFrame maxStreamIdFrame(maxStream, true);
EXPECT_EQ(0, writeFrame(maxStreamIdFrame, pktBuilder));
EXPECT_EQ(0, writeFrame(QuicSimpleFrame(maxStreamIdFrame), pktBuilder));
}
TEST_F(QuicWriteCodecTest, WriteConnClose) {
@@ -1039,14 +1034,15 @@ TEST_F(QuicWriteCodecTest, WriteConnClose) {
std::string reasonPhrase("You are fired");
ConnectionCloseFrame connectionCloseFrame(
TransportErrorCode::PROTOCOL_VIOLATION, reasonPhrase);
auto connCloseBytesWritten = writeFrame(connectionCloseFrame, pktBuilder);
auto connCloseBytesWritten =
writeFrame(std::move(connectionCloseFrame), pktBuilder);
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
// 6 == ErrorCode(2) + FrameType(1) + reasonPhrase-len(2)
EXPECT_EQ(4 + reasonPhrase.size(), connCloseBytesWritten);
auto& resultConnCloseFrame =
boost::get<ConnectionCloseFrame>(regularPacket.frames[0]);
*regularPacket.frames[0].asConnectionCloseFrame();
EXPECT_EQ(
TransportErrorCode::PROTOCOL_VIOLATION, resultConnCloseFrame.errorCode);
EXPECT_EQ("You are fired", resultConnCloseFrame.reasonPhrase);
@@ -1074,7 +1070,7 @@ TEST_F(QuicWriteCodecTest, DecodeConnCloseLarge) {
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
auto& resultConnCloseFrame =
boost::get<ConnectionCloseFrame>(regularPacket.frames[0]);
*regularPacket.frames[0].asConnectionCloseFrame();
EXPECT_EQ(
TransportErrorCode::PROTOCOL_VIOLATION, resultConnCloseFrame.errorCode);
EXPECT_EQ(resultConnCloseFrame.reasonPhrase, reasonPhrase);
@@ -1091,7 +1087,7 @@ TEST_F(QuicWriteCodecTest, NoSpaceConnClose) {
std::string reasonPhrase("You are all fired");
ConnectionCloseFrame connCloseFrame(
TransportErrorCode::PROTOCOL_VIOLATION, reasonPhrase);
EXPECT_EQ(0, writeFrame(connCloseFrame, pktBuilder));
EXPECT_EQ(0, writeFrame(std::move(connCloseFrame), pktBuilder));
}
TEST_F(QuicWriteCodecTest, DecodeAppCloseLarge) {
@@ -1101,12 +1097,12 @@ TEST_F(QuicWriteCodecTest, DecodeAppCloseLarge) {
reasonPhrase.resize(kMaxReasonPhraseLength + 10);
ApplicationCloseFrame applicationCloseFrame(
GenericApplicationErrorCode::UNKNOWN, reasonPhrase);
writeFrame(applicationCloseFrame, pktBuilder);
writeFrame(std::move(applicationCloseFrame), pktBuilder);
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
auto& resultAppCloseFrame =
boost::get<ApplicationCloseFrame>(regularPacket.frames[0]);
*regularPacket.frames[0].asApplicationCloseFrame();
EXPECT_EQ(
GenericApplicationErrorCode::UNKNOWN, resultAppCloseFrame.errorCode);
EXPECT_EQ(resultAppCloseFrame.reasonPhrase, reasonPhrase);
@@ -1119,13 +1115,12 @@ TEST_F(QuicWriteCodecTest, DecodeAppCloseLarge) {
TEST_F(QuicWriteCodecTest, WritePing) {
MockQuicPacketBuilder pktBuilder;
setupCommonExpects(pktBuilder);
PingFrame pingFrame;
auto pingBytesWritten = writeFrame(pingFrame, pktBuilder);
auto pingBytesWritten = writeFrame(PingFrame(), pktBuilder);
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(1, pingBytesWritten);
EXPECT_NO_THROW(boost::get<PingFrame>(regularPacket.frames[0]));
EXPECT_NE(regularPacket.frames[0].asPingFrame(), nullptr);
auto wireBuf = std::move(builtOut.second);
folly::io::Cursor cursor(wireBuf.get());
@@ -1140,20 +1135,18 @@ TEST_F(QuicWriteCodecTest, NoSpaceForPing) {
MockQuicPacketBuilder pktBuilder;
pktBuilder.remaining_ = 0;
setupCommonExpects(pktBuilder);
PingFrame pingFrame;
EXPECT_EQ(0, writeFrame(pingFrame, pktBuilder));
EXPECT_EQ(0, writeFrame(PingFrame(), pktBuilder));
}
TEST_F(QuicWriteCodecTest, WritePadding) {
MockQuicPacketBuilder pktBuilder;
setupCommonExpects(pktBuilder);
PaddingFrame paddingFrame;
auto paddingBytesWritten = writeFrame(paddingFrame, pktBuilder);
auto paddingBytesWritten = writeFrame(PaddingFrame(), pktBuilder);
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(1, paddingBytesWritten);
EXPECT_NO_THROW(boost::get<PaddingFrame>(regularPacket.frames[0]));
EXPECT_NE(regularPacket.frames[0].asPaddingFrame(), nullptr);
auto wireBuf = std::move(builtOut.second);
folly::io::Cursor cursor(wireBuf.get());
@@ -1183,7 +1176,7 @@ TEST_F(QuicWriteCodecTest, WriteStreamBlocked) {
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(blockedBytesWritten, 7);
EXPECT_NO_THROW(boost::get<StreamDataBlockedFrame>(regularPacket.frames[0]));
EXPECT_NE(regularPacket.frames[0].asStreamDataBlockedFrame(), nullptr);
auto wireBuf = std::move(builtOut.second);
folly::io::Cursor cursor(wireBuf.get());
@@ -1217,8 +1210,7 @@ TEST_F(QuicWriteCodecTest, WriteRstStream) {
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(13, rstStreamBytesWritten);
auto& resultRstStreamFrame =
boost::get<RstStreamFrame>(regularPacket.frames[0]);
auto& resultRstStreamFrame = *regularPacket.frames[0].asRstStreamFrame();
EXPECT_EQ(errorCode, resultRstStreamFrame.errorCode);
EXPECT_EQ(id, resultRstStreamFrame.streamId);
EXPECT_EQ(offset, resultRstStreamFrame.offset);
@@ -1255,7 +1247,7 @@ TEST_F(QuicWriteCodecTest, WriteBlockedFrame) {
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(bytesWritten, 5);
EXPECT_NO_THROW(boost::get<DataBlockedFrame>(regularPacket.frames[0]));
EXPECT_NE(regularPacket.frames[0].asDataBlockedFrame(), nullptr);
auto wireBuf = std::move(builtOut.second);
folly::io::Cursor cursor(wireBuf.get());
@@ -1279,13 +1271,13 @@ TEST_F(QuicWriteCodecTest, WriteStreamIdNeeded) {
setupCommonExpects(pktBuilder);
StreamId blockedStreamId = 0x211;
MaxStreamsFrame streamIdNeeded(blockedStreamId, true);
auto bytesWritten = writeFrame(streamIdNeeded, pktBuilder);
auto bytesWritten = writeFrame(QuicSimpleFrame(streamIdNeeded), pktBuilder);
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(bytesWritten, 3);
EXPECT_NO_THROW(boost::get<MaxStreamsFrame>(
boost::get<QuicSimpleFrame>(regularPacket.frames[0])));
*regularPacket.frames[0].asQuicSimpleFrame()));
auto wireBuf = std::move(builtOut.second);
folly::io::Cursor cursor(wireBuf.get());
@@ -1302,7 +1294,7 @@ TEST_F(QuicWriteCodecTest, NoSpaceForStreamIdNeeded) {
setupCommonExpects(pktBuilder);
StreamId blockedStreamId = 0x211;
MaxStreamsFrame streamIdNeeded(blockedStreamId, true);
EXPECT_EQ(0, writeFrame(streamIdNeeded, pktBuilder));
EXPECT_EQ(0, writeFrame(QuicSimpleFrame(streamIdNeeded), pktBuilder));
}
TEST_F(QuicWriteCodecTest, WriteNewConnId) {
@@ -1311,13 +1303,13 @@ TEST_F(QuicWriteCodecTest, WriteNewConnId) {
StatelessResetToken token;
memset(token.data(), 'a', token.size());
NewConnectionIdFrame newConnId(1, 0, getTestConnectionId(), token);
auto bytesWritten = writeFrame(newConnId, pktBuilder);
auto bytesWritten = writeFrame(QuicSimpleFrame(newConnId), pktBuilder);
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(bytesWritten, 28);
auto& resultNewConnIdFrame = boost::get<NewConnectionIdFrame>(
boost::get<QuicSimpleFrame>(regularPacket.frames[0]));
*regularPacket.frames[0].asQuicSimpleFrame());
EXPECT_EQ(resultNewConnIdFrame.sequenceNumber, 1);
EXPECT_EQ(resultNewConnIdFrame.retirePriorTo, 0);
EXPECT_EQ(resultNewConnIdFrame.connectionId, getTestConnectionId());
@@ -1338,13 +1330,13 @@ TEST_F(QuicWriteCodecTest, WriteRetireConnId) {
MockQuicPacketBuilder pktBuilder;
setupCommonExpects(pktBuilder);
RetireConnectionIdFrame retireConnId(3);
auto bytesWritten = writeFrame(retireConnId, pktBuilder);
auto bytesWritten = writeFrame(QuicSimpleFrame(retireConnId), pktBuilder);
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(bytesWritten, 2);
auto resultRetireConnIdFrame = boost::get<RetireConnectionIdFrame>(
boost::get<QuicSimpleFrame>(regularPacket.frames[0]));
*regularPacket.frames[0].asQuicSimpleFrame());
EXPECT_EQ(resultRetireConnIdFrame.sequenceNumber, 3);
auto wireBuf = std::move(builtOut.second);
@@ -1385,7 +1377,7 @@ TEST_F(QuicWriteCodecTest, NoSpaceForNewConnId) {
setupCommonExpects(pktBuilder);
NewConnectionIdFrame newConnId(
1, 0, getTestConnectionId(), StatelessResetToken());
EXPECT_EQ(0, writeFrame(newConnId, pktBuilder));
EXPECT_EQ(0, writeFrame(QuicSimpleFrame(newConnId), pktBuilder));
}
TEST_F(QuicWriteCodecTest, WriteExpiredStreamDataFrame) {
@@ -1394,13 +1386,14 @@ TEST_F(QuicWriteCodecTest, WriteExpiredStreamDataFrame) {
StreamId id = 10;
uint64_t offset = 0x08;
ExpiredStreamDataFrame expiredStreamDataFrame(id, offset);
auto bytesWritten = writeFrame(expiredStreamDataFrame, pktBuilder);
auto bytesWritten =
writeFrame(QuicSimpleFrame(expiredStreamDataFrame), pktBuilder);
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(bytesWritten, 4);
auto result = boost::get<ExpiredStreamDataFrame>(
boost::get<QuicSimpleFrame>(regularPacket.frames[0]));
*regularPacket.frames[0].asQuicSimpleFrame());
EXPECT_EQ(id, result.streamId);
EXPECT_EQ(offset, result.minimumStreamOffset);
@@ -1424,13 +1417,14 @@ TEST_F(QuicWriteCodecTest, WriteMinStreamDataFrame) {
uint64_t maximumData = 0x64;
uint64_t offset = 0x08;
MinStreamDataFrame minStreamDataFrame(id, maximumData, offset);
auto bytesWritten = writeFrame(minStreamDataFrame, pktBuilder);
auto bytesWritten =
writeFrame(QuicSimpleFrame(minStreamDataFrame), pktBuilder);
auto builtOut = std::move(pktBuilder).buildPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(bytesWritten, 6);
auto result = boost::get<MinStreamDataFrame>(
boost::get<QuicSimpleFrame>(regularPacket.frames[0]));
*regularPacket.frames[0].asQuicSimpleFrame());
EXPECT_EQ(id, result.streamId);
EXPECT_EQ(maximumData, result.maximumData);
EXPECT_EQ(offset, result.minimumStreamOffset);
@@ -1461,7 +1455,7 @@ TEST_F(QuicWriteCodecTest, WritePathChallenge) {
auto regularPacket = builtOut.first;
auto result = boost::get<PathChallengeFrame>(
boost::get<QuicSimpleFrame>(regularPacket.frames[0]));
*regularPacket.frames[0].asQuicSimpleFrame());
EXPECT_EQ(result.pathData, pathData);
auto wireBuf = std::move(builtOut.second);
@@ -1486,7 +1480,7 @@ TEST_F(QuicWriteCodecTest, WritePathResponse) {
auto regularPacket = builtOut.first;
auto result = boost::get<PathResponseFrame>(
boost::get<QuicSimpleFrame>(regularPacket.frames[0]));
*regularPacket.frames[0].asQuicSimpleFrame());
EXPECT_EQ(result.pathData, pathData);
auto wireBuf = std::move(builtOut.second);

View File

@@ -35,6 +35,11 @@ namespace quic {
new (&X##_) X(std::move(x)); \
}
#define UNION_COPY_CTORS(X, NAME) \
NAME(const X& x) : type_(Type::X##_E) { \
new (&X##_) X(x); \
}
#define UNION_MOVE_CASES(X, other) \
case Type::X##_E: \
new (&X##_) X(std::move(other.X##_)); \
@@ -56,6 +61,8 @@ namespace quic {
\
X(UNION_CTORS, NAME) \
\
X(UNION_COPY_CTORS, NAME) \
\
NAME(NAME&& other) { \
switch (other.type_) { X(UNION_MOVE_CASES, other) } \
type_ = other.type_; \

View File

@@ -70,8 +70,12 @@ PacketNum rstStreamAndSendPacket(
conn.transportSettings.writeConnectionDataPacketsLimit);
for (const auto& packet : conn.outstandingPackets) {
for (const auto& frame : all_frames<RstStreamFrame>(packet.packet.frames)) {
if (frame.streamId == stream.id) {
for (const auto& frame : packet.packet.frames) {
auto rstFrame = frame.asRstStreamFrame();
if (!rstFrame) {
continue;
}
if (rstFrame->streamId == stream.id) {
return packet.packet.header.getPacketSequenceNum();
}
}

View File

@@ -276,15 +276,14 @@ auto findFrameInPacketFunc() {
return [&](auto& p) {
return std::find_if(
p.packet.frames.begin(), p.packet.frames.end(), [&](auto& f) {
QuicSimpleFrame* simpleFrame = f.asQuicSimpleFrame();
if (!simpleFrame) {
return false;
}
return folly::variant_match(
f,
[&](QuicSimpleFrame& s) {
return folly::variant_match(
s,
*simpleFrame,
[&](FrameType&) { return true; },
[&](auto&) { return false; });
},
[&](auto&) { return false; });
}) != p.packet.frames.end();
};
}

View File

@@ -195,62 +195,88 @@ std::unique_ptr<QLogPacketEvent> QLogger::createPacketEvent(
uint64_t numPaddingFrames = 0;
// looping through the packet to store logs created from frames in the packet
for (const auto& quicFrame : writePacket.frames) {
folly::variant_match(
quicFrame,
[&](const PaddingFrame& /* unused */) { ++numPaddingFrames; },
[&](const RstStreamFrame& frame) {
switch (quicFrame.type()) {
case QuicWriteFrame::Type::PaddingFrame_E:
++numPaddingFrames;
break;
case QuicWriteFrame::Type::RstStreamFrame_E: {
const RstStreamFrame& frame = *quicFrame.asRstStreamFrame();
event->frames.push_back(std::make_unique<RstStreamFrameLog>(
frame.streamId, frame.errorCode, frame.offset));
},
[&](const ConnectionCloseFrame& frame) {
break;
}
case QuicWriteFrame::Type::ConnectionCloseFrame_E: {
const ConnectionCloseFrame& frame = *quicFrame.asConnectionCloseFrame();
event->frames.push_back(std::make_unique<ConnectionCloseFrameLog>(
frame.errorCode, frame.reasonPhrase, frame.closingFrameType));
},
[&](const ApplicationCloseFrame& frame) {
break;
}
case QuicWriteFrame::Type::ApplicationCloseFrame_E: {
const ApplicationCloseFrame& frame =
*quicFrame.asApplicationCloseFrame();
event->frames.push_back(std::make_unique<ApplicationCloseFrameLog>(
frame.errorCode, frame.reasonPhrase));
},
[&](const MaxDataFrame& frame) {
break;
}
case QuicWriteFrame::Type::MaxDataFrame_E: {
const MaxDataFrame& frame = *quicFrame.asMaxDataFrame();
event->frames.push_back(
std::make_unique<MaxDataFrameLog>(frame.maximumData));
},
[&](const MaxStreamDataFrame& frame) {
break;
}
case QuicWriteFrame::Type::MaxStreamDataFrame_E: {
const MaxStreamDataFrame& frame = *quicFrame.asMaxStreamDataFrame();
event->frames.push_back(std::make_unique<MaxStreamDataFrameLog>(
frame.streamId, frame.maximumData));
},
[&](const StreamsBlockedFrame& frame) {
break;
}
case QuicWriteFrame::Type::StreamsBlockedFrame_E: {
const StreamsBlockedFrame& frame = *quicFrame.asStreamsBlockedFrame();
event->frames.push_back(std::make_unique<StreamsBlockedFrameLog>(
frame.streamLimit, frame.isForBidirectional));
},
[&](const PingFrame& /* unused */) {
break;
}
case QuicWriteFrame::Type::PingFrame_E:
event->frames.push_back(std::make_unique<PingFrameLog>());
},
[&](const DataBlockedFrame& frame) {
break;
case QuicWriteFrame::Type::DataBlockedFrame_E: {
const DataBlockedFrame& frame = *quicFrame.asDataBlockedFrame();
event->frames.push_back(
std::make_unique<DataBlockedFrameLog>(frame.dataLimit));
},
[&](const StreamDataBlockedFrame& frame) {
break;
}
case QuicWriteFrame::Type::StreamDataBlockedFrame_E: {
const StreamDataBlockedFrame& frame = *quicFrame.asStreamDataBlockedFrame();
event->frames.push_back(std::make_unique<StreamDataBlockedFrameLog>(
frame.streamId, frame.dataLimit));
},
[&](const WriteAckFrame& frame) {
break;
}
case QuicWriteFrame::Type::WriteAckFrame_E: {
const WriteAckFrame& frame = *quicFrame.asWriteAckFrame();
event->frames.push_back(std::make_unique<WriteAckFrameLog>(
frame.ackBlocks, frame.ackDelay));
},
[&](const WriteStreamFrame& frame) {
break;
}
case QuicWriteFrame::Type::WriteStreamFrame_E: {
const WriteStreamFrame& frame = *quicFrame.asWriteStreamFrame();
event->frames.push_back(std::make_unique<StreamFrameLog>(
frame.streamId, frame.offset, frame.len, frame.fin));
},
[&](const WriteCryptoFrame& frame) {
break;
}
case QuicWriteFrame::Type::WriteCryptoFrame_E: {
const WriteCryptoFrame& frame = *quicFrame.asWriteCryptoFrame();
event->frames.push_back(
std::make_unique<CryptoFrameLog>(frame.offset, frame.len));
},
[&](const QuicSimpleFrame& simpleFrame) {
break;
}
case QuicWriteFrame::Type::QuicSimpleFrame_E: {
const QuicSimpleFrame& simpleFrame = *quicFrame.asQuicSimpleFrame();
addQuicSimpleFrameToEvent(event.get(), simpleFrame);
},
[&](const auto& /* unused */) {
// Ignore other frames.
});
break;
}
default:
break;
}
}
if (numPaddingFrames > 0) {
event->frames.push_back(

View File

@@ -57,9 +57,9 @@ void markPacketLoss(
bool processed,
PacketNum currentPacketNum) {
for (auto& packetFrame : packet.frames) {
folly::variant_match(
packetFrame,
[&](MaxStreamDataFrame& frame) {
switch (packetFrame.type()) {
case QuicWriteFrame::Type::MaxStreamDataFrame_E: {
MaxStreamDataFrame& frame = *packetFrame.asMaxStreamDataFrame();
// For all other frames, we process it if it's not from a clone
// packet, or if the clone and its siblings have never been processed.
// But for both MaxData and MaxStreamData, clone and its siblings may
@@ -69,28 +69,31 @@ void markPacketLoss(
// since newer value is already sent in later packets.
auto stream = conn.streamManager->getStream(frame.streamId);
if (!stream) {
return;
break;
}
// TODO: check for the stream is in Open or HalfClosedLocal state, the
// peer doesn't need a flow control update in these cases.
if (stream->latestMaxStreamDataPacket == currentPacketNum) {
onStreamWindowUpdateLost(*stream);
}
},
[&](MaxDataFrame&) {
break;
}
case QuicWriteFrame::Type::MaxDataFrame_E: {
if (conn.latestMaxDataPacket == currentPacketNum) {
onConnWindowUpdateLost(conn);
}
},
break;
}
// For other frame types, we only process them if the packet is not a
// processed clone.
[&](WriteStreamFrame& frame) {
case QuicWriteFrame::Type::WriteStreamFrame_E: {
WriteStreamFrame frame = *packetFrame.asWriteStreamFrame();
if (processed) {
return;
break;
}
auto stream = conn.streamManager->getStream(frame.streamId);
if (!stream) {
return;
break;
}
auto bufferItr = std::lower_bound(
stream->retransmissionBuffer.begin(),
@@ -103,12 +106,12 @@ void markPacketLoss(
// It's possible that the stream was reset or data on the stream was
// skipped while we discovered that its packet was lost so we might
// not have the offset.
return;
break;
}
// The original rxmt offset might have been bumped up after it was
// shrunk due to egress partially reliable skip.
if (!ackFrameMatchesRetransmitBuffer(*stream, frame, *bufferItr)) {
return;
break;
}
stream->lossBuffer.insert(
std::upper_bound(
@@ -121,16 +124,16 @@ void markPacketLoss(
std::move(*bufferItr));
stream->retransmissionBuffer.erase(bufferItr);
conn.streamManager->updateLossStreams(*stream);
},
[&](WriteCryptoFrame& frame) {
break;
}
case QuicWriteFrame::Type::WriteCryptoFrame_E: {
WriteCryptoFrame& frame = *packetFrame.asWriteCryptoFrame();
if (processed) {
return;
break;
}
auto protectionType = packet.header.getProtectionType();
auto encryptionLevel =
protectionTypeToEncryptionLevel(protectionType);
auto cryptoStream =
getCryptoStream(*conn.cryptoState, encryptionLevel);
auto encryptionLevel = protectionTypeToEncryptionLevel(protectionType);
auto cryptoStream = getCryptoStream(*conn.cryptoState, encryptionLevel);
auto bufferItr = std::lower_bound(
cryptoStream->retransmissionBuffer.begin(),
@@ -142,7 +145,7 @@ void markPacketLoss(
if (bufferItr == cryptoStream->retransmissionBuffer.end()) {
// It's possible that the stream was reset while we discovered that
// it's packet was lost so we might not have the offset.
return;
break;
}
DCHECK_EQ(bufferItr->offset, frame.offset);
cryptoStream->lossBuffer.insert(
@@ -155,40 +158,48 @@ void markPacketLoss(
}),
std::move(*bufferItr));
cryptoStream->retransmissionBuffer.erase(bufferItr);
},
[&](RstStreamFrame& frame) {
break;
}
case QuicWriteFrame::Type::RstStreamFrame_E: {
RstStreamFrame& frame = *packetFrame.asRstStreamFrame();
if (processed) {
return;
break;
}
auto stream = conn.streamManager->getStream(frame.streamId);
if (!stream) {
// If the stream is dead, ignore the retransmissions of the rst
// stream.
return;
break;
}
// Add the lost RstStreamFrame back to pendingEvents:
conn.pendingEvents.resets.insert({frame.streamId, frame});
},
[&](StreamDataBlockedFrame& frame) {
break;
}
case QuicWriteFrame::Type::StreamDataBlockedFrame_E: {
StreamDataBlockedFrame& frame = *packetFrame.asStreamDataBlockedFrame();
if (processed) {
return;
break;
}
auto stream = conn.streamManager->getStream(frame.streamId);
// TODO: check for retransmittable
if (!stream) {
return;
break;
}
onBlockedLost(*stream);
},
[&](QuicSimpleFrame& frame) {
break;
}
case QuicWriteFrame::Type::QuicSimpleFrame_E: {
QuicSimpleFrame& frame = *packetFrame.asQuicSimpleFrame();
if (processed) {
return;
break;
}
updateSimpleFrameOnPacketLoss(conn, frame);
},
[&](auto&) {
break;
}
default:
// ignore the rest of the frames.
});
break;
}
}
}
} // namespace quic

View File

@@ -696,10 +696,14 @@ TEST_F(QuicLossFunctionsTest, TestMarkRstLoss) {
auto& packet2 =
getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet;
bool rstFound = false;
for (auto& frame : all_frames<RstStreamFrame>(packet2.frames)) {
EXPECT_EQ(stream->id, frame.streamId);
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, frame.errorCode);
EXPECT_EQ(currentOffset, frame.offset);
for (auto& frame : packet2.frames) {
auto resetFrame = frame.asRstStreamFrame();
if (!resetFrame) {
continue;
}
EXPECT_EQ(stream->id, resetFrame->streamId);
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, resetFrame->errorCode);
EXPECT_EQ(currentOffset, resetFrame->offset);
rstFound = true;
}
EXPECT_TRUE(rstFound);
@@ -1235,12 +1239,19 @@ TEST_F(QuicLossFunctionsTest, TestMarkPacketLossProcessedPacket) {
for (const auto& frame :
getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)
->packet.frames) {
folly::variant_match(
frame,
[&](const WriteStreamFrame&) { streamDataCounter++; },
[&](const MaxStreamDataFrame&) { streamWindowUpdateCounter++; },
[&](const MaxDataFrame&) { connWindowUpdateCounter++; },
[](const auto&) { ASSERT_TRUE(false); });
switch (frame.type()) {
case QuicWriteFrame::Type::WriteStreamFrame_E:
streamDataCounter++;
break;
case QuicWriteFrame::Type::MaxStreamDataFrame_E:
streamWindowUpdateCounter++;
break;
case QuicWriteFrame::Type::MaxDataFrame_E:
connWindowUpdateCounter++;
break;
default:
CHECK(false) << "unexpected frame=" << (int)frame.type();
}
}
EXPECT_EQ(1, streamDataCounter);
EXPECT_EQ(1, streamWindowUpdateCounter);

View File

@@ -756,9 +756,10 @@ void onServerReadDataFromOpen(
[&](const OutstandingPacket&,
const QuicWriteFrame& packetFrame,
const ReadAckFrame&) {
folly::variant_match(
packetFrame,
[&](const WriteStreamFrame& frame) {
switch (packetFrame.type()) {
case QuicWriteFrame::Type::WriteStreamFrame_E: {
const WriteStreamFrame& frame =
*packetFrame.asWriteStreamFrame();
VLOG(4)
<< "Server received ack for stream=" << frame.streamId
<< " offset=" << frame.offset << " fin=" << frame.fin
@@ -771,32 +772,40 @@ void onServerReadDataFromOpen(
*ackedStream,
StreamEvents::AckStreamFrame(frame));
}
},
[&](const WriteCryptoFrame& frame) {
break;
}
case QuicWriteFrame::Type::WriteCryptoFrame_E: {
const WriteCryptoFrame& frame =
*packetFrame.asWriteCryptoFrame();
auto cryptoStream =
getCryptoStream(*conn.cryptoState, encryptionLevel);
processCryptoStreamAck(
*cryptoStream, frame.offset, frame.len);
},
[&](const RstStreamFrame& frame) {
break;
}
case QuicWriteFrame::Type::RstStreamFrame_E: {
const RstStreamFrame& frame = *packetFrame.asRstStreamFrame();
VLOG(4) << "Server received ack for reset stream="
<< frame.streamId << " " << conn;
auto stream =
conn.streamManager->getStream(frame.streamId);
auto stream = conn.streamManager->getStream(frame.streamId);
if (stream) {
invokeStreamSendStateMachine(
conn, *stream, StreamEvents::RstAck(frame));
}
},
[&](const WriteAckFrame& frame) {
break;
}
case QuicWriteFrame::Type::WriteAckFrame_E: {
const WriteAckFrame& frame = *packetFrame.asWriteAckFrame();
DCHECK(!frame.ackBlocks.empty());
VLOG(4) << "Server received ack for largestAcked="
<< frame.ackBlocks.back().end << " " << conn;
commonAckVisitorForAckFrame(ackState, frame);
},
[&](const auto& /*frame*/) {
// Ignore other frames.
});
break;
}
default: {
break;
}
}
},
markPacketLoss,
readData.networkData.receiveTimePoint);

View File

@@ -1116,7 +1116,7 @@ TEST_F(QuicServerTransportTest, TestOpenAckStreamFrame) {
PacketNum currentPacket = packet.packet.header.getPacketSequenceNum();
ASSERT_FALSE(packet.packet.frames.empty());
for (auto& quicFrame : packet.packet.frames) {
auto frame = boost::get<WriteStreamFrame>(&quicFrame);
auto frame = quicFrame.asWriteStreamFrame();
if (!frame) {
continue;
}
@@ -1374,7 +1374,7 @@ TEST_F(QuicServerTransportTest, RecvStopSendingFrame) {
StopSendingFrame stopSendingFrame(
streamId, GenericApplicationErrorCode::UNKNOWN);
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(std::move(stopSendingFrame), builder);
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
auto packet = std::move(builder).buildPacket();
EXPECT_CALL(
connCallback,
@@ -1416,7 +1416,7 @@ TEST_F(QuicServerTransportTest, RecvStopSendingFrameAfterCloseStream) {
StopSendingFrame stopSendingFrame(
streamId, GenericApplicationErrorCode::UNKNOWN);
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(std::move(stopSendingFrame), builder);
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
auto packet = std::move(builder).buildPacket();
server->resetStream(streamId, GenericApplicationErrorCode::UNKNOWN);
EXPECT_CALL(connCallback, onStopSending(_, _)).Times(0);
@@ -1499,7 +1499,7 @@ TEST_F(QuicServerTransportTest, RecvStopSendingFrameAfterHalfCloseRemote) {
builder, 0x00, stream->currentReadOffset, 0, 10, true);
ASSERT_TRUE(dataLen.hasValue());
ASSERT_EQ(*dataLen, 0);
writeFrame(std::move(stopSendingFrame), builder);
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
auto packet = std::move(builder).buildPacket();
EXPECT_CALL(
connCallback,
@@ -1523,7 +1523,7 @@ TEST_F(QuicServerTransportTest, RecvStopSendingBeforeStream) {
StopSendingFrame stopSendingFrame(
streamId, GenericApplicationErrorCode::UNKNOWN);
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(std::move(stopSendingFrame), builder);
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
auto packet = std::move(builder).buildPacket();
EXPECT_CALL(connCallback, onNewBidirectionalStream(streamId));
EXPECT_CALL(
@@ -1578,8 +1578,8 @@ TEST_F(QuicServerTransportTest, RecvStopSendingFrameAfterReset) {
StopSendingFrame stopSendingFrame2(
streamId2, GenericApplicationErrorCode::UNKNOWN);
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(std::move(stopSendingFrame1), builder);
writeFrame(std::move(stopSendingFrame2), builder);
writeFrame(QuicSimpleFrame(stopSendingFrame1), builder);
writeFrame(QuicSimpleFrame(stopSendingFrame2), builder);
auto packet = std::move(builder).buildPacket();
EXPECT_CALL(
connCallback, onStopSending(_, GenericApplicationErrorCode::UNKNOWN))
@@ -1605,7 +1605,7 @@ TEST_F(QuicServerTransportTest, StopSendingLoss) {
StopSendingFrame stopSendingFrame(
streamId, GenericApplicationErrorCode::UNKNOWN);
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(stopSendingFrame, builder);
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
auto packet = std::move(builder).buildPacket();
markPacketLoss(
server->getNonConstConn(),
@@ -1635,7 +1635,7 @@ TEST_F(QuicServerTransportTest, StopSendingLossAfterStreamClosed) {
StopSendingFrame stopSendingFrame(
streamId, GenericApplicationErrorCode::UNKNOWN);
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(stopSendingFrame, builder);
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
auto packet = std::move(builder).buildPacket();
// clear out all the streams, this is not a great way to simulate closed

View File

@@ -205,9 +205,10 @@ TEST_F(QuicOpenStateTest, AckStream) {
EXPECT_EQ(stream->retransmissionBuffer.size(), 1);
EXPECT_EQ(1, conn->outstandingPackets.size());
auto& streamFrame = boost::get<WriteStreamFrame>(
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
->packet.frames.front());
auto& streamFrame =
*getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
->packet.frames.front()
.asWriteStreamFrame();
StreamEvents::AckStreamFrame ack(streamFrame);
invokeHandler<StreamSendStateMachine>(stream->send, ack, *stream);
@@ -256,8 +257,9 @@ TEST_F(QuicOpenStateTest, RetxBufferSortedAfterAck) {
EXPECT_EQ(3, stream->retransmissionBuffer.size());
EXPECT_EQ(3, conn->outstandingPackets.size());
auto packet = conn->outstandingPackets[folly::Random::rand32() % 3];
auto streamFrame = boost::get<WriteStreamFrame>(
conn->outstandingPackets[std::rand() % 3].packet.frames.front());
auto streamFrame = *conn->outstandingPackets[std::rand() % 3]
.packet.frames.front()
.asWriteStreamFrame();
StreamEvents::AckStreamFrame ack(streamFrame);
invokeHandler<StreamSendStateMachine>(stream->send, ack, *stream);
EXPECT_EQ(2, stream->retransmissionBuffer.size());
@@ -289,9 +291,10 @@ TEST_F(QuicOpenStateTest, AckStreamAfterSkip) {
EXPECT_EQ(stream->retransmissionBuffer.size(), 1);
EXPECT_EQ(1, conn->outstandingPackets.size());
auto& streamFrame = boost::get<WriteStreamFrame>(
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
->packet.frames.front());
auto& streamFrame =
*getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
->packet.frames.front()
.asWriteStreamFrame();
PacketNum packetNum(1);
MinStreamDataFrame minDataFrame(stream->id, 1000, 100);
@@ -333,9 +336,10 @@ TEST_F(QuicOpenStateTest, AckStreamAfterSkipHalfBuf) {
EXPECT_EQ(stream->retransmissionBuffer.size(), 1);
EXPECT_EQ(1, conn->outstandingPackets.size());
auto& streamFrame = boost::get<WriteStreamFrame>(
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
->packet.frames.front());
auto& streamFrame =
*getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
->packet.frames.front()
.asWriteStreamFrame();
PacketNum packetNum(1);
// Skip ~0.5 buffers.
@@ -387,11 +391,11 @@ TEST_F(QuicOpenStateTest, AckStreamAfterSkipOneAndAHalfBuf) {
auto streamFrameIt =
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData);
auto& streamFrame1 =
boost::get<WriteStreamFrame>(streamFrameIt->packet.frames.front());
auto& streamFrame2 = boost::get<WriteStreamFrame>(
getNextOutstandingPacket(
*streamFrameIt->packet.frames.front().asWriteStreamFrame();
auto& streamFrame2 = *getNextOutstandingPacket(
*conn, PacketNumberSpace::AppData, ++streamFrameIt)
->packet.frames.front());
->packet.frames.front()
.asWriteStreamFrame();
PacketNum packetNum(1);
// Skip ~1.5 buffers.
@@ -502,9 +506,10 @@ TEST_F(QuicHalfClosedRemoteStateTest, AckStream) {
EXPECT_EQ(stream->retransmissionBuffer.size(), 1);
EXPECT_EQ(1, conn->outstandingPackets.size());
auto& streamFrame = boost::get<WriteStreamFrame>(
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
->packet.frames.front());
auto& streamFrame =
*getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
->packet.frames.front()
.asWriteStreamFrame();
StreamEvents::AckStreamFrame ack(streamFrame);
invokeHandler<StreamSendStateMachine>(stream->send, ack, *stream);
@@ -541,9 +546,10 @@ TEST_F(QuicHalfClosedRemoteStateTest, AckStreamAfterSkip) {
EXPECT_EQ(stream->retransmissionBuffer.size(), 1);
EXPECT_EQ(1, conn->outstandingPackets.size());
auto& streamFrame = boost::get<WriteStreamFrame>(
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
->packet.frames.front());
auto& streamFrame =
*getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
->packet.frames.front()
.asWriteStreamFrame();
PacketNum packetNum(1);
MinStreamDataFrame minDataFrame(stream->id, 1000, 100);

View File

@@ -81,7 +81,7 @@ TEST_P(AckHandlersTest, TestAckMultipleSequentialBlocks) {
GetParam(),
ackFrame,
[&](const auto&, const auto& packetFrame, const ReadAckFrame&) {
auto& stream = boost::get<WriteStreamFrame>(packetFrame);
auto& stream = *packetFrame.asWriteStreamFrame();
streams.emplace_back(stream);
},
testLossHandler(lostPackets),
@@ -152,7 +152,7 @@ TEST_P(AckHandlersTest, TestAckBlocksWithGaps) {
GetParam(),
ackFrame,
[&](const auto&, const auto& packetFrame, const ReadAckFrame&) {
auto& stream = boost::get<WriteStreamFrame>(packetFrame);
auto& stream = *packetFrame.asWriteStreamFrame();
streams.emplace_back(stream);
},
testLossHandler(lostPackets),
@@ -259,7 +259,7 @@ TEST_P(AckHandlersTest, TestNonSequentialPacketNumbers) {
GetParam(),
ackFrame,
[&](const auto&, const auto& packetFrame, const ReadAckFrame&) {
auto& stream = boost::get<WriteStreamFrame>(packetFrame);
auto& stream = *packetFrame.asWriteStreamFrame();
streams.emplace_back(stream);
},
testLossHandler(lostPackets),
@@ -337,15 +337,10 @@ TEST_P(AckHandlersTest, AckVisitorForAckTest) {
auto ackedPacketNum =
outstandingPacket.packet.header.getPacketSequenceNum();
EXPECT_EQ(ackedPacketNum, firstReceivedAck.largestAcked);
folly::variant_match(
packetFrame,
[&](const WriteAckFrame& frame) {
commonAckVisitorForAckFrame(
conn.ackStates.appDataAckState, frame);
},
[&](const auto& /* frame */) {
// Ignore other frames.
});
const WriteAckFrame* frame = packetFrame.asWriteAckFrame();
if (frame) {
commonAckVisitorForAckFrame(conn.ackStates.appDataAckState, *frame);
}
},
[](auto& /* conn */,
auto& /* packet */,
@@ -368,15 +363,10 @@ TEST_P(AckHandlersTest, AckVisitorForAckTest) {
GetParam(),
secondReceivedAck,
[&](const auto&, const auto& packetFrame, const ReadAckFrame&) {
folly::variant_match(
packetFrame,
[&](const WriteAckFrame& frame) {
commonAckVisitorForAckFrame(
conn.ackStates.appDataAckState, frame);
},
[&](const auto& /* frame */) {
// Ignore other frames.
});
const WriteAckFrame* frame = packetFrame.asWriteAckFrame();
if (frame) {
commonAckVisitorForAckFrame(conn.ackStates.appDataAckState, *frame);
}
},
[](auto& /* conn */,
auto& /* packet */,