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:
committed by
Facebook Github Bot
parent
233346268e
commit
68c332acb1
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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(
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
|
@@ -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));
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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_; \
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -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();
|
||||
};
|
||||
}
|
||||
|
@@ -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(
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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 */,
|
||||
|
Reference in New Issue
Block a user